diff --git a/CMakeLists.txt b/CMakeLists.txt index bb93ecfce..b8da93823 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ file(GLOB GPUMD_SOURCES src/minimize/*.cu src/phonon/*.cu src/integrate/*.cu + src/integrate/spin/*.cu src/mc/*.cu src/force/*.cu src/force/*/*.cu @@ -30,7 +31,7 @@ file(GLOB GPUMD_SOURCES src/utilities/*.cu) add_executable(gpumd ${GPUMD_SOURCES}) target_include_directories(gpumd PRIVATE src) -target_link_libraries(gpumd PRIVATE CUDA::cublas CUDA::cusolver CUDA::cufft) +target_link_libraries(gpumd PRIVATE CUDA::cublas CUDA::cusolver CUDA::cufft Threads::Threads) # --- nep --- file(GLOB NEP_SOURCES diff --git a/developer/README.md b/developer/README.md index e7710df2f..0c58c49f6 100644 --- a/developer/README.md +++ b/developer/README.md @@ -52,7 +52,12 @@ The main source directories are: | `src/utilities/` | Shared utilities, GPU wrappers, input helpers, and containers | | `src/main_nep/` | `nep` executable | -Files added under an existing source directory are normally collected automatically by the makefiles. For `nep`, the CUDA and HIP makefiles also collect `.cu` files one directory below `src/main_nep/`. +Files added under an existing source directory are normally collected automatically by the makefiles. The CUDA and HIP makefiles also collect `.cu` files one directory below `src/force/` for `gpumd`, and `src/main_nep/` for `nep`. + +Spin inference, multi-GPU evaluation, external magnetic fields, and Spin-specific +small-box kernels live in `src/force/nep_spin/`. Training in +`src/main_nep/nep_spin/` includes the same magnetic descriptor and force headers; +ordinary NEP keeps its own small-box kernels in `src/force/nep_small_box.cuh`. ## 3. Main `gpumd` architecture @@ -199,6 +204,7 @@ The `nep` executable is implemented under `src/main_nep/` and shares utilities w | Top level | Entry point, model selection, optimizer, scheduling, and shared data structures | | `common/` | Reusable NEP parameter, data, loss, I/O, and runtime-compilation helpers | | `nep/` | Ordinary and temperature-dependent NEP | +| `nep_spin/` | Spin3 parameters, magnetic labels/neighbors, response supervision, and model I/O | | `nep_charge/` | NEP charge modes 1 and 2 | | `nep_vdw/` | NEP with long-range dispersion | | `nep_charge_vdw/` | NEP with charge and dispersion | @@ -233,6 +239,16 @@ Shared structure and dataset code handles common data. Model-specific labels, GP `evaluate()` receives contiguous candidate parameter vectors on the host. The model owns intermediate losses; `accumulate_fitness()` adds their contributions after common regularization. Keep model-specific reduction and transfer decisions behind these interfaces, so later GPU reduction or population parallelism does not require model branches in `Fitness` or `SNES`. +Spin3 keeps `Structure` and `Dataset` unchanged and stores magnetic labels and device +buffers in `Spin_Data`, indexed by `NEP_Batch_Data`. Labels are matched through +`Structure::index_in_file` after batch sorting or energy-difference grouping. +Its reader supplies the largest structural/magnetic cutoff to the shared geometry +reader. `response.xyz` has separate device data and contributes only response loss; +it does not fit the energy reference or scalers. Spin3 uses the shared +`energy_reference` and block model/restart formats while preserving its +fixed-reference scaler and the common generation-zero lifecycle. Legacy Spin3 +model and two-column restart files remain readable. + ### Adding a training model 1. Implement the `Potential` interface in the model's subdirectory, with its parameter parsing, labels, workspaces, losses, and output handling. @@ -261,3 +277,17 @@ The basic internal units are: - charge: elementary charge User-facing changes to keywords, file formats, units, or physical definitions should be reflected in the documentation under `doc/`. + +Spin moments are in muB and magnetic forces in eV/muB. See the +[model input units](../doc/gpumd/input_files/model_xyz.rst) and +[external magnetic field](../doc/gpumd/input_parameters/add_mfield.rst) +documentation for the input and Zeeman conventions. + +See [Spin regression checks](spin_validation.md) for portable format, training, +and GPU validation commands. + +Spin lattice coupling and restart handling live in `src/integrate/spin/`. +`Spin_Lattice_NHC` and `Spin_Lattice_MTTK` reuse the upstream mechanical +integrators and add endpoint persistence and resumed temperature/pressure +protocols only for Spin ensembles. Ordinary NHC/MTTK classes remain unchanged. +The XYZ reader and restart writer delegate Spin metadata to this directory. diff --git a/developer/spin_validation.md b/developer/spin_validation.md new file mode 100644 index 000000000..ca4254b63 --- /dev/null +++ b/developer/spin_validation.md @@ -0,0 +1,32 @@ +# Spin regression checks + +Build on the target GPU with its CUDA architecture, for example: + +```sh +make -C src -j8 CUDA_ARCH=-arch=sm_70 gpumd nep +``` + +Use Python with NumPy and pytest. Set RESULTS to a new directory outside the +checkout. Multi-GPU checks require four allocated GPUs visible through +CUDA_VISIBLE_DEVICES. GPUMD_COMMAND selects the runtime binary; otherwise tests +use src/gpumd. Keep the frozen model/oracle values independent of the candidate. + +```sh +python -m pytest --noconftest -q tests_pytest/test_spin_model_format.py +python tests_pytest/validate_main_nep_spin3_training.py +python tests_pytest/validate_spin_training_lifecycle.py +python tests_pytest/validate_spin_training_multigpu.py --output "$RESULTS/training" +python tests_pytest/validate_nep_spin3_runtime.py +python tests_pytest/validate_nep_spin3_runtime.py --block-format +python tests_pytest/validate_spin_multigpu.py --binary src/gpumd --model tests_pytest/fixtures/nep_spin3/nep4_spin3_o3c2_uniform.nep --block-format --output "$RESULTS/runtime" +python -m pytest --noconftest -q tests_pytest/test_spin_tspin.py tests_pytest/test_spin_lattice_restart.py +``` + +Training checks cover five representative layouts, actual energy errors, +magnetic loss components, model IO and restart. Flexible ZBL is rejected; +universal ZBL remains supported. The CPU model codec is checked with strict +C++14 compilation. Build the focused probes with `-std=c++14` as well. +Initialization checks share `restart_parity.cu`; torque and response edge +cases share `spin_mforce_split.cu` and `response_fitness.cu`. + +Use `-m "not slow"` for routine pytest and `-m slow` for extended statistics. diff --git a/doc/gpumd/input_files/model_xyz.rst b/doc/gpumd/input_files/model_xyz.rst index b918e4b1a..a50d5bc2d 100644 --- a/doc/gpumd/input_files/model_xyz.rst +++ b/doc/gpumd/input_files/model_xyz.rst @@ -51,6 +51,8 @@ Essentially any keyword is allowed, but we only read the following ones: * ``mass:R:1`` mass (*Optional*: default mass values will be used when this is missing) * ``charge:R:1`` charge (*Optional*: default charge is zero) * ``vel:R:3`` velocity vector (*Optional*) + * ``spin:R:3`` magnetic-moment vector in Bohr magnetons (muB) (*Required for NEP_Spin*) + * ``spin_vel:R:3`` spin velocity vector (*Optional; requires ``spin:R:3``*) * ``group:I:number_of_grouping_methods`` grouping methods (*Optional*) @@ -67,6 +69,15 @@ The mass should be given in units of the unified atomic mass unit (amu). The charge is in units of e (proton charge). The cell dimensions and atom coordinates should be given in units of Ångstrom. Velocities need to be specified in units of Å/fs. +Spin is specified in Bohr magnetons (muB). Spin velocity is in muB/fs. +Magnetic force is the negative energy derivative with respect to spin, in eV/muB. +The spin torque, spin crossed with magnetic force, is in eV. +External magnetic induction B is specified in tesla (T). +Spin vectors store Cartesian magnetic moments, not normalized directions. +Readers do not normalize them or rescale model parameters; training and +runtime data must use the same spin convention. +Property names may not be repeated. NEP_Spin fails if ``spin:R:3`` is absent; +missing spin values are never filled with zeros. Example ------- diff --git a/doc/gpumd/input_files/run_in.rst b/doc/gpumd/input_files/run_in.rst index e9c414719..6cf082939 100644 --- a/doc/gpumd/input_files/run_in.rst +++ b/doc/gpumd/input_files/run_in.rst @@ -101,6 +101,10 @@ Simulation setup - Apply an electric field to selected atoms - No - No + * - :ref:`add_mfield ` + - Apply a magnetic field to an atom group or fractional region + - No + - Yes * - :ref:`add_spring ` - Add spring interactions to selected atom groups - No diff --git a/doc/gpumd/input_parameters/add_mfield.rst b/doc/gpumd/input_parameters/add_mfield.rst new file mode 100644 index 000000000..814f4f702 --- /dev/null +++ b/doc/gpumd/input_parameters/add_mfield.rst @@ -0,0 +1,58 @@ +.. _kw_add_mfield: + +:attr:`add_mfield` +================== + +Apply a constant external magnetic induction to an atom group or a fractional-coordinate region:: + + add_mfield + add_mfield region + +Grouping method and group ID select an existing model.xyz group, as in +add_efield. The three finite field components are in tesla (T). There is no +separate magnitude or direction normalization. For a 10 T field along z:: + + add_mfield 0 0 0 0 10 + +Group selection follows atom identities even when atoms move. Region selection +instead follows current fractional coordinates along cell vectors a, b, and c, +using the same coordinate conversion and membership test as heat_lan. +Bounds must be finite, in [0, 1], and satisfy min < max. Intervals are half-open: +[min, max). The region scales and tilts with the current cell, including under +NPT. Coordinates are evaluated after normal periodic boundary wrapping; there +is no extra wrapping in nonperiodic directions. No group labels are needed for +region mode. + +For a 10 T field along z in the first half of the cell along a:: + + add_mfield region 0 0.5 0 1 0 1 0 0 10 + +Membership is recomputed on every force evaluation: atoms entering the region +receive the field, and atoms leaving it no longer do. The sharp boundary gives +a discontinuous Zeeman energy. No mechanical boundary impulse is implemented; +energy conservation is not guaranteed for atoms crossing this boundary. This +is a local magnetic drive, not a smooth conservative gradient-field model. + +A Spin potential and spin:R:3 are required for a nonzero field. The field acts +on all selected magnetic moments, independently of the model spin_dof_type +response mask. It does not impose an integration constraint. + +Each command replaces the previous field and group/region selection. The setting +persists across run commands. To turn it off:: + + add_mfield 0 0 0 0 0 + +Spin is in muB, magnetic force is in eV/muB, and energy is in eV. With +c_B = 5.7883818060e-5, the added magnetic force is c_B times the field vector; +the added per-atom Zeeman energy is minus spin dotted with this force. +Both contributions are recomputed at every force evaluation using the actual +stored moments and do not accumulate across evaluations. +Output energies and magnetic forces include these contributions. +No additional g factor is applied. There is no direct mechanical force or +virial contribution. Time-dependent fields and linear gradients are not supported. + +The field is magnetic induction B, not H in A/m. The integrators consume +magnetic force in eV/muB, so tesla-valued inputs must undergo this conversion +before integration; the conversion does not change their gamma convention. +For example, a 2 muB moment aligned with 1 T has Zeeman energy approximately +-1.1576e-4 eV and magnetic force +5.7884e-5 eV/muB along the field. diff --git a/doc/gpumd/input_parameters/dump_restart.rst b/doc/gpumd/input_parameters/dump_restart.rst index 80242bc36..292d28899 100644 --- a/doc/gpumd/input_parameters/dump_restart.rst +++ b/doc/gpumd/input_parameters/dump_restart.rst @@ -28,3 +28,19 @@ Caveats ------- This keyword is not propagating. That means, its effect will not be passed from one run to the next. + +Spin lattice checkpoints +------------------------ + +Spin NVT/NPT runs save the atomic thermostat/barostat state and original ramp +phase as paired ``nhc_state``/``nhc_time`` or ``mttk_state``/``mttk_time`` fields. +Copy ``restart.xyz`` to ``model.xyz`` and retain the potential, atom order, +timestep, temperature/pressure endpoints and ensemble parameters. Do not +regenerate velocities. The original ramp continues and holds its final target +beyond its saved length. Mismatched configurations are rejected; selecting a +different lattice driver discards pending state. ``lattice off`` has no lattice +thermostat checkpoint. Ordinary NHC/MTTK ensembles retain upstream behavior. + +This preserves the lattice bath, not every extended variable or random stream +of the spin integrator. TSPIN's spin thermostat state is not checkpointed. +Other stateful modifiers and analysis histories are outside this contract. diff --git a/doc/gpumd/input_parameters/dump_xyz.rst b/doc/gpumd/input_parameters/dump_xyz.rst index 9ea577336..00f93aa65 100644 --- a/doc/gpumd/input_parameters/dump_xyz.rst +++ b/doc/gpumd/input_parameters/dump_xyz.rst @@ -29,7 +29,7 @@ If it is omitted, data for the whole system will be output. :attr:`single` (the default) writes nine significant digits, which is enough to recover a single-precision value exactly. :attr:`double` writes 17 significant digits, which is enough to recover a double-precision value exactly. -* Then one can write the properties to be output, and the allowed properties include: :attr:`mass`, :attr:`velocity`, :attr:`force`, :attr:`potential`, :attr:`virial`, :attr:`charge`, :attr:`bec`, :attr:`group_labels`, and :attr:`unwrapped_position`. +* Then one can write the properties to be output, and the allowed properties include: :attr:`mass`, :attr:`velocity`, :attr:`force`, :attr:`potential`, :attr:`virial`, :attr:`charge`, :attr:`bec`, :attr:`group_labels`, :attr:`spin`, :attr:`mforce`, :attr:`spin_velocity`, and :attr:`unwrapped_position`. The :attr:`group_labels` property writes one integer column per grouping method, holding the label of the group each atom belongs to. @@ -63,3 +63,9 @@ Caveats * For qNEP models, the charge values dumped out are predicted by the qNEP models. For other models, the charge values are those specified in :attr:`model.xyz` via :attr:`charge:R:1`. * The Born effective charge (:term:`BEC`) is only meaningful for a qNEP model trained with target :term:`BEC`. +* ``spin`` and ``mforce`` are three-component vectors available when + ``model.xyz`` contains ``spin:R:3``. ``spin_velocity`` additionally requires + an initialized ``spin_vel:R:3`` property. +* The per-atom ``virial`` property contains all nine row-major components + ``xx xy xz yx yy yz zx zy zz``. NEP_Spin does not symmetrize this per-atom + tensor. diff --git a/doc/gpumd/input_parameters/ensemble.rst b/doc/gpumd/input_parameters/ensemble.rst index 5559ecdb8..920432a28 100644 --- a/doc/gpumd/input_parameters/ensemble.rst +++ b/doc/gpumd/input_parameters/ensemble.rst @@ -10,6 +10,7 @@ There are different categories of methods accessible via this keyword, which are * :ref:`"standard" ensembles ` * :ref:`MTTK integrators ` +* :ref:`TSPIN integrators for Spin potentials ` * :ref:`integrators for thermal conductivity simulations ` * :ref:`integrators for path integral molecular dynamics simulations ` * :ref:`MSST integrator for simulating compressive shock wave ` @@ -22,7 +23,7 @@ There are different categories of methods accessible via this keyword, which are Units and suggested parameters ------------------------------ -The units of temperature and pressure for this keyword are K and GPa, respectively. +The units of temperature and pressure for this keyword are K and GPa, respectively. The temperature coupling constant :attr:`` means :math:`\tau_T/\Delta t`, where :math:`\tau_T` is the relaxation time of the thermostat and :math:`\Delta t` is the time step for integration. We require :math:`\tau_T/\Delta t \geq 1` and a good choice is :math:`\tau_T/\Delta t \approx 100`. diff --git a/doc/gpumd/input_parameters/ensemble_tspin.rst b/doc/gpumd/input_parameters/ensemble_tspin.rst new file mode 100644 index 000000000..69287794d --- /dev/null +++ b/doc/gpumd/input_parameters/ensemble_tspin.rst @@ -0,0 +1,193 @@ +.. _kw_ensemble_tspin: +.. _kw_nvt_tspin: +.. _kw_npt_tspin: +.. index:: + single: nvt_tspin (keyword in run.in) + single: npt_tspin (keyword in run.in) + single: TSPIN integrator + +:attr:`ensemble` (TSPIN) +======================== + +Use TSPIN to propagate the Cartesian spin coordinates of a Spin potential. +Choose ``nvt_tspin`` for a fixed simulation cell, optionally with lattice +dynamics, or ``npt_tspin`` when the simulation cell and pressure must also be +controlled. + +The implementation is compositional. Both commands add the same spin +Nose--Hoover-chain integrator. ``nvt_tspin`` combines it with the standard +lattice Nose--Hoover chain, whereas ``npt_tspin`` combines it with the +:ref:`MTTK thermostat and barostat `. TSPIN does not contain +a second implementation of the lattice thermostat or barostat. + +Syntax +------ + +For fixed-cell NVT dynamics, use:: + + ensemble nvt_tspin \ + [lattice on|off] \ + [mass_factor | mass_factor ...] \ + [seed ] + +For pressure-controlled NPT dynamics, use:: + + ensemble npt_tspin temp \ + [tperiod ] [pperiod ] \ + [mass_factor | mass_factor ...] \ + [seed ] + +The ``npt_tspin`` options through ``pperiod`` have the same syntax, meaning, +and defaults as ``npt_mttk``. The pressure terms can be ``iso``, ``aniso``, +``tri``, or a supported combination of ``x``, ``y``, ``z``, ``xy``, ``xz``, +and ``yz``. The optional TSPIN pairs must come after all MTTK options. + +Examples +-------- + +Run fixed-cell spin--lattice dynamics at 300 K:: + + ensemble nvt_tspin 300 300 100 mass_factor 0.001 seed 12345 + +Keep atomic positions and lattice velocities fixed and propagate only the +spin coordinates:: + + ensemble nvt_tspin 300 300 100 lattice off \ + mass_factor 0.001 seed 12345 + +For a Fe--Ge structure, propagate Fe spins with a coefficient of ``0.001`` +and keep Ge spins fixed:: + + ensemble nvt_tspin 300 300 100 \ + mass_factor Fe 0.001 Ge 0 seed 12345 + +Run isotropic pressure-controlled spin--lattice dynamics at 300 K and 0 GPa:: + + ensemble npt_tspin temp 300 300 iso 0 0 \ + tperiod 100 pperiod 1000 mass_factor 0.001 seed 12345 + +In both examples, ``mass_factor`` is a spin-mass coefficient. It does not +replace or change the lattice atomic masses. + +Parameters +---------- + +``T_1``, ``T_2`` + Initial and final target temperatures in K. The target is ramped linearly + during each ``run`` and is shared by the lattice and spin thermostats. + +``T_coup`` + Thermostat coupling period in timesteps for ``nvt_tspin``. It controls both + lattice and spin thermostats with ``lattice on``, and only the spin + thermostat with ``lattice off``. It must be finite and at least ``1``. + +``lattice on|off`` + Available only for ``nvt_tspin`` and defaults to ``on``. With ``on``, the + lattice positions and velocities are integrated and thermostatted by the + standard Nose--Hoover chain. With ``off``, GPUMD leaves every atomic + position and lattice velocity unchanged while continuing to evaluate the + Spin potential and integrate the spin coordinates. Supplied lattice + velocities are preserved rather than cleared. + +``mass_factor `` + A single positive finite value applies to every element. The code default is + ``1.0``. A practical starting value for magnetic-dynamics runs is ``0.001``. + A smaller positive value produces a faster spin response and can require a + smaller timestep, so check trajectory and temperature stability for the + system being studied. + +``mass_factor ...`` + Sets the coefficient by element name. Every element present in + ``model.xyz`` must be listed exactly once. Values must be finite and + non-negative, and at least one element must have a positive value. A value + of ``0`` is a TSPIN freeze marker: GPUMD excludes those spins from the spin + thermostat degrees of freedom, sets their spin velocities to zero, and does + not update their spin coordinates. Zero is never used as a physical mass or + as a divisor. + +``seed `` + Positive integer used to generate spin velocities when ``spin_vel:R:3`` is + absent. The default is ``12345``. The seed is ignored when initialized spin + velocities are supplied. + +Spin integration and ``spin_dof_type`` +-------------------------------------- + +TSPIN integrates every ``spin:R:3`` coordinate in ``model.xyz`` and includes +all of them in the spin thermostat degrees of freedom. It consumes the public +``mforce:R:3`` returned by the potential, but it does not read +``spin_dof_type``. + +``spin_dof_type`` is a Spin-potential response mask. For an excluded atom +type, the potential returns zero public magnetic force. This does not freeze +the spin, clear its spin velocity, or remove it from TSPIN. With zero magnetic +force, that coordinate can still move because of its current spin velocity +and the spin thermostat. Fixing selected spin coordinates therefore requires +an explicit integration constraint; ``spin_dof_type`` must not be used for +that purpose. + +State initialization and restart +-------------------------------- + +Each atom must have a ``spin:R:3`` vector. TSPIN propagates the full Cartesian +vector and does not normalize its length. + +If ``spin_vel:R:3`` is absent, GPUMD generates spin velocities from ``seed`` +and rescales them separately for each atom type to ``T_1``. If +``spin_vel:R:3`` is present, GPUMD uses every supplied value and ignores +``seed``. For an element whose mass factor is zero, any supplied spin velocity +is replaced by zero. Initialized spin velocities are reused by later ``run`` +commands. +They are also written by ``dump_restart`` and reused when its ``restart.xyz`` +is loaded as ``model.xyz``. + +Pressure coupling in ``npt_tspin`` +---------------------------------- + +The MTTK barostat acts on the simulation cell, atomic positions, and lattice +momenta. It neither rescales nor rotates the Cartesian spin vectors. The +instantaneous pressure contains the lattice kinetic term and the full +potential virial of :math:`U(\boldsymbol R,\boldsymbol S)`, but not the TSPIN +kinetic energy. Spin affects the cell through the Spin-potential virial. +Because pressure control requires cell and lattice dynamics, ``npt_tspin`` +does not accept ``lattice off``. + +Output and checks +----------------- + +Write the propagated state and magnetic force with:: + + dump_xyz 100 spin.xyz spin mforce spin_velocity + +The extended-XYZ fields are ``spin:R:3``, ``mforce:R:3``, and +``spin_vel:R:3``. Check that the spin temperature remains stable for the +chosen ``mass_factor`` and timestep. With ``lattice on``, also check the +lattice temperature. For ``npt_tspin``, check cell and pressure stability. + +The run log reports either ``integrate the lattice with a Nose-Hoover chain`` +or ``keep lattice positions and velocities fixed``. When using ``lattice +off``, include ``velocity`` in a short ``dump_xyz`` run; positions are written +automatically. Confirm that both remain unchanged while ``spin`` evolves. +The log also prints the resolved spin mass factor for each element. For an +element assigned ``0``, confirm that both ``spin`` and ``spin_velocity`` stay +unchanged while an element with a positive factor evolves. + +Restrictions +------------ + +TSPIN requires exactly one Spin potential, a positive timestep, positive +target temperatures, and finite integration parameters. ``npt_tspin`` is the +only pressure-controlled TSPIN variant; ``npt_ber_tspin`` and +``npt_scr_tspin`` are not implemented. The MTTK restriction +``pperiod >= 200`` also applies to ``npt_tspin``. The ``lattice`` keyword is +only valid for ``nvt_tspin`` and accepts only ``on`` or ``off``. Element-wise +``mass_factor`` input must cover every element present in ``model.xyz``; +unknown, missing, or repeated element names are rejected. + +Defaults +-------- + +``lattice`` defaults to ``on``, ``mass_factor`` defaults to ``1.0``, and +``seed`` defaults to ``12345``. +For ``npt_tspin``, MTTK retains its own defaults, including ``tperiod 100`` +and ``pperiod 1000``. diff --git a/doc/gpumd/input_parameters/index.rst b/doc/gpumd/input_parameters/index.rst index f9b68e302..3d88dc30f 100644 --- a/doc/gpumd/input_parameters/index.rst +++ b/doc/gpumd/input_parameters/index.rst @@ -23,6 +23,7 @@ Below you can find a listing of keywords for the ``run.in`` input file. ensemble ensemble_standard ensemble_mttk + ensemble_tspin ensemble_qtb ensemble_heat ensemble_ttm @@ -38,6 +39,7 @@ Below you can find a listing of keywords for the ``run.in`` input file. ensemble_nphug add_force add_efield + add_mfield add_spring deposit electron_stop @@ -79,7 +81,7 @@ Below you can find a listing of keywords for the ``run.in`` input file. .. toctree:: :maxdepth: 1 :caption: Output - + active dump_xyz dump_beads diff --git a/doc/gpumd/input_parameters/potential.rst b/doc/gpumd/input_parameters/potential.rst index 96324fd62..4ea156cfa 100644 --- a/doc/gpumd/input_parameters/potential.rst +++ b/doc/gpumd/input_parameters/potential.rst @@ -30,7 +30,7 @@ relative or absolute path) of the potential file to be used. Some potential types require additional parameters, as described in their corresponding sections. -For standard NEP and temperature-dependent NEP models, a multi-GPU run can +For standard NEP, temperature-dependent NEP, and ``nep_spin`` models, a multi-GPU run can optionally specify the spatial partition direction:: potential [partition_direction] @@ -41,7 +41,7 @@ triclinic box. If the direction is omitted, GPUMD selects it automatically, normally along the thickest direction of the box. The optional partition direction applies only to the multi-GPU implementation -of standard NEP and temperature-dependent NEP models. Charge NEP models +of standard NEP, temperature-dependent NEP, and ``nep_spin`` models. Charge NEP models currently use the single-GPU implementation in ``gpumd``. Example @@ -55,3 +55,38 @@ For a multi-GPU NEP run, one can force the decomposition along a specific direction, for example:: potential Si_NEP.txt x + +NEP-Spin spatial decomposition +------------------------------ + +A ``nep_spin`` simulation uses all GPUs visible to the process for the same +atomic system. For example, request four GPUs from the scheduler and run:: + + CUDA_VISIBLE_DEVICES=0,1,2,3 ./gpumd + +The model and the TSPIN/SIB ensemble commands are unchanged. The optional +partition direction above also applies to NEP-Spin. Fully periodic orthogonal +and triclinic cells are supported, as in the single-GPU Spin3 implementation. +SOC, noncollinear spins, and group/region ``add_mfield`` use the same physical +conventions as the single-GPU path. This is single-process, single-node MD; +it does not distribute training configurations or independent trajectories. + +Positions, types, and spins are repacked on every force evaluation, including +repeated evaluations at unchanged atomic positions. Ownership and neighbour lists can be reused while every +atom moves less than 0.2 times the maximum cutoff from the partition reference. +A five-cell halo (2.5 cutoffs) covers the two-hop environment plus this motion; +exceeding the displacement bound or changing the cell rebuilds the partition. Each spatial slab includes at least two maximum cutoffs +of halo atoms: the neighbours of an owned atom must themselves have complete +local environments for the force and magnetic-force derivatives. The existing +Spin3 evaluator computes each extended slab. Only owned-atom energy, force, +magnetic force, and all nine virial components are returned to GPU 0; ghost +outputs are discarded rather than added a second time. The external field and +integration act on the assembled global state. + +Small cells may require the entire geometry on each active GPU and therefore +need not speed up. Slabs have equal geometric widths; a strongly nonuniform +atomic distribution can cause load imbalance. Integration and global atom +arrays remain on GPU 0, so memory capacity does not grow exactly in proportion +to the GPU count. Prefer a long, evenly populated partition direction and +GPUs connected by fast peer links. Runtime-staged copies are supported when +direct peer access is unavailable, but can reduce throughput. diff --git a/doc/installation.rst b/doc/installation.rst index ead19f708..56cb691e1 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -97,7 +97,7 @@ use ``CUDA_VISIBLE_DEVICES`` to select a subset, for example:: CUDA_VISIBLE_DEVICES=0,1 ./nep The ``gpumd`` executable also uses all visible GPUs when running standard NEP -or temperature-dependent NEP models that support the multi-GPU implementation. +or temperature-dependent NEP models, and ``nep_spin`` spin models. For example:: CUDA_VISIBLE_DEVICES=0,1 ./gpumd diff --git a/doc/nep/input_files/index.rst b/doc/nep/input_files/index.rst index 62eaf0a0a..ea48dfe0e 100644 --- a/doc/nep/input_files/index.rst +++ b/doc/nep/input_files/index.rst @@ -12,4 +12,5 @@ To run a :term:`NEP` construction using the ``nep`` executable, one has to prep nep_in train_test_xyz + response_xyz ediff_in diff --git a/doc/nep/input_files/nep_in.rst b/doc/nep/input_files/nep_in.rst index 070fd84cd..122f7d9b6 100644 --- a/doc/nep/input_files/nep_in.rst +++ b/doc/nep/input_files/nep_in.rst @@ -48,6 +48,24 @@ Keywords - select between training and prediction (inference) * - :ref:`zbl ` - outer cutoff for the universal :term:`ZBL` potential [Ziegler1985]_ + * - :ref:`spin_version ` + - enable the Spin3 descriptor + * - :ref:`spin_cutoff ` + - radial and angular cutoffs used by the spin descriptor + * - :ref:`spin_basis_size ` + - radial and angular basis sizes used by the spin descriptor + * - :ref:`spin_l_max ` + - maximum spatial tensor rank used by the spin descriptor + * - :ref:`spin_compress ` + - number of shared compressed radial channels + * - :ref:`spin_order ` + - highest Spin3 contraction level supplied to the neural network + * - :ref:`spin_soc ` + - enable joint spin--space rotation-invariant Spin3 channels + * - :ref:`spin_dof_type ` + - atom types selected for magnetic-force output and magnetic supervision + * - :ref:`spin_env_type ` + - atom types allowed to contribute to magnetic environments * - :ref:`use_typewise_cutoff_zbl ` - enable typewise cutoff radii for the ZBL part of the model * - :ref:`cutoff ` @@ -70,6 +88,16 @@ Keywords - weight of force loss term * - :ref:`lambda_v ` - weight of virial loss term + * - :ref:`lambda_m ` + - weight of Cartesian magnetic-force loss term + * - :ref:`lambda_m_parallel ` + - weight of parallel magnetic-force RMSE (requires ``lambda_m_perp``) + * - :ref:`lambda_m_perp ` + - weight of perpendicular magnetic-force RMSE (requires ``lambda_m_parallel``) + * - :ref:`lambda_tau ` + - weight of spin-torque loss term + * - :ref:`lambda_spin_response ` + - weight of grouped magnetic-response loss term * - :ref:`lambda_q ` - weight of total-charge loss term for qNEP models * - :ref:`lambda_z ` @@ -98,6 +126,8 @@ Keywords - fine tune a model starting from a foundation model * - :ref:`import_q_scaler ` - import descriptor normalization factors from an existing ``nep.txt`` + * - :ref:`initial_para ` + - set reference parameters used to compute descriptor normalization Consistency with model files already present -------------------------------------------- @@ -129,3 +159,28 @@ Here is an example :attr:`nep.in` file using all the default parameters:: batch 1000 # default population 50 # default generation 100000 # default + +Spin3 example +------------- + +The following Spin setup uses the default descriptor shape. ``spin_compress`` +defaults to 2 and may be omitted. Together with the structural defaults, this +gives 55 magnetic and 97 total coordinates, within :ref:`nep_spin_dimensions`:: + + version 4 + type 2 Fe Ge + spin_version 1 + spin_basis_size 8 0 + spin_l_max 2 0 0 + spin_compress 2 + spin_order 3 + spin_soc 1 + neuron 30 + lambda_m 1.0 + batch 1000 + generation 100000 + +Each frame in ``train.xyz`` and ``test.xyz`` must then contain a Cartesian +``spin:R:3`` property. Add ``mforce:R:3`` when training magnetic forces. See +:ref:`train_test_xyz` for the complete data contract and :ref:`nep_spin` for +the Spin3 formalism. diff --git a/doc/nep/input_files/response_xyz.rst b/doc/nep/input_files/response_xyz.rst new file mode 100644 index 000000000..6f41e1db0 --- /dev/null +++ b/doc/nep/input_files/response_xyz.rst @@ -0,0 +1,39 @@ +.. _response_xyz: + +``response.xyz`` +================ + +Place this file beside ``nep.in`` when enabling +:ref:`lambda_spin_response `. It contains complete +rotation paths for the magnetic-response objective, independently of the +ordinary training minibatches. With zero response weight the file is ignored. + +Use extended XYZ frames with a cell (``Lattice``), ``species:S:1``, ``pos:R:3``, +``energy``, ordinary ``force:R:3``, final constrained-DFT ``spin:R:3`` and +``mforce:R:3``. All these labels are required, as in complete magnetic +training data; only virial is optional. Missing energy or force is an input +error, not a zero-valued label. Each frame also needs line-2 metadata:: + + response_probe=rotation response_group=scan-a response_coordinate=0.0 + +Each group must have at least three finite, distinct coordinates and fixed +atom order, species, positions, and cell. For a rotation angle, use radians. +Tangents are derived internally from the final spins; do not supply +``spin_tangent``. Spin is measured in Bohr magnetons and magnetic force in +eV per Bohr magneton. + +All groups enter each candidate's response loss in every generation with equal +group weight. Response-only frames never enter the ordinary energy, force, +virial, magnetic-force or torque losses. Baseline fitting and descriptor +scaling use only ordinary training data. A frame contributes to ordinary +losses only if explicitly included in ``train.xyz``. Requiring complete +labels does not enable additional response supervision: energy and ordinary +force labels are currently unused by the response loss, and no relative-energy +response loss is implemented. + +Keep response and validation data disjoint. With response loss enabled, +shared response group names between train/test or response/test are rejected. +An identical stored cell, species/order, positions and spin in response/test +is also rejected, even if the group name is removed or changed. This exact +frame check does not identify atom permutations or periodic-image equivalents; +keep complete physical scans in one split when preparing the data. diff --git a/doc/nep/input_files/train_test_xyz.rst b/doc/nep/input_files/train_test_xyz.rst index c20c12d31..2781f797d 100644 --- a/doc/nep/input_files/train_test_xyz.rst +++ b/doc/nep/input_files/train_test_xyz.rst @@ -53,11 +53,46 @@ Essentially any keyword is allowed, but we only read the following ones: * :attr:`pos:R:3` position vector * :attr:`force:R:3` or :attr:`forces:R:3` target force vector * :attr:`bec:R:9` target Born effective charge (:term:`BEC`) tensor (optional) + * :attr:`spin:R:3`, :attr:`spins:R:3`, :attr:`moment:R:3`, or + :attr:`moments:R:3` Cartesian magnetic-moment vector in muB (required when + :ref:`spin_version ` is specified) + * :attr:`mforce:R:3` target magnetic-force vector (optional). The aliases + ``mforces``, ``force_mag``, ``forces_mag``, ``magnetic_force``, and + ``magnetic_forces`` are also accepted. + + ``spin_tangent`` is not an input property. The trainer derives it internally + from each complete final-DFT spin path. * If a dipole model is to be trained, energy, virial, stress, and force will be ignored and one should additionally provide :attr:`dipole="dx dy dz"`, which is the dipole vector of the structure. * If a polarizability model is to be trained, energy, virial, stress, force, and dipole will be ignored and one should additionally provide :attr:`pol="pxx pxy pxz pyx pyy pyz pzx pzy pzz"`, which is the polarizability tensor of the structure. +Magnetic-response groups +^^^^^^^^^^^^^^^^^^^^^^^^ + +The grouped response loss is optional and is enabled by +:ref:`lambda_spin_response `. Its frames belong in +a separate :ref:`response.xyz ` file. Every response +frame must contain the final constrained-DFT ``spin:R:3``, ``mforce:R:3``, and +the following three line-2 metadata items: + +.. code:: + + response_probe=rotation response_group= response_coordinate= + +``response_group`` identifies frames belonging to one physical rotation path. +``response_coordinate`` parameterizes points on that path; using the rotation +angle in radians is recommended. The trainer sorts the group by this value and +derives the tangent from the converged DFT spins using a second-order, +three-point nonuniform finite difference. The coordinate only needs to be +meaningful within its group. + +Each response group needs at least three distinct coordinate values and must +keep atom count, type/order, positions, and cell fixed. Ordinary spin training +does not require response metadata. Non-``rotation`` probe metadata in ordinary +train/test data is accepted for analysis; response.xyz requires rotation groups. Atom types excluded by +:ref:`spin_dof_type ` are masked automatically. + Starting from line 3 ^^^^^^^^^^^^^^^^^^^^ @@ -71,6 +106,8 @@ Units * Virials are expected in units of eV (such that the virial divided by the volume yields the stress). * Dipole and polarizability can be in arbitrary units (such as the Hartree atomic units) as liked (and remembered) by the user. * :term:`BEC` is in units of elementary charge e. +* Spin is in Bohr magnetons (muB), and magnetic force is in eV/muB. + Magnetic force is the negative Cartesian derivative of energy with respect to spin. Tips ---- @@ -83,4 +120,3 @@ Tips * The energy and virial data refer to the total energy and virial for the system. They are not per-atom but per-cell quantities. * The :term:`BEC` is optional. You can also have it only for some structures. - diff --git a/doc/nep/input_parameters/batch.rst b/doc/nep/input_parameters/batch.rst index 1e288e0df..5b710aa98 100644 --- a/doc/nep/input_parameters/batch.rst +++ b/doc/nep/input_parameters/batch.rst @@ -11,6 +11,9 @@ The syntax is:: batch Here, :attr:`` sets the batch size :math:`N_\mathrm{bat}`, which must satisfy :math:`N_\mathrm{bat}\geq 1` and defaults to :math:`N_\mathrm{bat}=1000`. +For :ref:`lambda_spin_response `, this setting still +controls only ordinary training data. Complete groups in ``response.xyz`` +are evaluated separately in every generation. The keyword takes one argument. In principle one can train against the entire training set during every iteration of the optimization procedure (equivalent to :math:`N_\mathrm{bat}` being identical to the number of structures in the training set). It is, however, often beneficial for computational speed and potentially necessary for memory reasons to consider only a subset of the training data at any given iteration. diff --git a/doc/nep/input_parameters/import_q_scaler.rst b/doc/nep/input_parameters/import_q_scaler.rst index 9270a4ab8..26cdb9749 100644 --- a/doc/nep/input_parameters/import_q_scaler.rst +++ b/doc/nep/input_parameters/import_q_scaler.rst @@ -5,7 +5,7 @@ :attr:`import_q_scaler` ======================== -By default, when training or resuming a NEP potential without :attr:`fine_tune`, :program:`nep` computes :attr:`q_scaler`, the per-descriptor-component normalization used by the neural network, from the training structures of the current run at generation 0. +For ordinary structural NEP, when training or resuming without :attr:`fine_tune`, :program:`nep` computes :attr:`q_scaler`, the per-descriptor-component normalization used by the neural network, from the training structures of the current run at generation 0. This keyword instead tells :program:`nep` to read :attr:`q_scaler` from the :attr:`nep.txt` file present in the run directory, skipping that computation. This naturally requires such a file to be present. The syntax is:: @@ -19,3 +19,40 @@ In that case, the transplanted network weights were tuned under the :attr:`q_sca Unlike :attr:`fine_tune`, this keyword does not perform any species extraction: the :attr:`nep.txt` file it reads from is expected to already have the exact same architecture and species as the current run, which is why the file is referred to implicitly rather than by a path argument, matching the way :attr:`nep.restart` is referred to. :program:`nep` compares the header of that file against :attr:`nep.in` and raises an error naming the keyword on any mismatch; see :ref:`the nep.in page ` for the details. The mean/standard-deviation restart state (:attr:`mu`/:attr:`sigma`) is unaffected by this keyword: it is unconditionally read from :attr:`nep.restart`, exactly as in any other non-:attr:`fine_tune` run. + +Spin3 training and restart +-------------------------- + +Fresh Spin3 training computes scaling from the training structures using a +fixed, non-degenerate reference parameter vector, independent of the SNES +search mean and search RNG. Constant spin projection matrices would collapse +distinct descriptor channels, so the structural NEP constant-vector reference +is not used for Spin3. Response-only structures never enter this calculation. +The :ref:`initial_para ` keyword scales the radial coefficients +of this reference model while leaving its channel mixing matrices unchanged. + +When ``nep.restart`` is present, Spin3 automatically restores the scaler from +the matching ``nep.txt`` instead of recomputing it. This also preserves models +written before this fix, whose scaler depended on the initial search vector. +The two files must come from the same training run with matching architecture +and element order. The scaler must be finite and positive. Missing or +incompatible model data are errors, not requests to initialize a new model. +``import_q_scaler 0`` does not discard the scaler required by a Spin3 restart. + +``import_q_scaler 1`` is also supported for a fresh Spin3 search. It imports +scaling only; parameters are still newly initialized and the elemental energy +baseline is fitted to ordinary training data. On restart, both the saved +baseline and search state are retained. The cross-species ``fine_tune`` mode +remains unsupported for Spin3. + +``nep.restart`` stores the search distribution and ``energy_reference`` in the +shared restart format (see :ref:`nep_restart`), while ``nep.txt`` stores a +selected candidate model. Legacy two-column ``mu sigma`` restarts are still +accepted with their matching legacy ``nep.txt``. +The search mean and that candidate need not predict the same values. +No parameter rescaling or substitution of the selected candidate for the +search mean is performed during restart. + +As in the existing SNES lifecycle, a restart begins a new requested generation +segment and resets RNG initialization. The restart file does not store global +generation progress; it is not an exact replay of an uninterrupted trajectory. diff --git a/doc/nep/input_parameters/index.rst b/doc/nep/input_parameters/index.rst index 4a84e1a8f..e9592245e 100644 --- a/doc/nep/input_parameters/index.rst +++ b/doc/nep/input_parameters/index.rst @@ -43,4 +43,17 @@ Below you can find a listing of keywords for the ``nep.in`` input file. output_descriptor fine_tune import_q_scaler + initial_para charge_mode + spin_version + spin_compress + spin_basis_size + spin_l_max + spin_cutoff + spin_order + spin_soc + spin_dof_type + spin_env_type + lambda_m + lambda_tau + lambda_spin_response diff --git a/doc/nep/input_parameters/initial_para.rst b/doc/nep/input_parameters/initial_para.rst new file mode 100644 index 000000000..4759ceb9c --- /dev/null +++ b/doc/nep/input_parameters/initial_para.rst @@ -0,0 +1,34 @@ +.. _kw_initial_para: +.. index:: + single: initial_para (keyword in nep.in) + +:attr:`initial_para` +==================== + +Set the reference parameter scale used when computing descriptor normalization +factors (``q_scaler``) from the training structures:: + + initial_para + +The value must be finite and within [0.1, 1]. The default is 1. +This keyword does not set the SNES search mean, random seed, or search width +(``sigma0``). + +For ordinary structural NEP, the reference parameter vector is filled with +this value. For Spin3, this value multiplies the structural and magnetic +radial coefficients of a fixed, non-degenerate reference model. Its channel +mixing matrices are retained unchanged so that distinct magnetic channels +remain distinct. ``initial_para 1`` preserves the default Spin3 reference. +The magnetic scaler still obeys the gain cap described in :ref:`nep_spin`; +changing this value does not uniformly rescale every descriptor component. + +For example, a fresh Spin3 training run can use:: + + spin_version 1 + initial_para 0.5 + +Spin3 prediction, restart, and :ref:`import_q_scaler 1 ` +reuse the scaler saved in ``nep.txt``, regardless of ``initial_para``. +Changing this keyword in those runs does not rescale stored model parameters +or recompute normalization. To compute a new scaler, start a fresh training +run without ``nep.restart`` and with ``import_q_scaler 0``. diff --git a/doc/nep/input_parameters/lambda_m.rst b/doc/nep/input_parameters/lambda_m.rst new file mode 100644 index 000000000..ba35dd018 --- /dev/null +++ b/doc/nep/input_parameters/lambda_m.rst @@ -0,0 +1,90 @@ +.. _kw_lambda_m: +.. index:: + single: lambda_m (keyword in nep.in) + +:attr:`lambda_m` +================= + +This keyword sets the weight of Cartesian magnetic-force RMSE in the loss:: + + lambda_m + +The weight must be non-negative and defaults to 1. It multiplies the RMSE of +the Cartesian magnetic force + +.. math:: + + \boldsymbol{M}_i=-\frac{\partial U}{\partial\boldsymbol{s}_i}, + +whose unit is eV/muB. Only frames containing ``mforce:R:3`` and +atoms enabled by :ref:`spin_dof_type ` enter this RMSE. A +frame without magnetic-force labels can still contribute energy, force, or +virial data. + +Set ``lambda_m 0`` to remove the Cartesian magnetic-force RMSE from the +optimization objective. This does not change the analytic magnetic-force +definition or the model format. ``lambda_mforce`` is an accepted input alias, +but ``lambda_m`` is the canonical spelling used in the documentation and +training output. + + +.. _kw_lambda_m_parallel: +.. _kw_lambda_m_perp: +.. index:: + single: lambda_m_parallel (keyword in nep.in) + single: lambda_m_perp (keyword in nep.in) + +Independent parallel and perpendicular losses +--------------------------------------------- + +To fit the magnetic-moment magnitude and direction with separate coefficients, +replace ``lambda_m`` with **both** of the following keywords:: + + lambda_m_parallel 1.0 + lambda_m_perp 1.0 + +Each coefficient must be finite and non-negative. Set either coefficient to +zero to disable that component. Mixing these keywords with ``lambda_m`` or +``lambda_mforce`` is an error. With neither new keyword present, the original +Cartesian objective and output columns are unchanged. + +For residual :math:`\delta\boldsymbol M_i=\boldsymbol M_i-\boldsymbol M_i^{ref}` +and the input spin direction :math:`\hat{\boldsymbol s}_i`, define + +.. math:: + + R_\parallel &= \sqrt{\frac{1}{N_{mag}}\sum_i + (\delta\boldsymbol M_i\cdot\hat{\boldsymbol s}_i)^2},\\ + R_\perp &= \sqrt{\frac{1}{2N_{mag}}\sum_i + |\delta\boldsymbol M_i-(\delta\boldsymbol M_i\cdot\hat{\boldsymbol s}_i) + \hat{\boldsymbol s}_i|^2},\\ + L_{mag} &= \lambda_{m,\parallel}R_\parallel+ + \lambda_{m,\perp}R_\perp. + +Both reductions use the same labeled, active atoms as ``lambda_m``; the +normalization counts one parallel and two perpendicular degrees of freedom. +At exactly zero spin, squared residuals are assigned isotropically: one third +to the parallel channel and two thirds to the perpendicular channel. Every +nonzero spin defines a direction, without a small-moment cutoff. During +optimization, the existing squared configuration weights multiply each squared +residual; reported RMSEs are unweighted. + +Native SNES minimizes a weighted sum of **RMSEs**. TorchNEP's independent +coefficients multiply **MSEs**, so its ``(1/3, 2/3)`` vector-loss mapping is not +an equivalent mapping here. In general no pair of constant coefficients makes +the sum of these two RMSEs equal to Cartesian RMSE. Use ``lambda_m`` when exact +legacy behavior is required. The raw metrics obey +:math:`3 R_M^2=R_\parallel^2+2R_\perp^2`. + +``lambda_tau`` remains an independent torque term. Torque weights the +perpendicular residual by spin magnitude and is not the same as ``R_perp``. +The magnetic force itself, model format, prediction outputs, and MD dynamics +are unchanged. Native SNES has no TorchNEP second-stage lambda keywords. + +In split mode, ``loss.out`` adds four columns after ``rmse_tau_test`` and before +any energy-difference columns: ``rmse_m_parallel_train``, ``rmse_m_perp_train``, +``rmse_m_parallel_test``, and ``rmse_m_perp_test``. Read the ``# columns`` header; +the Cartesian and torque diagnostics are retained. Training metrics describe +the reported batch, as for the existing loss columns. Test metrics are zero +when no test set is supplied. On restart, the objective is taken from +``nep.in``; the model/restart files do not store these loss coefficients. diff --git a/doc/nep/input_parameters/lambda_spin_response.rst b/doc/nep/input_parameters/lambda_spin_response.rst new file mode 100644 index 000000000..41a623904 --- /dev/null +++ b/doc/nep/input_parameters/lambda_spin_response.rst @@ -0,0 +1,77 @@ +.. _kw_lambda_spin_response: +.. index:: + single: lambda_spin_response (keyword in nep.in) + +:attr:`lambda_spin_response` +============================= + +This keyword sets the weight of grouped magnetic-response loss:: + + lambda_spin_response + +The weight must be finite and non-negative and defaults to 0. A positive value +requires ``spin_version 1`` and :ref:`response.xyz ` in the working +directory. A missing file, an empty file, or an incomplete rotation group is +an input error. With weight 0, the file is not opened. + +Ordinary ``train.xyz`` data still use the ``batch`` setting. All complete +response groups are evaluated separately for every candidate in every SNES +generation after initialization (generation 0). As in ordinary NEP, generation 0 +prepares training state without physical candidate fitness. Response groups are never split by ordinary minibatches. There +is no ``response_file`` keyword or additional response batch setting. + +Response frames contribute only this loss. They do not contribute ordinary +energy, force, virial, magnetic-force or torque losses, the fitted energy +baseline, or descriptor scaling. They reuse the baseline and scaler from +``train.xyz``. GPUMD's existing test reporting and model-selection behavior +are unchanged; no separate response validation loss is added. + +For a response frame :math:`a`, the derived tangent +:math:`\boldsymbol{t}_{ai}` defines a scalar generalized response + +.. math:: + + R_a=\sum_i \boldsymbol{M}_{ai}\cdot\boldsymbol{t}_{ai}. + +The loss compares predicted and target :math:`R_a` values within each named +group. It robustly constrains both the centered response shape along the path +and, with a smaller weight, the group mean. This is useful when relative +magnetic response along a controlled rotation path matters in addition to +per-component magnetic-force RMSE. + +Every ``response.xyz`` frame must provide ``energy``, ``force:R:3``, the +converged DFT ``spin:R:3`` and ``mforce:R:3`` (virial is optional), together +with:: + + response_probe=rotation response_group= response_coordinate= + +Each group needs at least three distinct ``response_coordinate`` values, and +the trainer sorts each complete group by this coordinate and derives +``d spin / d response_coordinate`` using second-order, three-point nonuniform +weights in local spin coordinates. Angular displacements use the sphere +logarithm at the current spin; magnitude differences are differentiated +separately. This avoids a spurious radial tangent for a fixed-length rotation. +The coordinate does not have to be globally comparable between groups. + +For a rotation angle :math:`\theta`, ``response_coordinate`` should be +:math:`\theta` in radians. ``spin`` must contain the moments from the final +constrained-DFT state, not the initially requested constraint vectors. The +derived path tangent retains both transverse and longitudinal relaxation. +Atoms excluded by :ref:`spin_dof_type ` are masked from the +derived response automatically. ``spin_tangent:R:3`` is not accepted as an +input label. + +The rotation path must be resolved: angular separations within a stencil must +be less than pi. Antipodal samples are ambiguous and require intermediate +frames. At zero moment the tangent uses Cartesian differences. Constant-rate +great-circle rotations are differentiated exactly apart from floating-point +rounding; other paths retain the finite-stencil approximation. + +With this tangent convention, :math:`R_a\approx-\partial U_a/\partial\theta`. +Each group contributes equally and uses its own uncentered target-response +RMS, with a floor of :math:`10^{-6}`, to normalize its centered-shape and +group-mean Huber terms. The latter has weight 0.25. A large exchange response +in one group therefore cannot suppress a small anisotropy response in another. +Coordinates do not create an additional reliability weight. This GPUMD +reduction differs from the older shared-scale, Cartesian-tangent policy; +cross-implementation parity with TorchNEP must be checked explicitly. diff --git a/doc/nep/input_parameters/lambda_tau.rst b/doc/nep/input_parameters/lambda_tau.rst new file mode 100644 index 000000000..54cce573f --- /dev/null +++ b/doc/nep/input_parameters/lambda_tau.rst @@ -0,0 +1,30 @@ +.. _kw_lambda_tau: +.. index:: + single: lambda_tau (keyword in nep.in) + +:attr:`lambda_tau` +=================== + +This keyword sets the weight of spin-torque RMSE in the loss:: + + lambda_tau + +The weight must be non-negative and defaults to 0. For each labeled active +atom, the predicted and target quantities are converted to + +.. math:: + + \boldsymbol{\tau}_i + = \boldsymbol{s}_i\times\boldsymbol{M}_i. + +The resulting torque RMSE emphasizes magnetic-force components perpendicular +to the current spin. Only frames containing ``mforce:R:3`` and atom types +enabled by :ref:`spin_dof_type ` contribute. + +The Cartesian loss :ref:`lambda_m ` constrains all magnetic-force +components, whereas torque is insensitive to the parallel component. +Set ``lambda_m 0`` and a positive ``lambda_tau`` to supervise spin rotation +without constraining the longitudinal magnetic force. Zero spins are excluded +from torque RMSE, which is normalized by two degrees of freedom per active +nonzero spin. Squared torque errors weight squared transverse magnetic-force +errors by :math:`|\boldsymbol{s}_i|^2`. diff --git a/doc/nep/input_parameters/spin_basis_size.rst b/doc/nep/input_parameters/spin_basis_size.rst new file mode 100644 index 000000000..7b14ba881 --- /dev/null +++ b/doc/nep/input_parameters/spin_basis_size.rst @@ -0,0 +1,22 @@ +.. _kw_spin_basis_size: +.. index:: + single: spin_basis_size (keyword in nep.in) + +:attr:`spin_basis_size` +======================= + +This keyword sets the largest radial and angular basis indices of the spin +descriptor:: + + spin_basis_size + +The default is ``8 0``. As for the ordinary NEP basis, a maximum index +:math:`K` represents :math:`K+1` functions because indexing starts from zero. + +For ``spin_version 1``, the current radial construction uses exactly nine basis +functions and no separate angular basis. The only supported value is:: + + spin_basis_size 8 0 + +The first value controls the radial basis count; the second must be zero and +is omitted from the model-file field ``spin_basis_size 8``. diff --git a/doc/nep/input_parameters/spin_compress.rst b/doc/nep/input_parameters/spin_compress.rst new file mode 100644 index 000000000..bff2e5c60 --- /dev/null +++ b/doc/nep/input_parameters/spin_compress.rst @@ -0,0 +1,30 @@ +.. _kw_spin_compress: +.. index:: + single: spin_compress (keyword in nep.in) + +:attr:`spin_compress` +====================== + +This keyword sets the shared latent radial rank of the spin descriptor:: + + spin_compress + +The default is 2 and the input range is 1--9. The symbol :math:`C` denotes +this value in :ref:`nep_spin`. Each channel is a learned combination of the +radial basis, and every Spin3 contraction family reuses the same :math:`C` +channels. It therefore controls descriptor rank and cost; it does not select +a fixed list of Hamiltonian terms. + +For ``spin_version 1``, the spin descriptor must not exceed 96 components, and +the combined structural plus spin descriptor must not exceed 199 components. +The exact count also depends on :ref:`spin_order `, +:ref:`spin_l_max `, and :ref:`spin_soc `. + +For example, the commonly used order-3, :math:`l_\mathrm{max}=2`, SOC-enabled +shape has 55 magnetic coordinates with:: + + spin_compress 2 + +Together with the default structural descriptors, this default Spin shape has +97 total coordinates and satisfies both dimension limits. Use the formulas in +:ref:`nep_spin_dimensions` before increasing this value. diff --git a/doc/nep/input_parameters/spin_cutoff.rst b/doc/nep/input_parameters/spin_cutoff.rst new file mode 100644 index 000000000..21dfd5108 --- /dev/null +++ b/doc/nep/input_parameters/spin_cutoff.rst @@ -0,0 +1,25 @@ +.. _kw_spin_cutoff: +.. index:: + single: spin_cutoff (keyword in nep.in) + +:attr:`spin_cutoff` +==================== + +This keyword sets the Spin3 cutoff distance in Å:: + + spin_cutoff + spin_cutoff ... + +Use either one positive value, which is broadcast to all atom types, or exactly +one positive value for every type in the order declared by :ref:`type +`. If this keyword is absent, the largest ordinary radial +:ref:`cutoff ` is broadcast. For an edge between types :math:`a` +and :math:`b`, Spin3 uses the arithmetic mean +:math:`(r_a^\mathrm{spin}+r_b^\mathrm{spin})/2`. + +For example, with ``type 2 Fe Ge``:: + + spin_cutoff 5.0 7.0 + +uses 5, 6, and 7 Å for Fe--Fe, Fe--Ge, and Ge--Ge magnetic edges. This setting +does not change the ordinary structural NEP cutoffs. diff --git a/doc/nep/input_parameters/spin_dof_type.rst b/doc/nep/input_parameters/spin_dof_type.rst new file mode 100644 index 000000000..e1f3da879 --- /dev/null +++ b/doc/nep/input_parameters/spin_dof_type.rst @@ -0,0 +1,34 @@ +.. _kw_spin_dof_type: +.. index:: + single: spin_dof_type (keyword in nep.in) + +:attr:`spin_dof_type` +====================== + +This keyword selects atom types for magnetic-force output and magnetic supervision:: + + spin_dof_type [ ...] + +At least one type must be listed. Names must be unique and must appear in +:ref:`type `. If the keyword is absent, all atom types are selected. + +Selected types receive learned magnetic-force output and contribute to Cartesian +magnetic-force and torque RMSEs, including the optional parallel/perpendicular +split, when the corresponding labels are present. Excluded types receive zero +public magnetic force and do not enter these RMSE counts. Their current spins +can nevertheless contribute to a magnetic environment when explicitly included +by :ref:`spin_env_type `. + +This keyword selects supervised derivatives; it does not define an integration constraint. + +For TSPIN coordinate constraints, see :ref:`kw_ensemble_tspin`. + +The grouped-response path derivative is computed from the converged DFT spins. +When :ref:`lambda_spin_response ` is used, the trainer +automatically sets that derived tangent to zero on excluded atom types. + +To select only Fe for magnetic-force output and magnetic supervision, use:: + + spin_dof_type Fe + +Every selected type must also appear in ``spin_env_type``. diff --git a/doc/nep/input_parameters/spin_env_type.rst b/doc/nep/input_parameters/spin_env_type.rst new file mode 100644 index 000000000..9f34d348a --- /dev/null +++ b/doc/nep/input_parameters/spin_env_type.rst @@ -0,0 +1,27 @@ +.. _kw_spin_env_type: +.. index:: + single: spin_env_type (keyword in nep.in) + +:attr:`spin_env_type` +====================== + +This keyword selects atom types allowed to contribute as magnetic neighbors:: + + spin_env_type [ ...] + +Names must be unique and must appear in :ref:`type `. If this keyword +is absent, its mask is copied from +:ref:`spin_dof_type `; it does not independently default to +all atom types. + +Every type selected by ``spin_dof_type`` must also be an environment type, so +``spin_dof_type`` must be a subset of ``spin_env_type``. The two masks may +differ when a type should affect local magnetic descriptors but should not +receive a public magnetic force. For example:: + + spin_dof_type Fe + spin_env_type Fe Ge + +Here Fe receives magnetic-force output and magnetic supervision, while both +Fe and Ge atoms may enter the spin neighbor environment. These masks do not +freeze Ge spin coordinates during MD; see :ref:`spin_dof_type `. diff --git a/doc/nep/input_parameters/spin_l_max.rst b/doc/nep/input_parameters/spin_l_max.rst new file mode 100644 index 000000000..9d5fd6648 --- /dev/null +++ b/doc/nep/input_parameters/spin_l_max.rst @@ -0,0 +1,34 @@ +.. _kw_spin_l_max: +.. index:: + single: spin_l_max (keyword in nep.in) + +:attr:`spin_l_max` +=================== + +This keyword controls the maximum spatial tensor rank used by the spin +descriptor:: + + spin_l_max + +The default is ``2 0 0``. For ``spin_version 1``, ``l_3body`` can range from 0 +to 2 and the other two values must be zero. + +For Spin3, the first value has the following interpretation: + +.. list-table:: + :header-rows: 1 + :widths: 15 85 + + * - Value + - Enabled spatial information + * - 0 + - scalar and spin-only contractions + * - 1 + - additionally use vector/rank-1 spin--space contractions + * - 2 + - additionally use symmetric-traceless rank-2 contractions + +This rank cutoff is distinct from :ref:`spin_order ` and from +the ordinary structural :ref:`l_max `. A typical Spin3 setting is:: + + spin_l_max 2 0 0 diff --git a/doc/nep/input_parameters/spin_order.rst b/doc/nep/input_parameters/spin_order.rst new file mode 100644 index 000000000..6ddd7448a --- /dev/null +++ b/doc/nep/input_parameters/spin_order.rst @@ -0,0 +1,33 @@ +.. _kw_spin_order: +.. index:: + single: spin_order (keyword in nep.in) + +:attr:`spin_order` +=================== + +This Spin3 keyword selects the highest contraction level supplied to the +neural network:: + + spin_order + +The value can be 1, 2, or 3 and defaults to 3. It is used only with +``spin_version 1``. + +.. list-table:: + :header-rows: 1 + :widths: 15 85 + + * - Value + - Descriptor content + * - 1 + - local spin invariants and direct one-edge contractions + * - 2 + - order 1 plus edge powers, density norms, and two-leg correlations + * - 3 + - order 2 plus nested three-leg contractions + +The levels are nested: order 1 is a prefix of order 2, which is a prefix of +order 3. ``spin_order`` is **not** the body order of the final energy. The +neural network is nonlinear and can combine these coordinates with each other +and with the structural NEP descriptor. See :ref:`nep_spin_contractions` for +the explicit construction. diff --git a/doc/nep/input_parameters/spin_soc.rst b/doc/nep/input_parameters/spin_soc.rst new file mode 100644 index 000000000..33b387328 --- /dev/null +++ b/doc/nep/input_parameters/spin_soc.rst @@ -0,0 +1,31 @@ +.. _kw_spin_soc: +.. index:: + single: spin_soc (keyword in nep.in) + +:attr:`spin_soc` +================= + +This Spin3 keyword controls whether the descriptor can couple spin direction +to the local spatial environment:: + + spin_soc + +The flag can be 0 or 1 and defaults to 1. It is used only with +``spin_version 1``. + +.. list-table:: + :header-rows: 1 + :widths: 15 85 + + * - Value + - Rotational symmetry represented by the descriptor + * - 0 + - independent rotations of positions and spins + * - 1 + - joint rotations of positions and axial spin vectors (default) + +With value 0, Spin3 retains only the separately spin-rotation-invariant +subset. With value 1, it also includes scalar contractions between spin and +spatial rank-1/rank-2 objects up to +:ref:`spin_l_max `. The flag changes the descriptor's allowed +information flow; it does not impose a particular analytic SOC Hamiltonian. diff --git a/doc/nep/input_parameters/spin_version.rst b/doc/nep/input_parameters/spin_version.rst new file mode 100644 index 000000000..c8c54a583 --- /dev/null +++ b/doc/nep/input_parameters/spin_version.rst @@ -0,0 +1,43 @@ +.. _kw_spin_version: +.. index:: + single: spin_version (keyword in nep.in) + +:attr:`spin_version` +==================== + +This keyword selects the spin-dependent energy model and its magnetic +model contract:: + + spin_version 1 + +The only supported value is ``1``. Omit this keyword for ordinary NEP. +A missing value, an unsupported version, or a repeated model selector is an +input error. Version 1 uses the order/compression descriptor described in +:ref:`nep_spin`; :ref:`spin_order ` independently selects its +contraction order. + +Spin training requires ``version 4``, ``model_type 0``, and one hidden layer. +``version`` identifies the NEP architecture; ``spin_version`` identifies the +magnetic descriptor and parameter-layout contract. The resulting ``nep.txt`` +contains ``model nep_spin`` and ``spin_version 1``. Prediction, scaler import, +and restart require a compatible model. The shared model-file keyword +``format_version`` does not belong in ``nep.in``. + +Every training frame must contain a Cartesian ``spin:R:3`` property. Add +``mforce:R:3`` to train magnetic forces; see :ref:`train_test_xyz` for aliases +and units. Charge models and type-dependent structural cutoffs are unsupported. +Type-dependent :ref:`spin_cutoff ` and universal +:ref:`zbl ` are supported; flexible ZBL is not supported. ``fine_tune`` is not supported. ``import_q_scaler`` imports the +scaler while fitting a new energy reference to the current training set. + +A complete magnetic descriptor configuration is:: + + spin_version 1 + spin_basis_size 8 0 + spin_l_max 2 0 0 + spin_compress 2 + spin_order 3 + spin_soc 1 + +The last four keywords determine the magnetic descriptor dimension. See +:ref:`nep_spin_dimensions` before changing the shape. diff --git a/doc/nep/input_parameters/zbl.rst b/doc/nep/input_parameters/zbl.rst index 97b3aad8a..d9a264bbb 100644 --- a/doc/nep/input_parameters/zbl.rst +++ b/doc/nep/input_parameters/zbl.rst @@ -17,9 +17,17 @@ The "inner" cutoff of the :term:`ZBL` potential, below which value the pair inte When this keyword is absent, the :term:`ZBL` potential will not be enabled and the value of :math:`r_\mathrm{c}^\mathrm{ZBL-outer}` is irrelevant. -Permissible values are 1 Å :math:`\leq r_\mathrm{c}^\mathrm{ZBL-outer} \leq` 3 Å +ZBL is compatible with :ref:`spin_version 1 ` and produces a +``model nep_spin`` file with an additional ``zbl`` field. NEP-spin supports +universal ZBL only: training with ZBL enabled rejects an existing ``zbl.in`` +before reading its parameters, and model loading rejects ``zbl 0 0``. +Since ZBL +is spin independent, it contributes to energy, force, and virial but not to +magnetic force or torque. -One can also use flexible ZBL parameters by providing a `zbl.in` file in the working directory, in which case the :attr:`` parameter is still needed but will not be used. +Permissible values are 1 Å :math:`\leq r_\mathrm{c}^\mathrm{ZBL-outer} \leq` 4 Å. + +For non-spin models, one can also use flexible ZBL parameters by providing a `zbl.in` file in the working directory, in which case the :attr:`` parameter is still needed but will not be used. For a :math:`n`-species system, there should be :math:`n(n+1)/2` lines in the `zbl.in` files. Each line represents a unique pair of species. Counting from 1, the order of the lines is 1-1, 1-2, ..., 1-:math:`n`, 2-2, 2-3, ..., 2-:math:`n`, :math:`n`-:math:`n`. diff --git a/doc/nep/output_files/index.rst b/doc/nep/output_files/index.rst index 80bb174f4..7d7d70175 100644 --- a/doc/nep/output_files/index.rst +++ b/doc/nep/output_files/index.rst @@ -7,7 +7,7 @@ Output files The ``nep`` executable produces several output files. The :ref:`loss.out file ` is written in "append mode", while all other files are continuously overwritten. -The contents of the :ref:`energy_train.out `, :ref:`force_train.out `, :ref:`virial_train.out `, :ref:`stress_train.out `, :ref:`dipole_train.out `, and :ref:`polarizability_train.out ` files are updated every 1000 steps, while the contents of the other output files are updated every 100 steps. +The contents of the :ref:`energy_train.out `, :ref:`force_train.out `, :ref:`mforce_train.out `, :ref:`virial_train.out `, :ref:`stress_train.out `, :ref:`dipole_train.out `, and :ref:`polarizability_train.out ` files are updated every 1000 steps, while the contents of the other output files are updated every 100 steps. With the exception of the :ref:`nep.txt file `, the output files contain only numbers (no text) in matrix form. All the files are plain text files. @@ -33,6 +33,10 @@ All the files are plain text files. - target and predicted forces for training data set * - :ref:`force_test.out ` - target and predicted forces for test data set + * - :ref:`mforce_train.out ` + - target and predicted magnetic forces for training data set + * - :ref:`mforce_test.out ` + - target and predicted magnetic forces for test data set * - :ref:`virial_train.out ` - target and predicted virials for training data set * - :ref:`virial_test.out ` @@ -69,6 +73,7 @@ All the files are plain text files. nep_restart energy_out force_out + mforce_out virial_out stress_out dipole_out diff --git a/doc/nep/output_files/loss_out.rst b/doc/nep/output_files/loss_out.rst index 6623a83ac..dc363b1d9 100644 --- a/doc/nep/output_files/loss_out.rst +++ b/doc/nep/output_files/loss_out.rst @@ -79,3 +79,24 @@ where * :attr:`rmse_polarizability_train` is the polarizability RMSE (per atom) for the training set. * :attr:`rmse_polarizability_test` is the polarizability RMSE (per atom) for the test set. + +If a Spin NEP potential is trained, each row contains the following fields:: + + generation total L1 L2 rmse_energy_train rmse_force_train rmse_virial_train rmse_mforce_train rmse_tau_train rmse_energy_test rmse_force_test rmse_virial_test rmse_mforce_test rmse_tau_test + +Here, :attr:`rmse_mforce` is the Cartesian magnetic-force RMSE in eV/muB and +:attr:`rmse_tau` is the RMSE of +:math:`\boldsymbol{s}_i\times\boldsymbol{M}_i`, in eV. +Only structures containing magnetic-force labels contribute to these two +terms. The grouped magnetic-response loss, when enabled, contributes to +:attr:`total` but currently has no separate output column. + +With :ref:`independent magnetic losses `, four additional +columns precede any energy-difference columns:: + + rmse_m_parallel_train rmse_m_perp_train rmse_m_parallel_test rmse_m_perp_test + +They report unweighted RMSE in eV/muB, normalized by one parallel or two +perpendicular degrees of freedom. Training columns describe the current batch; +test columns are zero if no test set is supplied. Use the ``# columns`` header +to identify columns for the selected objective. diff --git a/doc/nep/output_files/mforce_out.rst b/doc/nep/output_files/mforce_out.rst new file mode 100644 index 000000000..db85faf32 --- /dev/null +++ b/doc/nep/output_files/mforce_out.rst @@ -0,0 +1,22 @@ +.. _mforce_out_nep: +.. index:: + single: mforce_train.out (output file) + single: mforce_test.out (output file) + +``mforce_*.out`` +================= + +The ``mforce_train.out`` and ``mforce_test.out`` files contain the predicted +and target magnetic-force components of labeled configurations provided in +the :ref:`train.xyz and test.xyz input files `. Configurations +without magnetic-force labels are omitted during training diagnostics. + +With ``prediction 1``, ``mforce_train.out`` includes every atom in the original +``train.xyz`` order, including configurations without magnetic-force labels. +For those configurations the last three columns are zero placeholders, not +reference measurements; they must not be used to calculate a prediction error. + +There are 6 columns. The first three columns are the :math:`x`, :math:`y`, and +:math:`z` magnetic-force components predicted by the :term:`NEP` model in eV/muB. The last three columns are the corresponding target magnetic +forces. Each row corresponds to one atom in an included configuration; inactive +spin-DOF types have zero predicted magnetic force. diff --git a/doc/nep/output_files/nep_restart.rst b/doc/nep/output_files/nep_restart.rst index 6e7ca6007..a0edc0dc4 100644 --- a/doc/nep/output_files/nep_restart.rst +++ b/doc/nep/output_files/nep_restart.rst @@ -14,3 +14,9 @@ The default :ref:`output_interval ` is 100 generations. The user does not need to understand the contents of this file. Remove this file to start a new training run rather than resuming. + +Spin3 restarts use this shared format and preserve ``energy_reference`` together +with the search mean and standard deviation. A matching ``nep.txt`` is still +needed for the Spin3 metadata and descriptor scalers. Legacy two-column Spin3 +restarts are accepted with their matching legacy model; their structural +parameters are converted from basis-major order before training resumes. diff --git a/doc/nep/output_files/nep_txt.rst b/doc/nep/output_files/nep_txt.rst index 982159fcd..4073791fc 100644 --- a/doc/nep/output_files/nep_txt.rst +++ b/doc/nep/output_files/nep_txt.rst @@ -7,3 +7,34 @@ This file contains the parameters of the :term:`NEP` model generated by the training. It can be used by the ``gpumd`` executable to run :term:`MD` simulations. + +Spin3 models use the same block format as other NEP models:: + + nep 2 Fe Ge + format_version 1 + model nep_spin + ... + energy_reference + spin_version 1 + ... + @ parameters + ... + @ q_scaler + ... + +``format_version`` versions the shared file syntax; ``spin_version`` versions +the magnetic descriptor definitions and parameter layout. ``spin_order`` selects +the descriptor order within that version. Use ``spin_version 1`` in both +``nep.in`` and ``nep.txt``. Missing or unsupported versions in a +``model nep_spin`` file are rejected. + +The reference energies are constants per element in eV. Training fits residual +energies after subtracting these references; prediction output and MD restore +them once. Forces, virials and magnetic forces do not include derivatives of +these constants. The shared output-bias correction remains active. + +Structural descriptor parameters use type-pair-major order. Magnetic radial +parameters use channel/basis/type-pair order, followed by radial-leg projection +parameters. Scalers are stored separately from trainable parameters. +Automatic element compaction is disabled for Spin, so the model's element +indices remain unchanged. diff --git a/doc/potentials/index.rst b/doc/potentials/index.rst index 3c1fad004..cd8a5a50a 100644 --- a/doc/potentials/index.rst +++ b/doc/potentials/index.rst @@ -17,6 +17,7 @@ Interatomic potentials eam fcp nep + nep_spin nep_ilp sw_ilp tersoff_ilp diff --git a/doc/potentials/nep_spin.rst b/doc/potentials/nep_spin.rst new file mode 100644 index 000000000..d91fab2c7 --- /dev/null +++ b/doc/potentials/nep_spin.rst @@ -0,0 +1,617 @@ +.. _nep_spin: +.. index:: + single: Spin potential + single: NEP_Spin + single: magnetic force + +Spin potential +************** + +``NEP_Spin`` extends the :ref:`NEP4 formalism ` to a local +energy surface that depends on both atomic positions and Cartesian spin +vectors. The total energy is the only learned scalar output. Atomic forces, +virials, magnetic forces, and spin torques are derivatives of this same energy +and are not produced by independent response networks. + +The current format uses ``nep``, ``format_version 1``, and ``model nep_spin`` +with ``spin_version 1`` and named parameter and scaler blocks. It uses the order/compression (O/C) +descriptor described below. An optional ``zbl`` field adds a spin-independent +universal ZBL term. Flexible ZBL (``zbl 0 0``) is not supported. +``spin_version`` identifies the descriptor and parameter-layout +contract, independently of the file syntax version and ``spin_order``. + +Energy model +============ + +For atom :math:`i`, the ordinary structural descriptor +:math:`\boldsymbol{q}^{i,\mathrm{str}}` is concatenated with a magnetic +descriptor :math:`\boldsymbol{q}^{i,\mathrm{spin}}`: + +.. math:: + + \boldsymbol{q}^{i} + = \boldsymbol{q}^{i,\mathrm{str}} + \mathbin{\|} \boldsymbol{q}^{i,\mathrm{spin}}. + +After componentwise scaling, this vector enters the same one-hidden-layer, +element-dependent neural network used by ordinary NEP4. The total energy is + +.. math:: + + U(\{\boldsymbol{r}_i,\boldsymbol{s}_i\}) + = \sum_i \left[ + U_i(\boldsymbol{q}^{i}) + E^0_{Z_i} + \right] + U_\mathrm{ZBL}, + +where :math:`\boldsymbol{r}_i` is the position, :math:`\boldsymbol{s}_i` is a +Cartesian magnetic-moment vector in Bohr magnetons (muB), :math:`Z_i` denotes the atom type, and +:math:`E^0_{Z_i}` is a fitted per-type energy baseline. The ZBL term is present +when ZBL is enabled and contains no spin dependence. The reference energies +use the shared ``energy_reference`` convention. + +This architecture allows the nonlinear network to combine structural and +magnetic coordinates. Therefore, ``spin_order`` describes the hierarchy of +primitive magnetic contractions supplied to the network; it is not the body +order of the final energy. + +Spin3 radial channels +===================== + +Let + +.. math:: + + \boldsymbol{e}_{ij} + = \frac{\boldsymbol{r}_j-\boldsymbol{r}_i}{r_{ij}} + +be the minimum-image unit vector from center atom :math:`i` to neighbor +:math:`j`. For each compressed radial channel :math:`c=1,\ldots,C`, Spin3 +forms the type-dependent edge weight + +.. math:: + + w^i_{jc} + = \sum_{k=0}^{8} c^{Z_i Z_j}_{ck} f_k(r_{ij}), + +where + +.. math:: + + f_k(r) + = \frac{1}{2}\left[ + T_k\left(2(r/r_\mathrm{c}^{\mathrm{spin}}-1)^2-1\right)+1 + \right] f_\mathrm{c}(r) + +and + +.. math:: + + f_\mathrm{c}(r) + = \begin{cases} + \frac{1}{2}\left[1+\cos(\pi r/r_\mathrm{c}^{\mathrm{spin}})\right], + & r\leq r_\mathrm{c}^{\mathrm{spin}},\\ + 0, & r>r_\mathrm{c}^{\mathrm{spin}}. + \end{cases} + +Thus :ref:`spin_compress ` controls a shared latent radial +rank rather than selecting individual Hamiltonian terms. All contraction +families use the same :math:`C` radial channels. + +Canonical edge-moment bank +========================== + +Spin3 organizes each neighbor edge into a canonical collection of scalar, +vector, rank-2, and product-tensor objects. Define the symmetric traceless +product + +.. math:: + + \mathcal{Q}(\boldsymbol{a},\boldsymbol{b}) + = \frac{1}{2}\left( + \boldsymbol{a}\otimes\boldsymbol{b} + +\boldsymbol{b}\otimes\boldsymbol{a} + \right) + -\frac{\boldsymbol{a}\cdot\boldsymbol{b}}{3}\boldsymbol{I}. + +The implementation stores this tensor in five orthonormal components, + +.. math:: + + \operatorname{stf}_5(\boldsymbol{a},\boldsymbol{b}) + = \left( + \frac{2a_zb_z-a_xb_x-a_yb_y}{\sqrt{6}}, + \frac{a_xb_x-a_yb_y}{\sqrt{2}}, + \frac{a_xb_y+a_yb_x}{\sqrt{2}}, + \frac{a_yb_z+a_zb_y}{\sqrt{2}}, + \frac{a_zb_x+a_xb_z}{\sqrt{2}} + \right). + +For each center :math:`i` and channel :math:`c`, the neighbor reduction builds +the following moment bank: + +.. math:: + + \boldsymbol{\rho}^{s}_{ic} + &= \sum_j w^i_{jc}\boldsymbol{s}_j,\\ + \boldsymbol{\rho}^{r}_{ic} + &= \sum_j w^i_{jc}\boldsymbol{e}_{ij},\\ + \rho^{rs}_{ic} + &= \sum_j w^i_{jc}(\boldsymbol{e}_{ij}\cdot\boldsymbol{s}_j),\\ + \boldsymbol{\rho}^{r\times s}_{ic} + &= \sum_j w^i_{jc}(\boldsymbol{e}_{ij}\times\boldsymbol{s}_j),\\ + \boldsymbol{\rho}^{\mathrm{stf}(rs)}_{ic} + &= \sum_j w^i_{jc}\operatorname{stf}_5( + \boldsymbol{e}_{ij},\boldsymbol{s}_j),\\ + \boldsymbol{\rho}^{\mathrm{stf}(rr)}_{ic} + &= \sum_j w^i_{jc}\operatorname{stf}_5( + \boldsymbol{e}_{ij},\boldsymbol{e}_{ij}),\\ + \boldsymbol{\rho}^{\mathrm{stf}(rr)s}_{ic} + &= \sum_j w^i_{jc}\operatorname{stf}_5( + \boldsymbol{e}_{ij},\boldsymbol{e}_{ij})\otimes\boldsymbol{s}_j,\\ + \boldsymbol{\rho}^{(s\cdot s)s}_{ic} + &= \sum_j w^i_{jc}(\boldsymbol{s}_i\cdot\boldsymbol{s}_j) + \boldsymbol{s}_j. + +The last two objects have 15 and 3 components, respectively. Together with +the scalar and vector entries above, each radial channel has a 38-component +canonical moment state. Most density-derived descriptor coordinates are +scalar contractions of this bank; the moments themselves are not passed +directly to the neural network. Direct one-edge sums and same-edge +channel-pair accumulators are reduced separately. + +.. _nep_spin_contractions: + +O/C contraction hierarchy +========================== + +The hierarchy is nested: at fixed :math:`C`, every order-1 coordinate is a +prefix of order 2, and every order-2 coordinate is a prefix of order 3. +Representative exact contractions are listed below. + +Order 1 contains local and direct-edge magnetic information such as + +.. math:: + + q^{i,\mathrm{spin}}_\mathrm{local} + &= |\boldsymbol{s}_i|^2,\\ + q^{i,\mathrm{spin}}_{c,\mathrm{dot}} + &= \boldsymbol{s}_i\cdot\boldsymbol{\rho}^{s}_{ic} + = \sum_j w^i_{jc}(\boldsymbol{s}_i\cdot\boldsymbol{s}_j),\\ + q^{i,\mathrm{spin}}_{c,\mathrm{neighbor}} + &= \sum_j w^i_{jc}|\boldsymbol{s}_j|^2. + +When joint spin--orbit channels with :math:`l_\mathrm{max}=2` are enabled, +order 1 also contains the rank-2 contractions + +.. math:: + + \sum_j w^i_{jc}\, + \mathcal{Q}(\boldsymbol{s}_i,\boldsymbol{s}_j) + :\mathcal{Q}(\boldsymbol{e}_{ij},\boldsymbol{e}_{ij}) + +and + +.. math:: + + \mathcal{Q}(\boldsymbol{s}_i,\boldsymbol{s}_i) + :\boldsymbol{\rho}^{\mathrm{stf}(rr)}_{ic}. + +Order 2 adds edge powers, density norms, and correlations between two magnetic +density legs. Examples include + +.. math:: + + \sum_j w^i_{jc}(\boldsymbol{s}_i\cdot\boldsymbol{s}_j)^2, + \qquad + |\boldsymbol{\rho}^{s}_{ic}|^2, + \qquad + (\rho^{rs}_{ic})^2, + \qquad + |\boldsymbol{\rho}^{r\times s}_{ic}|^2, + +and + +.. math:: + + \boldsymbol{\rho}^{s}_{ic}\cdot + \boldsymbol{\rho}^{(s\cdot s)s}_{ic}. + +For a radial-channel pair :math:`c\leq d`, Spin3 keeps same-edge and +distinct-neighbor correlations separately: + +.. math:: + + S^i_{cd} + &= \sum_j w^i_{jc}w^i_{jd} + (\boldsymbol{s}_i\cdot\boldsymbol{s}_j)^2,\\ + D^i_{cd} + &= (\boldsymbol{s}_i\cdot\boldsymbol{\rho}^{s}_{ic}) + (\boldsymbol{s}_i\cdot\boldsymbol{\rho}^{s}_{id})-S^i_{cd}\\ + &= \sum_{j\neq k}w^i_{jc}w^i_{kd} + (\boldsymbol{s}_i\cdot\boldsymbol{s}_j) + (\boldsymbol{s}_i\cdot\boldsymbol{s}_k). + +This separation prevents a two-density contraction from conflating repeated +use of one neighbor edge with a correlation between distinct neighbors. + +Spin3 additionally resolves the distinct-neighbor exchange by spatial angular +rank. Define + +.. math:: + + \boldsymbol{A}^{(1)}_{ic} + &=\sum_j w^i_{jc}(\boldsymbol{s}_i\cdot\boldsymbol{s}_j) + \boldsymbol{e}_{ij},\\ + \boldsymbol{A}^{(2)}_{ic} + &=\sum_j w^i_{jc}(\boldsymbol{s}_i\cdot\boldsymbol{s}_j) + \operatorname{stf}_5(\boldsymbol{e}_{ij},\boldsymbol{e}_{ij}). + +For every :math:`c\leq d`, the new coordinates are + +.. math:: + + D^{i,(1)}_{cd} + &=\boldsymbol{A}^{(1)}_{ic}\cdot\boldsymbol{A}^{(1)}_{id}-S^i_{cd},\\ + D^{i,(2)}_{cd} + &=\frac{3}{2}\boldsymbol{A}^{(2)}_{ic}\cdot + \boldsymbol{A}^{(2)}_{id}-S^i_{cd}. + +The subtraction removes the repeated-edge contribution, while the +:math:`3/2` factor compensates the norm of the rank-2 STF representation. +These blocks distinguish angular exchange environments that have the same +scalar distinct-neighbor contraction. + +Joint spin--orbit contractions use four learned radial-leg mixing matrices +:math:`A^{(\alpha)}\in\mathbb{R}^{C\times C}`. For any moment family +:math:`\boldsymbol{\rho}`, a projected leg is + +.. math:: + + \overline{\boldsymbol{\rho}}^{(\alpha)}_{ic} + = \sum_{d=1}^{C} A^{(\alpha)}_{cd}\boldsymbol{\rho}_{id}. + +This permits non-collinear contraction legs while retaining one shared radial +seam. Representative order-2 joint invariants are + +.. math:: + + \left( + \overline{\boldsymbol{\rho}}^{r,(0)}_{ic} + \times + \overline{\boldsymbol{\rho}}^{r,(1)}_{ic} + \right)\cdot + \left( + \boldsymbol{s}_i\times + \overline{\boldsymbol{\rho}}^{s,(0)}_{ic} + \right) + +and + +.. math:: + + \operatorname{axial}\left([ + \overline{\mathcal{Q}}^{(0)}_{ic}, + \overline{\mathcal{Q}}^{(1)}_{ic} + ]\right)\cdot + \left( + \boldsymbol{s}_i\times + \overline{\boldsymbol{\rho}}^{s,(0)}_{ic} + \right), + +where :math:`[\mathcal{A},\mathcal{B}]=\mathcal{A}\mathcal{B}- +\mathcal{B}\mathcal{A}` and ``axial`` maps the resulting antisymmetric tensor +to an axial vector. + +Order 3 adds dot-gated and triple-density contractions. Its direct-edge member +is + +.. math:: + + \sum_j w^i_{jc} + (\boldsymbol{s}_i\cdot\boldsymbol{s}_j) + \left(|\boldsymbol{s}_i|^2+|\boldsymbol{s}_j|^2\right), + +while representative joint contractions include scalar triple products such +as + +.. math:: + + \overline{\boldsymbol{\rho}}^{r,(0)}_{ic}\cdot + \left( + \overline{\boldsymbol{\rho}}^{s,(1)}_{ic} + \times + \overline{\boldsymbol{\rho}}^{r\times s,(2)}_{ic} + \right). + +These coordinates supply a symmetry-respecting polynomial basis to a +nonlinear energy model. They do not assign a fixed exchange, DMI, anisotropy, +or other spin-Hamiltonian coefficient to any individual descriptor channel. + +Symmetries +========== + +All Spin3 descriptor coordinates are even under global time reversal, + +.. math:: + + \boldsymbol{s}_i\longrightarrow-\boldsymbol{s}_i. + +With ``spin_soc 0``, the spatial vectors and spin vectors may be rotated +independently and the descriptor is invariant under both rotations. With +``spin_soc 1``, the extra channels are invariant under a joint orthogonal +transformation of the lattice vectors and axial spin vectors, + +.. math:: + + \boldsymbol{e}_{ij}\longrightarrow R\boldsymbol{e}_{ij}, + \qquad + \boldsymbol{s}_i\longrightarrow\det(R)R\boldsymbol{s}_i, + \qquad R\in O(3). + +The :ref:`spin_dof_type ` mask selects center atoms that +receive public magnetic forces. The +:ref:`spin_env_type ` mask selects neighbor types that enter +the moment sums. An environment-only spin can therefore affect the energy and +other spins while its public magnetic force is zero. This mask belongs to the +potential response and is not an integration constraint; a TSPIN integrator +still propagates that spin coordinate. + +.. _nep_spin_dimensions: + +Model dimensions +================ + +Let :math:`P=C(C+1)/2`, :math:`I_X` be 1 when condition :math:`X` is true and +0 otherwise, and define + +.. math:: + + a_C=1+I_{C\geq2},\qquad b_C=1+2I_{C\geq2}. + +For :math:`L=l_\mathrm{max}` and :math:`S=\texttt{spin\_soc}`, the order-1 +Spin3 dimension is + +.. math:: + + D_1=1+2C+2C I_S I_{L\geq2}. + +The order-2 increment is + +.. math:: + + \Delta D_2 &= 2C + +C I_{L\geq1}\left(3I_S+1-I_S\right) + +C I_{L\geq2}+C+2P\\ + &+a_C C I_S I_{L\geq1} + +a_C C I_S I_{L\geq2} + +P I_{L\geq1}+P I_{L\geq2}, + +and the order-3 increment is + +.. math:: + + \Delta D_3 &= C + +a_C C I_S I_{L\geq1}\\ + &+b_C C I_S I_{L\geq2} + +C I_S I_{L\geq1} I_{C\geq3}. + +Therefore :math:`D_2=D_1+\Delta D_2` and +:math:`D_3=D_2+\Delta D_3`. For the common :math:`L=2`, ``spin_soc 1`` shape, +O2-C2 has 43 magnetic coordinates and O3-C2 has 55. The implementation limits +the magnetic part to 96 coordinates and requires the combined structural and +magnetic dimension to satisfy :math:`D_\mathrm{str}+D_\mathrm{spin}\leq199`. +With the ordinary structural defaults, :math:`D_\mathrm{str}=42`; the default +O3-C2-L2-SOC1 shape therefore gives :math:`42+55=97` total coordinates. + +The trainable magnetic descriptor parameters comprise +:math:`9C N_\mathrm{typ}^2` radial coefficients and, for Spin3, +:math:`4C^2` radial-leg mixing coefficients. These are optimized together +with the neural-network parameters by SNES. + +Structural coordinates retain the ordinary inverse-range scaler. Magnetic +coordinates use +:math:`1/\max(\operatorname{RMS}(q),\operatorname{range}(q),1)`, without +centering. Their gain is therefore never larger than one, including for a +constant or initially unresolved magnetic channel. +For fresh training, :ref:`initial_para ` scales the radial +coefficients of the fixed reference model used to compute these scalers. +Its default of 1 retains the reference unchanged. Prediction, restart, and +explicit scaler import reuse the stored normalization instead. + +Energy derivatives +================== + +The atomic force and the unmasked magnetic derivative are defined by + +.. math:: + + \boldsymbol{F}_k=-\frac{\partial U}{\partial\boldsymbol{r}_k}, + \qquad + \widetilde{\boldsymbol{M}}_k + =-\frac{\partial U}{\partial\boldsymbol{s}_k}. + +For an atom type enabled by :ref:`spin_dof_type `, the +public magnetic force is +:math:`\boldsymbol{M}_k=\widetilde{\boldsymbol{M}}_k`. For an inactive type it +is explicitly set to zero, even when that atom is retained as an +environment-only spin input. This does not remove the atom from the spin +integrator or its thermostat degrees of freedom. + +Writing :math:`q^i_\nu` for either a structural or magnetic descriptor +component, the chain rule gives + +.. math:: + + \boldsymbol{F}_k + =-\sum_{i,\nu} + \frac{\partial U_i}{\partial q^i_\nu} + \frac{\partial q^i_\nu}{\partial\boldsymbol{r}_k} + -\frac{\partial U_\mathrm{ZBL}}{\partial\boldsymbol{r}_k}, + +.. math:: + + \widetilde{\boldsymbol{M}}_k + =-\sum_{i,\nu} + \frac{\partial U_i}{\partial q^i_\nu} + \frac{\partial q^i_\nu}{\partial\boldsymbol{s}_k}. + +The implementation first evaluates +:math:`\partial U_i/\partial q^i_\nu` through the neural network and then +applies the analytical vector--Jacobian product of every Spin3 contraction, +moment reduction, and radial basis function. The same position derivative +produces the full per-atom virial. No finite-difference force path is used. + +The spin torque used for training diagnostics is + +.. math:: + + \boldsymbol{\tau}_i + =\boldsymbol{s}_i\times\boldsymbol{M}_i. + +ZBL contributes to energy, atomic force, and virial but not to magnetic force +or torque because it is spin independent. + +Pressure-controlled spin dynamics +================================= + +``npt_tspin`` combines TSPIN with the same Nosé--Hoover-chain and +Parrinello--Rahman/MTTK cell dynamics used by :attr:`npt_mttk`. Its extended +energy has the schematic form + +.. math:: + + \mathcal{H}_\mathrm{ext} + = K_R + K_S + U(\boldsymbol R,\boldsymbol S) + + P_\mathrm{ext}V + + \mathcal{H}_{\mathrm{NH},R} + + \mathcal{H}_{\mathrm{NH},S} + + \mathcal{H}_{\mathrm{NH},h}, + +where :math:`K_R` is lattice kinetic energy, +:math:`K_S=\sum_i|\boldsymbol\pi_i^S|^2/(2\mu_i)` is spin-coordinate kinetic +energy, and :math:`h` denotes the cell degrees of freedom. The spin equations +are + +.. math:: + + \dot{\boldsymbol s}_i + = \frac{\boldsymbol\pi_i^S}{\mu_i}, + \qquad + \dot{\boldsymbol\pi}_i^S + = \boldsymbol M_i-\xi_S\boldsymbol\pi_i^S. + +Cartesian spins are internal coordinates: changing :math:`h` remaps atomic +positions, but neither rescales nor rotates :math:`\boldsymbol s_i`. Therefore +the barostat pressure contains lattice kinetic stress and the full potential +virial, + +.. math:: + + P_{\alpha\beta} + = \frac{1}{V}\left[ + \sum_i m_i v_{i\alpha}v_{i\beta} + + W_{\alpha\beta}(\boldsymbol R,\boldsymbol S) + \right], + +but no :math:`K_S` term. Spin still affects the cell because the analytical +virial :math:`W` differentiates the complete Spin-potential energy with +respect to cell deformation. Separate Nosé--Hoover chains control lattice and +spin kinetic energies at the same target-temperature ramp; the pressure chain +controls the cell momenta. + +The complete user-facing syntax, initialization rules, restart behavior, and +output example are documented under :ref:`npt_tspin `. This +implementation does not define ``npt_ber_tspin`` or ``npt_scr_tspin``; the +only pressure-controlled TSPIN path is the MTTK composition described above. + +Spin loss terms +=============== + +Spin training augments the ordinary :ref:`NEP loss ` with +magnetic-force and torque RMSE terms, + +.. math:: + + L_\mathrm{spin} + = \lambda_\mathrm{m} L_\mathrm{m} + + \lambda_\mathrm{tau} L_\mathrm{tau} + + \lambda_\mathrm{resp} L_\mathrm{resp}, + +where :math:`N_\mathrm{m}` counts labeled active spins and +:math:`N_\mathrm{tau}` counts only their nonzero spins, + +.. math:: + + L_\mathrm{m} + &=\left[ + \frac{1}{3N_\mathrm{m}} + \sum_i |\boldsymbol{M}^{\mathrm{NEP}}_i- + \boldsymbol{M}^{\mathrm{tar}}_i|^2 + \right]^{1/2},\\ + L_\mathrm{tau} + &=\left[ + \frac{1}{2N_\mathrm{tau}} + \sum_i |\boldsymbol{s}_i\times\boldsymbol{M}^{\mathrm{NEP}}_i- + \boldsymbol{s}_i\times\boldsymbol{M}^{\mathrm{tar}}_i|^2 + \right]^{1/2}. + +The magnetic-force loss always includes all three Cartesian components and +includes zero spins. The torque loss excludes zero spins. To supervise only +spin rotation, set ``lambda_m 0`` and a positive ``lambda_tau``. For nonzero +spins, the squared torque error equals the squared transverse magnetic-force +error multiplied by :math:`|\boldsymbol{s}_i|^2`. + +For a grouped rotation path with coordinate :math:`\theta`, the response +generator evaluated for frame :math:`n` is + +.. math:: + + G_n + =\sum_i \boldsymbol{M}_{ni}\cdot + \frac{\partial\boldsymbol{s}_{ni}}{\partial\theta} + =-\frac{\partial U_n}{\partial\theta}. + +The grouped response loss first centers :math:`G_n` within each group. Each +group contributes equally to the centered-curve Huber loss, independent of its +number of scan points. Each group's uncentered target-response RMS, floored +at :math:`10^{-6}`, normalizes its shape term and a second Huber term comparing +group means; the mean term is multiplied by 0.25. ``response_coordinate`` +defines the path derivative but does not add a separate reliability weight. +This GPUMD policy differs from the older shared-scale reduction. + +The group coordinate is explicit because Cartesian spin snapshots alone do +not determine their path ordering or parameterization. The trainer sorts each +group and derives +:math:`\partial\boldsymbol{s}/\partial\theta` from the final constrained-DFT +spins with second-order, three-point nonuniform weights applied to sphere-log +angular displacements and separate magnitude differences. This preserves +longitudinal moment relaxation without injecting the radial chord error of +Cartesian interpolation into constant-length rotations. Stencils must resolve +angular separations below pi. Atom types excluded by ``spin_dof_type`` are +masked from the derived tangent. See :ref:`lambda_spin_response +` for zero-moment and finite-stencil limitations. + +Spin3 uses the shared SNES lifecycle: generation zero prepares training scalers +and uses regularization-only fitness. Physical losses are evaluated from the +next generation. All magnetic descriptor orders participate throughout training. + +Model formats and input +======================= + +.. list-table:: + :header-rows: 1 + :widths: 25 30 45 + + * - Header in ``nep.txt`` + - Training mode + - Description + * - ``nep`` / ``model nep_spin`` + - ``spin_version 1`` + - Current block format with ``spin_version 1``; optional :ref:`zbl ` field. + +See :ref:`spin_version ` and the neighboring ``spin_*`` keyword +pages for descriptor configuration. The complete extended-XYZ data contract, +including magnetic-force labels and grouped response metadata, is documented +under :ref:`train_test_xyz`. +Runtime ``model.xyz`` files require one ``spin:R:3`` vector per atom. +TSPIN dynamics is documented in :ref:`kw_ensemble_tspin`. diff --git a/potentials/nep/nep_model_format.md b/potentials/nep/nep_model_format.md index 33f24439c..c7e9e4645 100644 --- a/potentials/nep/nep_model_format.md +++ b/potentials/nep/nep_model_format.md @@ -11,6 +11,7 @@ Version 1 supports the following model types: | `model` | Meaning | |---|---| | `nep` | Standard energy NEP | +| `nep_spin` | Spin-dependent energy NEP; requires `spin_version` (Section 5.1) | | `nep_temperature` | Temperature-dependent NEP | | `qnep1` | qNEP with charge mode 1 | | `qnep2` | qNEP with charge mode 2 | @@ -274,6 +275,7 @@ The model-dependent values are: | Model | `O` | `G` | `S` | Extra ANN inputs | Output order | |---|---:|---:|---:|---:|---| | `nep` | 1 | 1 | 1 | 0 | energy | +| `nep_spin` | 1 | 1 | 1 | `D_spin` | energy | | `nep_temperature` | 1 | 1 | 1 | 1 | energy | | `qnep1` | 2 | 2 | 1 | 0 | energy, charge | | `qnep2` | 2 | 2 | 1 | 0 | energy, charge | @@ -294,7 +296,7 @@ The global parameters within one ANN set are ordered as follows: | Model | Global parameter order | |---|---| -| `nep`, `nep_temperature`, `nep_vdw`, `nep_dipole` | common output bias | +| `nep`, `nep_spin`, `nep_temperature`, `nep_vdw`, `nep_dipole` | common output bias | | `nep_polarizability` | common output bias for each ANN set | | `qnep1`, `qnep2`, `qnep2_vdw` | `sqrt_epsilon_inf`, common energy-output bias | @@ -471,6 +473,9 @@ N + C_descriptor. ``` +`nep_spin` appends magnetic radial and projection coefficients to this array; +its complete count is given in Section 5.1. + This value must exactly match both the count declared in `@ parameters N` and the number of numerical values in that block. ### 4.2 `q_scaler` @@ -483,6 +488,9 @@ There is one float32 factor per ANN input: radial descriptors first, then angula Radial components follow increasing `n`. Angular components are grouped by invariant: `l = 1, ..., L_max`, then the enabled terms `q_222`, `q_1111`, `q_112`, `q_123`, `q_233`, and `q_134`, in that order. Within each angular group, `n` runs from zero through `n_max_angular`. +For `nep_spin`, magnetic components follow all structural components; see +Section 5.1 for their order. + The `q_scaler` block is not part of the trainable `parameters` vector and is not included in `N`. ### 4.3 `zbl_parameters` @@ -531,6 +539,107 @@ with the rows ordered as above. The model tables in Section 4.1 determine the number of outputs, global parameters, and ANN sets. Use these together with the descriptor and network dimensions to determine all array lengths. +### 5.1 Spin-dependent models: `model nep_spin` + +New Spin models use: + +```text +nep 2 Fe Ge +format_version 1 +model nep_spin +spin_version 1 +``` + +`format_version` describes the shared file syntax. `spin_version` describes the +magnetic descriptor definitions, units, scaler interpretation, and parameter +layout. Version `1` is the current order/compression (Spin3) model, including its +existing response/environment masks. +`spin_order` selects O1/O2/O3 within this contract and is not a version number. + +`spin_version` is required and must contain exactly the integer token `1`. +Missing or unknown versions are errors. Changes to descriptor meaning or array +layout that reinterpret existing parameter values require a new supported spin +version. Training-loss settings, implementation optimizations, and bug fixes +that restore the specified behavior do not change the version. + +The model fields below supplement the common energy-model fields: + +| Field | Version-1 meaning | +|---|---| +| `spin_version 1` | Magnetic model contract version | +| `spin_basis_size 8` | Highest magnetic radial basis index; nine basis functions | +| `spin_l_max L` | Magnetic angular rank, `L` in `0..2` | +| `spin_compress C` | Number of compressed radial channels, `C` in `1..9` | +| `spin_order O` | Contraction order, `O` in `1..3` | +| `spin_soc S` | Joint spin/spatial channels: `0` or `1` | +| `spin_cutoff ...` | One positive cutoff, or `T` cutoffs in element order, in angstroms; pair cutoff is their arithmetic mean | +| `spin_projection_size P` | Number of projection coefficients; must equal `4*C*C` | +| `spin_scaler 1` | Per-component scaling is present in `q_scaler` | +| `spin_dof_type ` | Optional nonempty subset receiving public magnetic forces; defaults to all elements | +| `spin_env_type ` | Optional nonempty subset entering magnetic environments; defaults to `spin_dof_type` | + +`spin_dof_type` must be a subset of `spin_env_type`. An environment-only spin +can influence the energy while its public magnetic force is masked to zero. +These masks do not freeze coordinates in a spin integrator. Spins use muB, +energy uses eV, and magnetic force uses eV/muB. For descriptor definitions and +scaling formulas, see [the Spin potential documentation](../../doc/potentials/nep_spin.rst). + +Version 1 supports one hidden layer (`ann N1 0`, `1 <= N1 <= 120`) and uniform +structural cutoffs. Structural limits are `nr <= 12`, `na <= 8`, `br <= 16`, +`ba <= 12`, and `L_max <= 8`, with at most 90 structural angular components. +Training supports at most 96 magnetic components, and the combined descriptor +must fit 199 components. The structural and magnetic dimensions are determined +by the enabled contractions, not by free metadata counts. + +#### Parameter and scaler layout + +Let `D = D_struct + D_spin`. With `O = G = S = 1` in the notation of Section 4.1 +(these symbols there describe ANN outputs, global parameters, and ANN sets), +the parameter vector is: + +```text +ANN parameters and common energy-output bias +structural radial coefficients [T, T, nr + 1, br + 1] +structural angular coefficients [T, T, na + 1, ba + 1] +magnetic radial coefficients [C, 9, T, T] +magnetic projection coefficients [4, C, C] +``` + +All arrays use C order. The magnetic radial indices are +`[channel, basis, center_type, neighbor_type]`; their type pair is the fastest +varying index, unlike the structural segments. Projection indices are +`[leg, output_channel, source_channel]`. This preserves the existing Spin3 +magnetic layout. The total parameter count is + +```text +N = T * N1 * (D + 2) + 1 + + T*T * ((nr + 1)*(br + 1) + (na + 1)*(ba + 1)) + + 9*C*T*T + 4*C*C. +``` + +The scaler contains `D` values, with structural components first as in Section +4.2. Magnetic components follow the version-1 contraction order defined by +`make_spin_polynomial_layout` in [nep_spin3_layout.cuh](../../src/force/nep_spin/nep_spin3_layout.cuh): +local squared moment; order-1 edge terms; order-2 edge/density/correlation and +axial terms; then order-3 gated and coupled terms. Disabled families contribute +no entries. Channels increase within a family; channel-pair families use +`(0,0), (0,1), ..., (0,C-1), (1,1), ..., (C-1,C-1)`. All enabled components retain +their original scaler and projection semantics. + +`energy_reference`, optional ZBL, numerical precision, and the restart syntax +remain the shared conventions. `nep.restart` has no separate spin version: it +must be interpreted with the corresponding `nep.txt`, whose version is checked +before loading the restart. Loss weights such as `lambda_m_parallel` and +`lambda_m_perp` are training inputs, not model-file fields. + +#### Training input + +Select this model in `nep.in` with `spin_version 1` and the ordinary NEP +architecture selector `version 4`. Omit `spin_version` for ordinary NEP. +Unsupported versions and repeated or conflicting model selectors are errors. +Prediction, scaler import, and restart require a compatible `nep.txt`. +Do not put the model-file fields `model` or `format_version` in `nep.in`. + ## 6. `nep.restart` The restart stores elemental energy references and the SNES mean (`mu`) and standard deviation (`sigma`) for every trainable parameter: @@ -555,6 +664,10 @@ Energy references are float64, written with 17 significant digits. `mu` and `sig ## 7. Legacy model conversion +The converter below covers the ordinary NEP model families; it does not convert +Spin files. Spin models are written directly by the trainer in the format +described in Section 5.1. + Supported legacy model files can be converted with ```bash diff --git a/src/force/force.cu b/src/force/force.cu index 7e0887737..1304a8bfa 100644 --- a/src/force/force.cu +++ b/src/force/force.cu @@ -34,6 +34,8 @@ The driver class calculating force and related quantities. #include "ilp_tersoff.cuh" #include "lj.cuh" #include "nep.cuh" +#include "nep_spin/nep_spin.cuh" +#include "nep_spin/nep_spin_multigpu.cuh" #include "nep_multigpu.cuh" #include "nep_charge.cuh" #include "nep_charge_vdw/nep_charge_vdw.cuh" @@ -46,6 +48,7 @@ The driver class calculating force and related quantities. #include "utilities/gpu_macro.cuh" #include "utilities/nep_model_file.cuh" #include "utilities/nep_model_input.cuh" +#include "utilities/nep_spin_model_file.cuh" #include "utilities/read_file.cuh" #include "utilities/run_input.cuh" #include @@ -114,6 +117,25 @@ std::unique_ptr Force::create_potential( strcmp(potential_name, "qnep2_vdw") == 0) { potential.reset(new NEP_Charge_VDW(tokens[1].c_str(), number_of_atoms, run_input)); is_nep = true; + } else if ( + strcmp(potential_name, "nep4_spin3") == 0 || + strcmp(potential_name, "nep4_spin3_zbl") == 0) { + if (!potentials.empty()) { + PRINT_INPUT_ERROR("NEP_Spin must be the only potential in a run."); + } + int direction = -1; + if (num_param == 3) { + if (tokens[2] == "x") direction = 0; + else if (tokens[2] == "y") direction = 1; + else if (tokens[2] == "z") direction = 2; + else PRINT_INPUT_ERROR("partition direction for multi-GPU NEP can only be x or y or z."); + } + int num_gpus = 0; + CHECK(gpuGetDeviceCount(&num_gpus)); + if (num_gpus == 1) potential.reset(new NEP_Spin(tokens[1].c_str(), number_of_atoms)); + else potential.reset(new NEP_Spin_MultiGPU(num_gpus, tokens[1].c_str(), number_of_atoms, direction)); + is_nep = true; + has_spin_potential_ = true; } else if ( strcmp(potential_name, "nep4_charge1") == 0 || strcmp(potential_name, "nep4_charge2") == 0 || @@ -234,7 +256,11 @@ void Force::parse_potential( PRINT_INPUT_ERROR("reading error for potential file."); } int num_types = get_number_of_types(fid_potential); - if (NEP_Model_Input::is_new_format(potential_name)) { + if (NEP_Model_Input::is_new_format(potential_name) && is_nep_spin_model_file(tokens[1])) { + NEP_Model_Input input(tokens[1]); + const std::vector header = input.get_tokens(); + std::strcpy(potential_name, header[0].c_str()); + } else if (NEP_Model_Input::is_new_format(potential_name)) { NEP_Model_File model; std::ifstream input(tokens[1]); std::string error; @@ -276,6 +302,9 @@ void Force::parse_potential( // Move the pointer into the list of potentials potentials.push_back(std::move(potential)); // Check if a non-NEP potential has previously been defined + if (has_spin_potential_ && potentials.size() != 1) { + PRINT_INPUT_ERROR("NEP_Spin must be the only potential in a run."); + } has_non_nep = has_non_nep || !is_nep; if (potentials.size() > 1 && has_non_nep) { PRINT_INPUT_ERROR("Multiple potentials may only be used with NEP potentials.\n"); @@ -613,3 +642,44 @@ void Force::compute( virial_per_atom); } + +void Force::compute_spin( + Box& box, + GPU_Vector& position_per_atom, + GPU_Vector& type, + std::vector& group, + GPU_Vector& potential_per_atom, + GPU_Vector& force_per_atom, + GPU_Vector& virial_per_atom, + GPU_Vector& spin_per_atom, + GPU_Vector& mforce_per_atom, + int* position_image) +{ + if (!has_spin_potential_ || potentials.size() != 1) { + PRINT_INPUT_ERROR("Spin-aware force dispatch requires one NEP_Spin potential."); + } + + const int number_of_atoms = type.size(); + if ( + spin_per_atom.size() != static_cast(number_of_atoms) * 3 || + mforce_per_atom.size() != static_cast(number_of_atoms) * 3) { + PRINT_INPUT_ERROR("NEP_Spin requires three spin and mforce components per atom."); + } + prepare_compute( + number_of_atoms, box, position_per_atom, potential_per_atom, + force_per_atom, virial_per_atom, position_image); + mforce_per_atom.fill(0.0); + GPU_CHECK_KERNEL + + potentials[0]->compute( + box, + type, + position_per_atom, + spin_per_atom, + potential_per_atom, + force_per_atom, + virial_per_atom, + mforce_per_atom); + magnetic_field_.compute( + box, position_per_atom, group, spin_per_atom, potential_per_atom, mforce_per_atom); +} diff --git a/src/force/force.cuh b/src/force/force.cuh index d53247c95..87b734347 100644 --- a/src/force/force.cuh +++ b/src/force/force.cuh @@ -18,6 +18,7 @@ #include "model/box.cuh" #include "model/group.cuh" #include "potential.cuh" +#include "nep_spin/mfield.cuh" #ifdef GPUMD_WPE_ENABLED #include "wpe_stage.cuh" #endif @@ -61,6 +62,26 @@ public: GPU_Vector& mass_per_atom, int* position_image = nullptr); + void compute_spin( + Box& box, + GPU_Vector& position_per_atom, + GPU_Vector& type, + std::vector& group, + GPU_Vector& potential_per_atom, + GPU_Vector& force_per_atom, + GPU_Vector& virial_per_atom, + GPU_Vector& spin_per_atom, + GPU_Vector& mforce_per_atom, + int* position_image = nullptr); + + bool has_spin_potential(void) const { return has_spin_potential_; } + + void parse_mfield(const char** param, int num_param, const std::vector& group) + { + magnetic_field_.parse(param, num_param, group); + } + bool has_mfield() const { return magnetic_field_.enabled(); } + // Zeroes the given arrays and evaluates one potential alone into them. The positions and the // float box are read as they are. void compute_one_potential( @@ -106,6 +127,8 @@ private: double temperature = 0; double delta_T; std::vector> potentials; + Spin_Magnetic_Field magnetic_field_; + bool has_spin_potential_ = false; bool is_fcp = false; bool has_non_nep = false; std::string multiple_potentials_mode_ = "observe"; // "observe" or "average" diff --git a/src/force/neighbor.cu b/src/force/neighbor.cu index c04f6407a..c8ca3c876 100644 --- a/src/force/neighbor.cu +++ b/src/force/neighbor.cu @@ -100,7 +100,9 @@ static __global__ void gpu_find_neighbor_ON1( const int ny, const int nz, const double rc_inv, - const float cutoff_square) + const float cutoff_square, + const int neighbor_capacity, + int* required_capacity) { const int n1 = blockIdx.x * blockDim.x + threadIdx.x + N1; int count = 0; @@ -153,17 +155,23 @@ static __global__ void gpu_find_neighbor_ON1( const float d2 = x12 * x12 + y12 * y12 + z12 * z12; if (d2 < cutoff_square) { - NL[static_cast(N) * count++ + n1] = n2; + if (count < neighbor_capacity) { + NL[static_cast(N) * count + n1] = n2; + } + ++count; } } } } } } - NN[n1] = count; + NN[n1] = min(count, neighbor_capacity); + atomicMax(required_capacity, count); } } +static __device__ int static_required_neighbor_capacity[1]; + void find_cell_list( const double rc, const int* num_bins, @@ -325,6 +333,13 @@ void find_neighbor( find_cell_list( rc_cell_list, num_bins, box, position_per_atom, cell_count, cell_count_sum, cell_contents); + const int MN = NL.size() / NN.size(); + int* gpu_required_capacity = nullptr; + CHECK(gpuGetSymbolAddress( + reinterpret_cast(&gpu_required_capacity), static_required_neighbor_capacity)); + const int zero = 0; + CHECK(gpuMemcpy(gpu_required_capacity, &zero, sizeof(int), gpuMemcpyHostToDevice)); + gpu_find_neighbor_ON1<<>>( box, N, @@ -343,10 +358,22 @@ void find_neighbor( num_bins[1], num_bins[2], rc_inv_cell_list, - rc * rc); + rc * rc, + MN, + gpu_required_capacity); GPU_CHECK_KERNEL - const int MN = NL.size() / NN.size(); + int required_capacity = 0; + CHECK(gpuMemcpy( + &required_capacity, gpu_required_capacity, sizeof(int), gpuMemcpyDeviceToHost)); + if (required_capacity > MN) { + printf( + "Neighbor capacity overflow: required %d slots but capacity is %d.\n", + required_capacity, + MN); + PRINT_INPUT_ERROR( + "Neighbor capacity is insufficient; no descriptor or force kernel was launched."); + } gpu_sort_neighbor_list<<>>(N, NN.data(), NL.data()); GPU_CHECK_KERNEL } @@ -776,14 +803,15 @@ void Neighbor::find_neighbor_global( bool is_first_time = false; - if (x0.size() == 0) { + if (x0.size() != N) { is_first_time = true; - x0.resize(N); - y0.resize(N); - z0.resize(N); + x0.resize_with_capacity(N); + y0.resize_with_capacity(N); + z0.resize_with_capacity(N); } - if (is_first_time || check_atom_distance(box, x, y, z)) { + if (force_rebuild_ || is_first_time || check_atom_distance(box, x, y, z)) { + force_rebuild_ = false; find_neighbor( 0, N, @@ -833,13 +861,14 @@ void Neighbor::find_local_neighbor_from_global( void Neighbor::initialize(const double rc, const int num_atoms, const int num_neighbors) { + invalidate(); const double rc_plus_skin = rc + skin; - const int MN = num_neighbors * rc_plus_skin * rc_plus_skin * rc_plus_skin / (rc * rc * rc); - NN.resize(num_atoms); - NL.resize(static_cast(num_atoms) * MN); - cell_count.resize(num_atoms); - cell_count_sum.resize(num_atoms); - cell_contents.resize(num_atoms); + MN_global = num_neighbors * rc_plus_skin * rc_plus_skin * rc_plus_skin / (rc * rc * rc); + NN.resize_with_capacity(num_atoms); + NL.resize_with_capacity(static_cast(num_atoms) * MN_global); + cell_count.resize_with_capacity(num_atoms); + cell_count_sum.resize_with_capacity(num_atoms); + cell_contents.resize_with_capacity(num_atoms); } double Neighbor::get_skin() const @@ -923,4 +952,3 @@ void NeighborManager::check_cutoff(const double requested_cutoff) const PRINT_INPUT_ERROR("Requested neighbor cutoff exceeds the supported candidate cutoff."); } } - diff --git a/src/force/neighbor.cuh b/src/force/neighbor.cuh index d57310cde..6a432b0f8 100644 --- a/src/force/neighbor.cuh +++ b/src/force/neighbor.cuh @@ -152,6 +152,7 @@ class Neighbor public: GPU_Vector NN, NL; // global neighbor list void initialize(const double rc, const int num_atoms, const int num_neighbors); + void invalidate() { force_rebuild_ = true; } double get_skin() const; int get_capacity() const; void find_neighbor_global( @@ -165,13 +166,19 @@ public: const GPU_Vector& position_per_atom, GPU_Vector& NN_local, GPU_Vector& NL_local); + double minimum_safe_box_thickness(const double rc) const + { + return 2.5 * (rc + skin); + } private: + bool force_rebuild_ = true; double skin = 1.0; // skin distance GPU_Vector cell_count; // for cell list GPU_Vector cell_count_sum; // for cell list GPU_Vector cell_contents; // for cell list GPU_Vector x0, y0, z0; // for checking atom distance + int MN_global = 0; int check_atom_distance(Box& box, const double* x, const double* y, const double* z); }; diff --git a/src/force/nep.cu b/src/force/nep.cu index dd37b0070..c2c5d2c44 100644 --- a/src/force/nep.cu +++ b/src/force/nep.cu @@ -22,6 +22,7 @@ heat transport, Phys. Rev. B. 104, 104309 (2021). #include "neighbor.cuh" #include "nep.cuh" +#include "nep_kernels.cuh" #include "nep_small_box.cuh" #include "utilities/common.cuh" #include "utilities/compact_nep.cuh" @@ -541,7 +542,7 @@ static __global__ void find_descriptor( } } -static __global__ void find_force_radial( +__global__ void find_force_radial( NEP::ParaMB paramb, NEP::ANN annmb, const int N, @@ -647,7 +648,7 @@ static __global__ void find_force_radial( } } -static __global__ void find_partial_force_angular( +__global__ void find_partial_force_angular( NEP::ParaMB paramb, NEP::ANN annmb, const int N, diff --git a/src/force/nep_kernels.cuh b/src/force/nep_kernels.cuh new file mode 100644 index 000000000..9e9de6239 --- /dev/null +++ b/src/force/nep_kernels.cuh @@ -0,0 +1,41 @@ +#pragma once + +#include "nep.cuh" + +__global__ void find_force_radial( + NEP::ParaMB paramb, + NEP::ANN annmb, + int N, + int N1, + int N2, + Box box, + const int* NN, + const int* NL, + const int* type, + const double* x, + const double* y, + const double* z, + const float* Fp, + double* fx, + double* fy, + double* fz, + double* virial); + +__global__ void find_partial_force_angular( + NEP::ParaMB paramb, + NEP::ANN annmb, + int N, + int N1, + int N2, + Box box, + const int* NN_angular, + const int* NL_angular, + const int* type, + const double* x, + const double* y, + const double* z, + const float* Fp, + const float* sum_fxyz, + float* f12x, + float* f12y, + float* f12z); diff --git a/src/force/nep_multigpu.cu b/src/force/nep_multigpu.cu index fc3eec547..e28918d49 100644 --- a/src/force/nep_multigpu.cu +++ b/src/force/nep_multigpu.cu @@ -420,214 +420,7 @@ void NEP_MULTIGPU::update_potential(float* parameters, ANN& ann) ann.c = pointer; } -static __device__ void find_cell_id( - const int partition_direction, - const Box& box, - const double x, - const double y, - const double z, - const double rc_inv, - const int nx, - const int ny, - const int nz, - int& cell_id_x, - int& cell_id_y, - int& cell_id_z, - int& cell_id) -{ - const double sx = box.cpu_h[9] * x + box.cpu_h[10] * y + box.cpu_h[11] * z; - const double sy = box.cpu_h[12] * x + box.cpu_h[13] * y + box.cpu_h[14] * z; - const double sz = box.cpu_h[15] * x + box.cpu_h[16] * y + box.cpu_h[17] * z; - cell_id_x = floor(sx * box.thickness_x * rc_inv); - cell_id_y = floor(sy * box.thickness_y * rc_inv); - cell_id_z = floor(sz * box.thickness_z * rc_inv); - - while (cell_id_x < 0) - cell_id_x += nx; - while (cell_id_x >= nx) - cell_id_x -= nx; - while (cell_id_y < 0) - cell_id_y += ny; - while (cell_id_y >= ny) - cell_id_y -= ny; - while (cell_id_z < 0) - cell_id_z += nz; - while (cell_id_z >= nz) - cell_id_z -= nz; - if (partition_direction == 0) { - cell_id = cell_id_y + ny * (cell_id_z + nz * cell_id_x); - } else if (partition_direction == 1) { - cell_id = cell_id_x + nx * (cell_id_z + nz * cell_id_y); - } else { - cell_id = cell_id_x + nx * (cell_id_y + ny * cell_id_z); - } -} - -static __device__ void find_cell_id( - const int partition_direction, - const Box& box, - const double x, - const double y, - const double z, - const double rc_inv, - const int nx, - const int ny, - const int nz, - int& cell_id) -{ - int cell_id_x, cell_id_y, cell_id_z; - find_cell_id( - partition_direction, - box, - x, - y, - z, - rc_inv, - nx, - ny, - nz, - cell_id_x, - cell_id_y, - cell_id_z, - cell_id); -} - -static __global__ void find_cell_counts( - const int partition_direction, - const Box box, - const int N, - int* cell_count, - const double* x, - const double* y, - const double* z, - const int nx, - const int ny, - const int nz, - const double rc_inv) -{ - const int n1 = blockIdx.x * blockDim.x + threadIdx.x; - if (n1 < N) { - int cell_id; - find_cell_id(partition_direction, box, x[n1], y[n1], z[n1], rc_inv, nx, ny, nz, cell_id); - atomicAdd(&cell_count[cell_id], 1); - } -} - -static __global__ void find_cell_contents( - const int partition_direction, - const Box box, - const int N, - int* cell_count, - const int* cell_count_sum, - int* cell_contents, - const double* x, - const double* y, - const double* z, - const int nx, - const int ny, - const int nz, - const double rc_inv) -{ - const int n1 = blockIdx.x * blockDim.x + threadIdx.x; - if (n1 < N) { - int cell_id; - find_cell_id(partition_direction, box, x[n1], y[n1], z[n1], rc_inv, nx, ny, nz, cell_id); - const int ind = atomicAdd(&cell_count[cell_id], 1); - cell_contents[cell_count_sum[cell_id] + ind] = n1; - } -} - -static void __global__ set_to_zero(int size, int* data) -{ - int n = threadIdx.x + blockIdx.x * blockDim.x; - if (n < size) { - data[n] = 0; - } -} - -static void find_cell_list( - gpuStream_t& stream, - const int partition_direction, - const double rc, - const int* num_bins, - Box& box, - const int N, - const GPU_Vector& position_per_atom, - GPU_Vector& cell_count, - GPU_Vector& cell_count_sum, - GPU_Vector& cell_contents) -{ - const int offset = position_per_atom.size() / 3; - const int block_size = 256; - const int grid_size = (N - 1) / block_size + 1; - const double rc_inv = 1.0 / rc; - const double* x = position_per_atom.data(); - const double* y = position_per_atom.data() + offset; - const double* z = position_per_atom.data() + offset * 2; - const int N_cells = num_bins[0] * num_bins[1] * num_bins[2]; - - // number of cells is allowed to be larger than the number of atoms - if (N_cells > cell_count.size()) { - cell_count.resize(N_cells); - cell_count_sum.resize(N_cells); - } - - set_to_zero<<<(cell_count.size() - 1) / 64 + 1, 64, 0, stream>>>( - cell_count.size(), cell_count.data()); - GPU_CHECK_KERNEL - - set_to_zero<<<(cell_count_sum.size() - 1) / 64 + 1, 64, 0, stream>>>( - cell_count_sum.size(), cell_count_sum.data()); - GPU_CHECK_KERNEL - - set_to_zero<<<(cell_contents.size() - 1) / 64 + 1, 64, 0, stream>>>( - cell_contents.size(), cell_contents.data()); - GPU_CHECK_KERNEL - - find_cell_counts<<>>( - partition_direction, - box, - N, - cell_count.data(), - x, - y, - z, - num_bins[0], - num_bins[1], - num_bins[2], - rc_inv); - GPU_CHECK_KERNEL - - thrust::exclusive_scan( -#ifdef USE_HIP - thrust::hip::par.on(stream), -#else - thrust::cuda::par.on(stream), -#endif - cell_count.data(), - cell_count.data() + N_cells, - cell_count_sum.data()); - - set_to_zero<<<(cell_count.size() - 1) / 64 + 1, 64, 0, stream>>>( - cell_count.size(), cell_count.data()); - GPU_CHECK_KERNEL - - find_cell_contents<<>>( - partition_direction, - box, - N, - cell_count.data(), - cell_count_sum.data(), - cell_contents.data(), - x, - y, - z, - num_bins[0], - num_bins[1], - num_bins[2], - rc_inv); - GPU_CHECK_KERNEL -} +#include "nep_partition.cuh" static __global__ void find_neighbor_list_large_box( NEP_MULTIGPU::ParaMB paramb, diff --git a/src/force/nep_partition.cuh b/src/force/nep_partition.cuh new file mode 100644 index 000000000..4226fe2cf --- /dev/null +++ b/src/force/nep_partition.cuh @@ -0,0 +1,216 @@ +// Cell ordering and slab packing shared by the single-process NEP backends. +// Extracted without algorithm changes from nep_multigpu.cu (GPUMD, LGPL-3.0-or-later). +#pragma once +#include "model/box.cuh" +#include "utilities/gpu_vector.cuh" +#include +#include + +static __device__ void find_cell_id( + const int partition_direction, + const Box& box, + const double x, + const double y, + const double z, + const double rc_inv, + const int nx, + const int ny, + const int nz, + int& cell_id_x, + int& cell_id_y, + int& cell_id_z, + int& cell_id) +{ + const double sx = box.cpu_h[9] * x + box.cpu_h[10] * y + box.cpu_h[11] * z; + const double sy = box.cpu_h[12] * x + box.cpu_h[13] * y + box.cpu_h[14] * z; + const double sz = box.cpu_h[15] * x + box.cpu_h[16] * y + box.cpu_h[17] * z; + cell_id_x = floor(sx * box.thickness_x * rc_inv); + cell_id_y = floor(sy * box.thickness_y * rc_inv); + cell_id_z = floor(sz * box.thickness_z * rc_inv); + + while (cell_id_x < 0) + cell_id_x += nx; + while (cell_id_x >= nx) + cell_id_x -= nx; + while (cell_id_y < 0) + cell_id_y += ny; + while (cell_id_y >= ny) + cell_id_y -= ny; + while (cell_id_z < 0) + cell_id_z += nz; + while (cell_id_z >= nz) + cell_id_z -= nz; + if (partition_direction == 0) { + cell_id = cell_id_y + ny * (cell_id_z + nz * cell_id_x); + } else if (partition_direction == 1) { + cell_id = cell_id_x + nx * (cell_id_z + nz * cell_id_y); + } else { + cell_id = cell_id_x + nx * (cell_id_y + ny * cell_id_z); + } +} + +static __device__ void find_cell_id( + const int partition_direction, + const Box& box, + const double x, + const double y, + const double z, + const double rc_inv, + const int nx, + const int ny, + const int nz, + int& cell_id) +{ + int cell_id_x, cell_id_y, cell_id_z; + find_cell_id( + partition_direction, + box, + x, + y, + z, + rc_inv, + nx, + ny, + nz, + cell_id_x, + cell_id_y, + cell_id_z, + cell_id); +} + +static __global__ void find_cell_counts( + const int partition_direction, + const Box box, + const int N, + int* cell_count, + const double* x, + const double* y, + const double* z, + const int nx, + const int ny, + const int nz, + const double rc_inv) +{ + const int n1 = blockIdx.x * blockDim.x + threadIdx.x; + if (n1 < N) { + int cell_id; + find_cell_id(partition_direction, box, x[n1], y[n1], z[n1], rc_inv, nx, ny, nz, cell_id); + atomicAdd(&cell_count[cell_id], 1); + } +} + +static __global__ void find_cell_contents( + const int partition_direction, + const Box box, + const int N, + int* cell_count, + const int* cell_count_sum, + int* cell_contents, + const double* x, + const double* y, + const double* z, + const int nx, + const int ny, + const int nz, + const double rc_inv) +{ + const int n1 = blockIdx.x * blockDim.x + threadIdx.x; + if (n1 < N) { + int cell_id; + find_cell_id(partition_direction, box, x[n1], y[n1], z[n1], rc_inv, nx, ny, nz, cell_id); + const int ind = atomicAdd(&cell_count[cell_id], 1); + cell_contents[cell_count_sum[cell_id] + ind] = n1; + } +} + +static void __global__ set_to_zero(int size, int* data) +{ + int n = threadIdx.x + blockIdx.x * blockDim.x; + if (n < size) { + data[n] = 0; + } +} + +static void find_cell_list( + gpuStream_t& stream, + const int partition_direction, + const double rc, + const int* num_bins, + Box& box, + const int N, + const GPU_Vector& position_per_atom, + GPU_Vector& cell_count, + GPU_Vector& cell_count_sum, + GPU_Vector& cell_contents) +{ + const int offset = position_per_atom.size() / 3; + const int block_size = 256; + const int grid_size = (N - 1) / block_size + 1; + const double rc_inv = 1.0 / rc; + const double* x = position_per_atom.data(); + const double* y = position_per_atom.data() + offset; + const double* z = position_per_atom.data() + offset * 2; + const int N_cells = num_bins[0] * num_bins[1] * num_bins[2]; + + // number of cells is allowed to be larger than the number of atoms + if (N_cells > cell_count.size()) { + cell_count.resize(N_cells); + cell_count_sum.resize(N_cells); + } + + set_to_zero<<<(cell_count.size() - 1) / 64 + 1, 64, 0, stream>>>( + cell_count.size(), cell_count.data()); + GPU_CHECK_KERNEL + + set_to_zero<<<(cell_count_sum.size() - 1) / 64 + 1, 64, 0, stream>>>( + cell_count_sum.size(), cell_count_sum.data()); + GPU_CHECK_KERNEL + + set_to_zero<<<(cell_contents.size() - 1) / 64 + 1, 64, 0, stream>>>( + cell_contents.size(), cell_contents.data()); + GPU_CHECK_KERNEL + + find_cell_counts<<>>( + partition_direction, + box, + N, + cell_count.data(), + x, + y, + z, + num_bins[0], + num_bins[1], + num_bins[2], + rc_inv); + GPU_CHECK_KERNEL + + thrust::exclusive_scan( +#ifdef USE_HIP + thrust::hip::par.on(stream), +#else + thrust::cuda::par.on(stream), +#endif + cell_count.data(), + cell_count.data() + N_cells, + cell_count_sum.data()); + + set_to_zero<<<(cell_count.size() - 1) / 64 + 1, 64, 0, stream>>>( + cell_count.size(), cell_count.data()); + GPU_CHECK_KERNEL + + find_cell_contents<<>>( + partition_direction, + box, + N, + cell_count.data(), + cell_count_sum.data(), + cell_contents.data(), + x, + y, + z, + num_bins[0], + num_bins[1], + num_bins[2], + rc_inv); + GPU_CHECK_KERNEL +} diff --git a/src/force/nep_spin/mfield.cu b/src/force/nep_spin/mfield.cu new file mode 100644 index 000000000..23a6d8f53 --- /dev/null +++ b/src/force/nep_spin/mfield.cu @@ -0,0 +1,126 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#include "mfield.cuh" +#include "utilities/error.cuh" +#include "utilities/fractional_region.cuh" +#include "utilities/gpu_macro.cuh" +#include "utilities/read_file.cuh" +#include +#include + +// spin is in muB; this converts a tesla-valued B to magnetic force in eV/muB. +void Spin_Magnetic_Field::parse(const char** param, int num_param, const std::vector& group) +{ + mfield_use_region_ = num_param > 1 && strcmp(param[1], "region") == 0; + if (num_param != (mfield_use_region_ ? 11 : 6)) { + PRINT_INPUT_ERROR( + "add_mfield requires group_method group_id Bx By Bz or " + "region amin amax bmin bmax cmin cmax Bx By Bz."); + } + if (mfield_use_region_) { + for (int k = 0; k < 6; ++k) { + if (!is_valid_real(param[k + 2], &mfield_region_[k]) || + !std::isfinite(mfield_region_[k]) || mfield_region_[k] < 0.0 || + mfield_region_[k] > 1.0) { + PRINT_INPUT_ERROR("add_mfield region bounds must be finite numbers in [0, 1]."); + } + } + for (int k = 0; k < 6; k += 2) { + if (mfield_region_[k] >= mfield_region_[k + 1]) { + PRINT_INPUT_ERROR("add_mfield region minimum must be smaller than maximum."); + } + } + } else { + if (!is_valid_int(param[1], &mfield_group_method_) || + mfield_group_method_ < 0 || mfield_group_method_ >= group.size()) { + PRINT_INPUT_ERROR("add_mfield grouping method is invalid."); + } + if (!is_valid_int(param[2], &mfield_group_id_) || mfield_group_id_ < 0 || + mfield_group_id_ >= group[mfield_group_method_].number) { + PRINT_INPUT_ERROR("add_mfield group id is invalid."); + } + } + const int field_start = mfield_use_region_ ? 8 : 3; + constexpr double muB_eV_per_T = 5.7883818060e-5; + double field[3]; + mfield_enabled_ = false; + for (int k = 0; k < 3; ++k) { + if (!is_valid_real(param[k + field_start], &field[k]) || !std::isfinite(field[k])) { + PRINT_INPUT_ERROR("add_mfield components must be finite numbers in tesla."); + } + mfield_[k] = field[k] * muB_eV_per_T; + mfield_enabled_ = mfield_enabled_ || field[k] != 0.0; + } + printf("External magnetic field: (%g, %g, %g) T.\n", field[0], field[1], field[2]); + if (mfield_use_region_) { + printf(" fractional region [%g, %g) [%g, %g) [%g, %g).\n", + mfield_region_[0], mfield_region_[1], mfield_region_[2], + mfield_region_[3], mfield_region_[4], mfield_region_[5]); + } else { + printf(" grouping method %d, group %d.\n", mfield_group_method_, mfield_group_id_); + } +} + +template +static __global__ void add_mfield( + const int n, const int count, const int offset, const int* members, + const double hx, const double hy, const double hz, + const Box box, const double* position, + const double amin, const double amax, const double bmin, const double bmax, + const double cmin, const double cmax, + const double* spin, double* energy, double* mforce) +{ + const int tid = blockIdx.x * blockDim.x + threadIdx.x; + if (tid >= count) return; + const int i = UseRegion ? tid : members[offset + tid]; + if (UseRegion) { + double sa, sb, sc; + get_fractional_position(box, position[i], position[n + i], position[2 * n + i], sa, sb, sc); + if (!is_in_region(sa, sb, sc, amin, amax, bmin, bmax, cmin, cmax)) return; + } + energy[i] -= spin[i] * hx + spin[n + i] * hy + spin[2 * n + i] * hz; + mforce[i] += hx; + mforce[n + i] += hy; + mforce[2 * n + i] += hz; +} + +void Spin_Magnetic_Field::compute( + const Box& box, const GPU_Vector& position_per_atom, + const std::vector& group, const GPU_Vector& spin_per_atom, + GPU_Vector& potential_per_atom, GPU_Vector& mforce_per_atom) const +{ + const int number_of_atoms = spin_per_atom.size() / 3; + if (mfield_enabled_) { + if (mfield_use_region_) { + add_mfield<<<(number_of_atoms + 127) / 128, 128>>>( + number_of_atoms, number_of_atoms, 0, nullptr, mfield_[0], mfield_[1], mfield_[2], + box, position_per_atom.data(), mfield_region_[0], mfield_region_[1], + mfield_region_[2], mfield_region_[3], mfield_region_[4], mfield_region_[5], + spin_per_atom.data(), potential_per_atom.data(), mforce_per_atom.data()); + GPU_CHECK_KERNEL + } else { + const Group& selected = group[mfield_group_method_]; + const int count = selected.cpu_size[mfield_group_id_]; + if (count > 0) { + add_mfield<<<(count + 127) / 128, 128>>>( + number_of_atoms, count, selected.cpu_size_sum[mfield_group_id_], selected.contents.data(), + mfield_[0], mfield_[1], mfield_[2], box, nullptr, 0, 0, 0, 0, 0, 0, + spin_per_atom.data(), potential_per_atom.data(), mforce_per_atom.data()); + GPU_CHECK_KERNEL + } + } + } +} diff --git a/src/force/nep_spin/mfield.cuh b/src/force/nep_spin/mfield.cuh new file mode 100644 index 000000000..6d1656b7d --- /dev/null +++ b/src/force/nep_spin/mfield.cuh @@ -0,0 +1,40 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once + +#include "model/box.cuh" +#include "model/group.cuh" +#include "utilities/gpu_vector.cuh" +#include + +class Spin_Magnetic_Field +{ +public: + void parse(const char** param, int num_param, const std::vector& group); + bool enabled() const { return mfield_enabled_; } + void compute( + const Box& box, const GPU_Vector& position_per_atom, + const std::vector& group, const GPU_Vector& spin_per_atom, + GPU_Vector& potential_per_atom, GPU_Vector& mforce_per_atom) const; + +private: + int mfield_group_method_ = 0; + int mfield_group_id_ = 0; + bool mfield_use_region_ = false; + double mfield_region_[6] = {}; + bool mfield_enabled_ = false; + double mfield_[3] = {}; // eV/muB +}; diff --git a/src/force/nep_spin/nep_spin.cu b/src/force/nep_spin/nep_spin.cu new file mode 100644 index 000000000..5e3e3ac5f --- /dev/null +++ b/src/force/nep_spin/nep_spin.cu @@ -0,0 +1,2233 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + Copyright 2026 NEPAdapters contributors + This file is part of GPUMD and is distributed under LGPLv3 or later. + + The Spin3 protocol follows TorchNEP spin commit 3e2a5b3 and the matching + NEPAdapters dev implementation inspected on 2026-09-03 (GPLv3+). +*/ + +#include "nep_spin.cuh" +#include "utilities/nep_spin_model_file.cuh" +#include "force/nep_kernels.cuh" +#include "nep_spin_small_box.cuh" +#include "utilities/gpu_macro.cuh" +#include "utilities/nep_utilities.cuh" +#include "utilities/error.cuh" +#include +#include +#include +#include +#include +#include +#include + +namespace { + +using SimulationBox = Box; + +#include "nep_spin3_common.cuh" + +enum class SpinVirialMode : int { + disabled, + center_owned, + neighbor_owned, + center_and_neighbor_float_sink, +}; + +constexpr const char* kElementSymbols[NUM_ELEMENTS] = { + "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", "Na", "Mg", "Al", "Si", "P", "S", + "Cl", "Ar", "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", + "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", + "In", "Sn", "Sb", "Te", "I", "Xe", "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", + "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", + "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu"}; + +__device__ __forceinline__ void atomic_add_per_atom_virial_double( + const int atom_stride, + const int atom, + const float x12, + const float y12, + const float z12, + const float fx, + const float fy, + const float fz, + double* virial) +{ + atomicAdd(&virial[atom], -static_cast(x12 * fx)); + atomicAdd(&virial[atom_stride + atom], -static_cast(y12 * fy)); + atomicAdd(&virial[2 * atom_stride + atom], -static_cast(z12 * fz)); + atomicAdd(&virial[3 * atom_stride + atom], -static_cast(x12 * fy)); + atomicAdd(&virial[4 * atom_stride + atom], -static_cast(x12 * fz)); + atomicAdd(&virial[5 * atom_stride + atom], -static_cast(y12 * fz)); + atomicAdd(&virial[6 * atom_stride + atom], -static_cast(y12 * fx)); + atomicAdd(&virial[7 * atom_stride + atom], -static_cast(z12 * fx)); + atomicAdd(&virial[8 * atom_stride + atom], -static_cast(z12 * fy)); +} + +__device__ __forceinline__ void atomic_add_per_atom_virial_float( + const int atom_stride, + const int atom, + const float x12, + const float y12, + const float z12, + const float fx, + const float fy, + const float fz, + float* virial) +{ + atomicAdd(&virial[atom], -x12 * fx); + atomicAdd(&virial[atom_stride + atom], -y12 * fy); + atomicAdd(&virial[2 * atom_stride + atom], -z12 * fz); + atomicAdd(&virial[3 * atom_stride + atom], -x12 * fy); + atomicAdd(&virial[4 * atom_stride + atom], -x12 * fz); + atomicAdd(&virial[5 * atom_stride + atom], -y12 * fz); + atomicAdd(&virial[6 * atom_stride + atom], -y12 * fx); + atomicAdd(&virial[7 * atom_stride + atom], -z12 * fx); + atomicAdd(&virial[8 * atom_stride + atom], -z12 * fy); +} + +__device__ __forceinline__ void atomic_add_spin_transfer_float( + int, int, float, float, float, const float*, float*) +{ +} + +__global__ void mask_inactive_spin_mforce( + const int atom_count, + const int atom_stride, + const int* __restrict__ types, + const int* __restrict__ spin_dof_type_active, + double* __restrict__ mforce) +{ + const int atom = blockIdx.x * blockDim.x + threadIdx.x; + if (atom < atom_count && spin_dof_type_active[types[atom]] == 0) { + mforce[atom] = 0.0; + mforce[atom_stride + atom] = 0.0; + mforce[2 * atom_stride + atom] = 0.0; + } +} + +using SpinPolynomialLayout = NEP_Spin::Spin_Polynomial_Layout; + +template +__device__ __forceinline__ void evaluate_spin3_edge_weights_b9_f32( + const float spin_cutoff, + const float dist, + const int num_types, + const int type_pair, + const float* __restrict__ descriptor_coefficients, + const int spin_coefficient_offset, + float* weights, + float* weight_derivatives) +{ + constexpr int BasisCount = 9; + constexpr float Pi = 3.14159265358979323846f; + const int pair_count = num_types * num_types; + const float rcinv = 1.0f / spin_cutoff; + const float r_scaled = dist * rcinv; + const float phase = Pi * r_scaled; + const float fc = 0.5f * cosf(phase) + 0.5f; + const float shifted = r_scaled - 1.0f; + const float x = 2.0f * shifted * shifted - 1.0f; + const float dxdr = 2.0f * shifted * rcinv; + const float fcp = NeedDerivatives ? -0.5f * Pi * sinf(phase) * rcinv : 0.0f; + float fn[BasisCount] = {}; + float fnp[BasisCount] = {}; + fn[0] = fc; + fnp[0] = fcp; + const float raw1 = 0.5f * (x + 1.0f); + fn[1] = raw1 * fc; + fnp[1] = dxdr * fc + raw1 * fcp; + float t0 = 1.0f; + float t1 = x; + float u0 = 1.0f; + float u1 = 2.0f * x; + for (int n = 2; n < BasisCount; ++n) { + const float t2 = 2.0f * x * t1 - t0; + const float raw = 0.5f * (t2 + 1.0f); + fn[n] = raw * fc; + fnp[n] = static_cast(n) * u1 * dxdr * fc + raw * fcp; + const float u2 = 2.0f * x * u1 - u0; + t0 = t1; t1 = t2; u0 = u1; u1 = u2; + } + for (int c = 0; c < C; ++c) { + float weight = 0.0f; + float derivative = 0.0f; + for (int k = 0; k < BasisCount; ++k) { + const int index = spin_coefficient_offset + + (c * BasisCount + k) * pair_count + type_pair; + weight += fn[k] * descriptor_coefficients[index]; + if (NeedDerivatives) { + derivative += fnp[k] * descriptor_coefficients[index]; + } + } + weights[c] = weight; + if (NeedDerivatives) { + weight_derivatives[c] = derivative; + } + } +} + +template +__device__ __forceinline__ bool load_spin3_edge_f32( + const int atom, + const int neighbor, + const int atom_stride, + const int num_types, + const int spin_basis_size, + const float spin_cutoff, + const float* __restrict__ spin_cutoff_pair, + const SimulationBox box, + const int* __restrict__ types, + const double* __restrict__ positions_soa3, + const double* __restrict__ slot_r12, + const int r12_plane_size, + const int slot_index, + const double* __restrict__ spins_soa3, + const float* __restrict__ descriptor_coefficients, + const int spin_coefficient_offset, + float* rhat, + float& dist, + float* si, + float* sj, + float* weights, + float* weight_derivatives) +{ + if (slot_r12) { + const float dx = static_cast(slot_r12[slot_index]); + const float dy = static_cast(slot_r12[r12_plane_size + slot_index]); + const float dz = static_cast(slot_r12[2 * r12_plane_size + slot_index]); + dist = sqrtf(dx * dx + dy * dy + dz * dz); + if (dist > 1.0e-12f) { + const float inverse_distance = 1.0f / dist; + rhat[0] = dx * inverse_distance; + rhat[1] = dy * inverse_distance; + rhat[2] = dz * inverse_distance; + } + } else { + compute_spin_edge_geometry_f32( + atom, neighbor, atom_stride, box, positions_soa3, rhat, dist); + } + for (int d = 0; d < 3; ++d) { + si[d] = static_cast(spins_soa3[d * atom_stride + atom]); + sj[d] = static_cast(spins_soa3[d * atom_stride + neighbor]); + } + const int type_pair = types[atom] * num_types + types[neighbor]; + const float resolved_spin_cutoff = + spin_cutoff_pair == nullptr ? spin_cutoff : spin_cutoff_pair[type_pair]; + if (!(dist > 1.0e-12f && dist < resolved_spin_cutoff) || spin_basis_size != 8) { + return false; + } + evaluate_spin3_edge_weights_b9_f32( + resolved_spin_cutoff, + dist, + num_types, + type_pair, + descriptor_coefficients, + spin_coefficient_offset, + weights, + weight_derivatives); + return true; +} + +#include "nep_spin3_layout.cuh" +#include "nep_spin3_descriptor.cuh" +#include "nep_spin3_force.cuh" + +__device__ int required_small_box_capacity[1]; + +__global__ void find_local_neighbors_spin( + const int N, + const Box box, + const float cutoff_radial_square, + const float cutoff_angular_square, + const float cutoff_spin_square, + const double* __restrict__ x, + const double* __restrict__ y, + const double* __restrict__ z, + const int* __restrict__ NN_global, + const int* __restrict__ NL_global, + int* NN_radial, + int* NL_radial, + int* NN_angular, + int* NL_angular, + int* NN_spin, + int* NL_spin) +{ + const int n1 = blockIdx.x * blockDim.x + threadIdx.x; + if (n1 >= N) { + return; + } + + const double x1 = x[n1]; + const double y1 = y[n1]; + const double z1 = z[n1]; + int count_radial = 0; + int count_angular = 0; + int count_spin = 0; + + for (int slot = 0; slot < NN_global[n1]; ++slot) { + const int n2 = NL_global[static_cast(N) * slot + n1]; + float x12 = x[n2] - x1; + float y12 = y[n2] - y1; + float z12 = z[n2] - z1; + apply_mic(box, x12, y12, z12); + const float distance_square = x12 * x12 + y12 * y12 + z12 * z12; + + if (distance_square < cutoff_radial_square) { + NL_radial[static_cast(N) * count_radial++ + n1] = n2; + } + if (distance_square < cutoff_angular_square) { + NL_angular[static_cast(N) * count_angular++ + n1] = n2; + } + if (distance_square < cutoff_spin_square) { + NL_spin[static_cast(N) * count_spin++ + n1] = n2; + } + } + + NN_radial[n1] = count_radial; + NN_angular[n1] = count_angular; + NN_spin[n1] = count_spin; +} + +__device__ __forceinline__ void apply_mic_spin_small_box( + const Box& box, const NEP::ExpandedBox& ebox, double& x12, double& y12, double& z12) +{ + double sx12 = + (box.cpu_h[9] * x12 + box.cpu_h[10] * y12 + box.cpu_h[11] * z12) / + ebox.num_cells[0]; + double sy12 = + (box.cpu_h[12] * x12 + box.cpu_h[13] * y12 + box.cpu_h[14] * z12) / + ebox.num_cells[1]; + double sz12 = + (box.cpu_h[15] * x12 + box.cpu_h[16] * y12 + box.cpu_h[17] * z12) / + ebox.num_cells[2]; + if (box.pbc_x == 1) + sx12 -= nearbyint(sx12); + if (box.pbc_y == 1) + sy12 -= nearbyint(sy12); + if (box.pbc_z == 1) + sz12 -= nearbyint(sz12); + x12 = box.cpu_h[0] * ebox.num_cells[0] * sx12 + + box.cpu_h[1] * ebox.num_cells[1] * sy12 + + box.cpu_h[2] * ebox.num_cells[2] * sz12; + y12 = box.cpu_h[3] * ebox.num_cells[0] * sx12 + + box.cpu_h[4] * ebox.num_cells[1] * sy12 + + box.cpu_h[5] * ebox.num_cells[2] * sz12; + z12 = box.cpu_h[6] * ebox.num_cells[0] * sx12 + + box.cpu_h[7] * ebox.num_cells[1] * sy12 + + box.cpu_h[8] * ebox.num_cells[2] * sz12; +} + +__global__ void find_neighbor_list_spin_small_box( + const NEP::ParaMB paramb, + const float spin_cutoff, + const int N, + const Box box, + const NEP::ExpandedBox ebox, + const int capacity, + const int* type, + const double* x, + const double* y, + const double* z, + int* NN_radial, + int* NL_radial, + int* NN_angular, + int* NL_angular, + int* NN_spin, + int* NL_spin, + double* r12_radial, + double* r12_angular, + double* r12_spin, + int* required_capacity) +{ + const int n1 = blockIdx.x * blockDim.x + threadIdx.x; + if (n1 >= N) { + return; + } + const double x1 = x[n1]; + const double y1 = y[n1]; + const double z1 = z[n1]; + const int t1 = type[n1]; + const int plane_size = N * capacity; + int count_radial = 0; + int count_angular = 0; + int count_spin = 0; + for (int n2 = 0; n2 < N; ++n2) { + for (int ia = 0; ia < ebox.num_cells[0]; ++ia) { + for (int ib = 0; ib < ebox.num_cells[1]; ++ib) { + for (int ic = 0; ic < ebox.num_cells[2]; ++ic) { + if (n1 == n2 && ia == 0 && ib == 0 && ic == 0) { + continue; + } + double x12 = x[n2] + box.cpu_h[0] * ia + box.cpu_h[1] * ib + + box.cpu_h[2] * ic - x1; + double y12 = y[n2] + box.cpu_h[3] * ia + box.cpu_h[4] * ib + + box.cpu_h[5] * ic - y1; + double z12 = z[n2] + box.cpu_h[6] * ia + box.cpu_h[7] * ib + + box.cpu_h[8] * ic - z1; + apply_mic_spin_small_box(box, ebox, x12, y12, z12); + const double d2 = x12 * x12 + y12 * y12 + z12 * z12; + const int t2 = type[n2]; + const float rc_radial = 0.5f * (paramb.rc_radial[t1] + paramb.rc_radial[t2]); + const float rc_angular = 0.5f * (paramb.rc_angular[t1] + paramb.rc_angular[t2]); + if (d2 < rc_radial * rc_radial) { + const int slot = count_radial++; + if (slot < capacity) { + const int index = n1 + N * slot; + NL_radial[index] = n2; + r12_radial[index] = x12; + r12_radial[plane_size + index] = y12; + r12_radial[2 * plane_size + index] = z12; + } + } + if (d2 < rc_angular * rc_angular) { + const int slot = count_angular++; + if (slot < capacity) { + const int index = n1 + N * slot; + NL_angular[index] = n2; + r12_angular[index] = x12; + r12_angular[plane_size + index] = y12; + r12_angular[2 * plane_size + index] = z12; + } + } + if (d2 < spin_cutoff * spin_cutoff) { + const int slot = count_spin++; + if (slot < capacity) { + const int index = n1 + N * slot; + NL_spin[index] = n2; + r12_spin[index] = x12; + r12_spin[plane_size + index] = y12; + r12_spin[2 * plane_size + index] = z12; + } + } + } + } + } + } + NN_radial[n1] = min(count_radial, capacity); + NN_angular[n1] = min(count_angular, capacity); + NN_spin[n1] = min(count_spin, capacity); + atomicMax(required_capacity, max(count_radial, max(count_angular, count_spin))); +} + +__global__ void find_structural_descriptor( + const NEP::ParaMB paramb, + const NEP::ANN ann, + const int N, + const Box box, + const int* NN_radial, + const int* NL_radial, + const int* NN_angular, + const int* NL_angular, + const double* r12_radial, + const double* r12_angular, + const int r12_plane_size, + const int* type, + const double* x, + const double* y, + const double* z, + float* descriptor, + float* sum_fxyz) +{ + const int n1 = blockIdx.x * blockDim.x + threadIdx.x; + if (n1 >= N) { + return; + } + const int t1 = type[n1]; + const double x1 = x[n1]; + const double y1 = y[n1]; + const double z1 = z[n1]; + float q[MAX_DIM] = {0.0f}; + + for (int i1 = 0; i1 < NN_radial[n1]; ++i1) { + const int n2 = NL_radial[static_cast(N) * i1 + n1]; + const int slot = N * i1 + n1; + double x12 = r12_radial ? r12_radial[slot] : x[n2] - x1; + double y12 = r12_radial ? r12_radial[r12_plane_size + slot] : y[n2] - y1; + double z12 = r12_radial ? r12_radial[2 * r12_plane_size + slot] : z[n2] - z1; + if (!r12_radial) { + apply_mic(box, x12, y12, z12); + } + const float d12 = sqrtf(x12 * x12 + y12 * y12 + z12 * z12); + const int t2 = type[n2]; + const float rc = (paramb.rc_radial[t1] + paramb.rc_radial[t2]) * 0.5f; + const float rcinv = 1.0f / rc; + float fc12; + find_fc(rc, rcinv, d12, fc12); + float fn12[MAX_NUM_N]; + find_fn(paramb.basis_size_radial, rcinv, d12, fc12, fn12); + const int basis_count = + (paramb.n_max_radial + 1) * (paramb.basis_size_radial + 1); + for (int n = 0; n <= paramb.n_max_radial; ++n) { + float gn12 = 0.0f; + for (int k = 0; k <= paramb.basis_size_radial; ++k) { + const int basis = n * (paramb.basis_size_radial + 1) + k; + gn12 += fn12[k] * ann.c_type_pair[(t1 * paramb.num_types + t2) * basis_count + basis]; + } + q[n] += gn12; + } + } + + for (int n = 0; n <= paramb.n_max_angular; ++n) { + float s[NUM_OF_ABC] = {0.0f}; + const int abc_count = (paramb.L_max + 1) * (paramb.L_max + 1) - 1; + for (int i1 = 0; i1 < NN_angular[n1]; ++i1) { + const int n2 = NL_angular[n1 + N * i1]; + const int slot = N * i1 + n1; + double x12 = r12_angular ? r12_angular[slot] : x[n2] - x1; + double y12 = r12_angular ? r12_angular[r12_plane_size + slot] : y[n2] - y1; + double z12 = r12_angular ? r12_angular[2 * r12_plane_size + slot] : z[n2] - z1; + if (!r12_angular) { + apply_mic(box, x12, y12, z12); + } + const float d12 = sqrtf(x12 * x12 + y12 * y12 + z12 * z12); + const int t2 = type[n2]; + const float rc = (paramb.rc_angular[t1] + paramb.rc_angular[t2]) * 0.5f; + const float rcinv = 1.0f / rc; + float fc12; + find_fc(rc, rcinv, d12, fc12); + float fn12[MAX_NUM_N]; + find_fn(paramb.basis_size_angular, rcinv, d12, fc12, fn12); + float gn12 = 0.0f; + for (int k = 0; k <= paramb.basis_size_angular; ++k) { + int c_index = paramb.num_c_radial; + c_index += (t1 * paramb.num_types + t2) * + ((paramb.n_max_angular + 1) * (paramb.basis_size_angular + 1)); + c_index += n * (paramb.basis_size_angular + 1) + k; + gn12 += fn12[k] * ann.c_type_pair[c_index]; + } + accumulate_s(paramb.L_max, d12, x12, y12, z12, gn12, s); + } + find_q( + paramb.L_max, + paramb.has_q_222, + paramb.has_q_1111, + paramb.has_q_112, + paramb.has_q_123, + paramb.has_q_233, + paramb.has_q_134, + paramb.n_max_angular + 1, + n, + s, + q + paramb.n_max_radial + 1); + for (int abc = 0; abc < abc_count; ++abc) { + sum_fxyz[static_cast(N) * (n * abc_count + abc) + n1] = s[abc]; + } + } + const int struct_dim = paramb.n_max_radial + 1 + paramb.dim_angular; + for (int d = 0; d < struct_dim; ++d) { + descriptor[static_cast(N) * d + n1] = q[d]; + } +} + +__global__ void find_potential( + const int N, + const int descriptor_dim, + const int hidden_neurons, + const int num_types, + const int* type, + const float* descriptor, + const float* parameters, + const float* q_scaler, + const double* energy_reference, + double* potential, + float* Fp) +{ + const int atom = blockIdx.x * blockDim.x + threadIdx.x; + if (atom >= N) { + return; + } + const int atom_type = type[atom]; + const std::size_t type_block = + static_cast(hidden_neurons) * (descriptor_dim + 2); + const float* w0 = parameters + static_cast(atom_type) * type_block; + const float* b0 = w0 + static_cast(hidden_neurons) * descriptor_dim; + const float* w1 = b0 + hidden_neurons; + const float* b1 = parameters + static_cast(num_types) * type_block; + float q[MAX_DIM_SPIN] = {0.0f}; + for (int d = 0; d < descriptor_dim; ++d) { + q[d] = descriptor[static_cast(N) * d + atom] * q_scaler[d]; + } + float energy = 0.0f; + float fp[MAX_DIM_SPIN] = {0.0f}; + for (int neuron = 0; neuron < hidden_neurons; ++neuron) { + float projection = 0.0f; + for (int d = 0; d < descriptor_dim; ++d) { + projection += w0[neuron * descriptor_dim + d] * q[d]; + } + const float activation = tanhf(projection - b0[neuron]); + const float activation_derivative = 1.0f - activation * activation; + energy += w1[neuron] * activation; + for (int d = 0; d < descriptor_dim; ++d) { + fp[d] += w1[neuron] * activation_derivative * + w0[neuron * descriptor_dim + d]; + } + } + energy -= b1[0]; + potential[atom] += + static_cast(energy) + static_cast(energy_reference[atom_type]); + for (int d = 0; d < descriptor_dim; ++d) { + Fp[static_cast(N) * d + atom] = fp[d] * q_scaler[d]; + } +} + +template +__global__ void find_potential_warp( + const int N, + const int descriptor_dim, + const int hidden_neurons, + const int num_types, + const int* __restrict__ type, + const float* __restrict__ descriptor, + const float* __restrict__ parameters, + const float* __restrict__ q_scaler, + const double* __restrict__ energy_reference, + double* potential, + float* __restrict__ Fp) +{ + static_assert(32 % lanes_per_atom == 0, "one warp must contain complete atom tiles"); + constexpr int warps_per_block = 4; + constexpr int atoms_per_warp = 32 / lanes_per_atom; + constexpr int atoms_per_block = warps_per_block * atoms_per_warp; + const int warp = threadIdx.x >> 5; + const int lane = threadIdx.x & 31; + const int atom_lane = lane / lanes_per_atom; + const int work_lane = lane - atom_lane * lanes_per_atom; + const int atom_local = warp * atoms_per_warp + atom_lane; + const int atom = blockIdx.x * atoms_per_block + atom_local; + const unsigned int atom_mask = + ((1u << lanes_per_atom) - 1u) << (atom_lane * lanes_per_atom); + + extern __shared__ float state[]; + float* q = state + static_cast(atom_local) * descriptor_dim; + float* hidden_delta = + state + static_cast(atoms_per_block) * descriptor_dim + + static_cast(atom_local) * hidden_neurons; + + if (atom < N) { + for (int d = work_lane; d < descriptor_dim; d += lanes_per_atom) { + q[d] = descriptor[static_cast(N) * d + atom] * q_scaler[d]; + } + } + __syncwarp(atom_mask); + if (atom >= N) { + return; + } + + const int atom_type = type[atom]; + const std::size_t type_block = + static_cast(hidden_neurons) * (descriptor_dim + 2); + const float* w0 = parameters + static_cast(atom_type) * type_block; + const float* b0 = w0 + static_cast(hidden_neurons) * descriptor_dim; + const float* w1 = b0 + hidden_neurons; + const float* b1 = parameters + static_cast(num_types) * type_block; + + float energy = 0.0f; + for (int neuron = work_lane; neuron < hidden_neurons; neuron += lanes_per_atom) { + float projection = 0.0f; + for (int d = 0; d < descriptor_dim; ++d) { + projection += w0[neuron * descriptor_dim + d] * q[d]; + } + const float activation = tanhf(projection - b0[neuron]); + const float delta = w1[neuron] * (1.0f - activation * activation); + hidden_delta[neuron] = delta; + energy += w1[neuron] * activation; + } + for (int offset = lanes_per_atom / 2; offset > 0; offset >>= 1) { + energy += __shfl_down_sync(atom_mask, energy, offset, lanes_per_atom); + } + __syncwarp(atom_mask); + + if (work_lane == 0) { + energy -= b1[0]; + potential[atom] += + static_cast(energy) + static_cast(energy_reference[atom_type]); + } + for (int d = work_lane; d < descriptor_dim; d += lanes_per_atom) { + float fp = 0.0f; + for (int neuron = 0; neuron < hidden_neurons; ++neuron) { + fp += hidden_delta[neuron] * w0[neuron * descriptor_dim + d]; + } + Fp[static_cast(N) * d + atom] = fp * q_scaler[d]; + } +} + +template +__global__ void find_force_angular_warp( + const NEP::ParaMB paramb, + const NEP::ANN ann, + const int N, + const Box box, + const int* NN_angular, + const int* NL_angular, + const int* __restrict__ type, + const double* __restrict__ x, + const double* __restrict__ y, + const double* __restrict__ z, + const float* __restrict__ Fp, + const float* __restrict__ sum_fxyz, + double* force, + double* virial) +{ + static_assert(atoms_per_warp * edge_lanes == 32, "one tile must fill one warp"); + constexpr int warps_per_block = 4; + constexpr int centers_per_block = warps_per_block * atoms_per_warp; + const int warp = threadIdx.x >> 5; + const int lane = threadIdx.x & 31; + const int atom_lane = lane / edge_lanes; + const int edge_lane = lane - atom_lane * edge_lanes; + const unsigned int center_mask = + (0xffffffffu >> (32 - edge_lanes)) << (atom_lane * edge_lanes); + const int center_local = warp * atoms_per_warp + atom_lane; + const int n1 = blockIdx.x * centers_per_block + center_local; + + const int abc_count = (paramb.L_max + 1) * (paramb.L_max + 1) - 1; + const int sum_count = (paramb.n_max_angular + 1) * NUM_OF_ABC; + const int state_size = paramb.dim_angular + sum_count; + extern __shared__ float center_state[]; + float* center_Fp = center_state + center_local * state_size; + float* center_sum_fxyz = center_Fp + paramb.dim_angular; + + if (n1 < N) { + for (int d = edge_lane; d < paramb.dim_angular; d += edge_lanes) { + center_Fp[d] = Fp[static_cast(N) * (paramb.n_max_radial + 1 + d) + n1]; + } + const int compact_sum_count = (paramb.n_max_angular + 1) * abc_count; + for (int d = edge_lane; d < compact_sum_count; d += edge_lanes) { + const int n = d / abc_count; + const int abc = d - n * abc_count; + center_sum_fxyz[n * NUM_OF_ABC + abc] = + sum_fxyz[static_cast(N) * d + n1]; + } + } + __syncwarp(); + + if (n1 >= N) { + return; + } + const int t1 = type[n1]; + const double x1 = x[n1]; + const double y1 = y[n1]; + const double z1 = z[n1]; + float center_force[3] = {}; + for (int i1 = edge_lane; i1 < NN_angular[n1]; i1 += edge_lanes) { + const int index = i1 * N + n1; + const int n2 = NL_angular[index]; + float x12 = x[n2] - x1; + float y12 = y[n2] - y1; + float z12 = z[n2] - z1; + apply_mic(box, x12, y12, z12); + float r12[3] = {x12, y12, z12}; + const float d12 = sqrt(r12[0] * r12[0] + r12[1] * r12[1] + r12[2] * r12[2]); + float f12[3] = {0.0f}; + float fc12; + float fcp12; + const int t2 = type[n2]; + const float rc = (paramb.rc_angular[t1] + paramb.rc_angular[t2]) * 0.5f; + const float rcinv = 1.0f / rc; + find_fc_and_fcp(rc, rcinv, d12, fc12, fcp12); + + float fn12[MAX_NUM_N]; + float fnp12[MAX_NUM_N]; + find_fn_and_fnp( + paramb.basis_size_angular, rcinv, d12, fc12, fcp12, fn12, fnp12); + for (int n = 0; n <= paramb.n_max_angular; ++n) { + float gn12 = 0.0f; + float gnp12 = 0.0f; + for (int k = 0; k <= paramb.basis_size_angular; ++k) { + int c_index = paramb.num_c_radial; + c_index += (t1 * paramb.num_types + t2) * + ((paramb.n_max_angular + 1) * (paramb.basis_size_angular + 1)); + c_index += n * (paramb.basis_size_angular + 1) + k; + gn12 += fn12[k] * ann.c_type_pair[c_index]; + gnp12 += fnp12[k] * ann.c_type_pair[c_index]; + } + if (l4_q222_only) { + accumulate_f12( + 4, + true, + false, + false, + false, + false, + false, + 5, + n, + paramb.n_max_angular + 1, + d12, + r12, + gn12, + gnp12, + center_Fp, + center_sum_fxyz, + f12); + } else { + accumulate_f12( + paramb.L_max, + paramb.has_q_222, + paramb.has_q_1111, + paramb.has_q_112, + paramb.has_q_123, + paramb.has_q_233, + paramb.has_q_134, + paramb.num_L, + n, + paramb.n_max_angular + 1, + d12, + r12, + gn12, + gnp12, + center_Fp, + center_sum_fxyz, + f12); + } + } + // One directed response contributes +f12 to its center and -f12 to its + // neighbor. The neighbor-owned virial is (-r12) tensor f12. + for (int d = 0; d < 3; ++d) { + center_force[d] += f12[d]; + atomicAdd(force + d * N + n2, -static_cast(f12[d])); + } + for (int a = 0; a < 3; ++a) { + for (int b = 0; b < 3; ++b) { + const int component = virial_internal_component(3 * a + b); + atomicAdd( + virial + component * N + n2, + -static_cast(r12[a] * f12[b])); + } + } + } + for (int offset = edge_lanes / 2; offset > 0; offset >>= 1) { + for (int d = 0; d < 3; ++d) { + center_force[d] += + __shfl_down_sync(center_mask, center_force[d], offset, edge_lanes); + } + } + if (edge_lane == 0) { + for (int d = 0; d < 3; ++d) { + atomicAdd(force + d * N + n1, static_cast(center_force[d])); + } + } +} + +template +void launch_force_angular_warp( + const NEP::ParaMB& paramb, + const NEP::ANN& ann, + const Box& box, + const GPU_Vector& type, + const GPU_Vector& position, + const NEP_Spin_Data& data, + GPU_Vector& force, + GPU_Vector& virial, + const int grid_size, + const int block_size, + const std::size_t shared_size) +{ + const int N = type.size(); + find_force_angular_warp + <<>>( + paramb, + ann, + N, + box, + data.NN_angular.data(), + data.NL_angular.data(), + type.data(), + position.data(), + position.data() + N, + position.data() + 2 * N, + data.Fp.data(), + data.sum_fxyz.data(), + force.data(), + virial.data()); +} + +std::vector split(const std::string& line) +{ + std::istringstream input(line); + std::vector tokens; + std::string token; + while (input >> token) { + tokens.push_back(token); + } + return tokens; +} + +std::vector next_tokens(std::istream& input) +{ + std::string line; + while (std::getline(input, line)) { + std::vector tokens = split(line); + if (!tokens.empty()) { + return tokens; + } + } + return {}; +} + +int parse_int(const std::string& token) +{ + std::size_t end = 0; + const long value = std::stol(token, &end); + if (end != token.size() || value < std::numeric_limits::min() || + value > std::numeric_limits::max()) { + throw std::runtime_error("invalid integer token: " + token); + } + return static_cast(value); +} + +double parse_double(const std::string& token) +{ + std::size_t end = 0; + const double value = std::stod(token, &end); + if (end != token.size() || !std::isfinite(value)) { + throw std::runtime_error("invalid finite numeric token: " + token); + } + return value; +} + +float parse_float(const std::string& token) +{ + const double value = parse_double(token); + if (std::abs(value) > std::numeric_limits::max()) { + throw std::runtime_error("model parameter is outside the float range"); + } + return static_cast(value); +} + +void require_line( + const std::vector& tokens, const char* name, const std::size_t arity) +{ + if (tokens.size() != arity || tokens.empty() || tokens[0] != name) { + throw std::runtime_error( + std::string("expected exact '") + name + "' line with " + + std::to_string(arity - 1) + " value(s)"); + } +} + +bool parse_flag(const std::string& token, const char* name, const bool allow_legacy_two = false) +{ + const int value = parse_int(token); + if (value != 0 && value != 1 && !(allow_legacy_two && value == 2)) { + throw std::runtime_error(std::string(name) + " must be 0 or 1"); + } + return value != 0; +} + +void check_unique_elements(const std::vector& elements) +{ + const std::set unique(elements.begin(), elements.end()); + if (unique.size() != elements.size()) { + throw std::runtime_error("model element symbols must be unique"); + } +} + +std::vector parse_active_types( + const std::vector& tokens, + const std::vector& elements, + const char* name) +{ + if (tokens.size() < 2) { + throw std::runtime_error(std::string(name) + " must enable at least one model type"); + } + std::vector active(elements.size(), 0); + for (std::size_t index = 1; index < tokens.size(); ++index) { + const auto found = std::find(elements.begin(), elements.end(), tokens[index]); + if (found == elements.end()) { + throw std::runtime_error(std::string("unknown ") + name + " model type"); + } + const std::size_t type = static_cast(found - elements.begin()); + if (active[type] != 0) { + throw std::runtime_error(std::string("duplicate model type in ") + name); + } + active[type] = 1; + } + return active; +} + +template +void launch_spin3_descriptors_typed( + const NEP_Spin::Model& model, + const Box& box, + const GPU_Vector& type, + const GPU_Vector& position, + const GPU_Vector& spin, + NEP_Spin_Data& data, + const double* slot_r12 = nullptr, + int r12_plane_size = 0, + gpuStream_t stream = nullptr) +{ + constexpr int block_size = 128; + const int N = type.size(); + const int density_work = C * N; + build_spin3_oc_density_bank<<< + (density_work + block_size - 1) / block_size, block_size, 0, stream>>>( + model.spin_polynomial_layout, + N, + N, + model.struct_descriptor_dim, + model.num_types, + model.spin_basis_size[0], + static_cast(model.spin_cutoff), + data.spin_cutoff_pair.data(), + static_cast(model.radial_parameter_count + model.angular_parameter_count), + box, + type.data(), + data.spin_dof_type_active.data(), + data.spin_env_type_active.data(), + position.data(), + slot_r12, + r12_plane_size, + spin.data(), + data.NN_spin.data(), + data.NL_spin.data(), + data.descriptor_parameters_type_pair.data(), + data.descriptor.data(), + data.spin3_moments.data()); + contract_spin3_oc_descriptors<<< + (N + block_size - 1) / block_size, block_size, 0, stream>>>( + model.spin_polynomial_layout, + N, + N, + model.struct_descriptor_dim, + type.data(), + data.spin_dof_type_active.data(), + spin.data(), + data.spin_projection_parameters.data(), + data.spin3_moments.data(), + data.descriptor.data()); + GPU_CHECK_KERNEL +} + +void launch_spin3_descriptors( + const NEP_Spin::Model& model, + const Box& box, + const GPU_Vector& type, + const GPU_Vector& position, + const GPU_Vector& spin, + NEP_Spin_Data& data, + const double* slot_r12 = nullptr, + int r12_plane_size = 0, + gpuStream_t stream = nullptr) +{ + switch (model.spin_compress) { + case 1: launch_spin3_descriptors_typed<1>(model, box, type, position, spin, data, slot_r12, r12_plane_size, stream); break; + case 2: launch_spin3_descriptors_typed<2>(model, box, type, position, spin, data, slot_r12, r12_plane_size, stream); break; + case 3: launch_spin3_descriptors_typed<3>(model, box, type, position, spin, data, slot_r12, r12_plane_size, stream); break; + case 4: launch_spin3_descriptors_typed<4>(model, box, type, position, spin, data, slot_r12, r12_plane_size, stream); break; + case 5: launch_spin3_descriptors_typed<5>(model, box, type, position, spin, data, slot_r12, r12_plane_size, stream); break; + case 6: launch_spin3_descriptors_typed<6>(model, box, type, position, spin, data, slot_r12, r12_plane_size, stream); break; + case 7: launch_spin3_descriptors_typed<7>(model, box, type, position, spin, data, slot_r12, r12_plane_size, stream); break; + case 8: launch_spin3_descriptors_typed<8>(model, box, type, position, spin, data, slot_r12, r12_plane_size, stream); break; + case 9: launch_spin3_descriptors_typed<9>(model, box, type, position, spin, data, slot_r12, r12_plane_size, stream); break; + } +} + +template +void launch_spin3_forces_typed( + const NEP_Spin::Model& model, + const Box& box, + const GPU_Vector& type, + const GPU_Vector& position, + const GPU_Vector& spin, + NEP_Spin_Data& data, + GPU_Vector& force, + GPU_Vector& mforce, + GPU_Vector& virial, + const double* slot_r12 = nullptr, + int r12_plane_size = 0) +{ + using Tile = Spin3ForceTile; + constexpr int block_size = Tile::block_size; + const int N = type.size(); + constexpr int atoms_per_warp = Tile::atoms_per_warp; + constexpr int centers_per_block = Tile::centers_per_block; + const int grid_size = (N - 1) / centers_per_block + 1; + const std::size_t shared_size = + static_cast(centers_per_block) * + model.spin_polynomial_layout.moment_count * sizeof(float); + accumulate_spin3_oc_native_forces< + C, SpinVirialMode::center_owned, false, atoms_per_warp> + <<>>( + model.spin_polynomial_layout, + N, + N, + model.struct_descriptor_dim, + model.num_types, + model.spin_basis_size[0], + static_cast(model.spin_cutoff), + data.spin_cutoff_pair.data(), + box, + type.data(), + data.spin_dof_type_active.data(), + data.spin_env_type_active.data(), + position.data(), + slot_r12, + r12_plane_size, + spin.data(), + data.NN_spin.data(), + data.NL_spin.data(), + data.Fp.data(), + data.descriptor_parameters_type_pair.data(), + data.spin_projection_parameters.data(), + data.spin3_moments.data(), + static_cast(model.radial_parameter_count + model.angular_parameter_count), + force.data(), + mforce.data(), + virial.data(), + nullptr, + nullptr); + GPU_CHECK_KERNEL +} + +void launch_spin3_forces( + const NEP_Spin::Model& model, + const Box& box, + const GPU_Vector& type, + const GPU_Vector& position, + const GPU_Vector& spin, + NEP_Spin_Data& data, + GPU_Vector& force, + GPU_Vector& mforce, + GPU_Vector& virial, + const double* slot_r12 = nullptr, + int r12_plane_size = 0) +{ + switch (model.spin_compress) { + case 1: launch_spin3_forces_typed<1>(model, box, type, position, spin, data, force, mforce, virial, slot_r12, r12_plane_size); break; + case 2: launch_spin3_forces_typed<2>(model, box, type, position, spin, data, force, mforce, virial, slot_r12, r12_plane_size); break; + case 3: launch_spin3_forces_typed<3>(model, box, type, position, spin, data, force, mforce, virial, slot_r12, r12_plane_size); break; + case 4: launch_spin3_forces_typed<4>(model, box, type, position, spin, data, force, mforce, virial, slot_r12, r12_plane_size); break; + case 5: launch_spin3_forces_typed<5>(model, box, type, position, spin, data, force, mforce, virial, slot_r12, r12_plane_size); break; + case 6: launch_spin3_forces_typed<6>(model, box, type, position, spin, data, force, mforce, virial, slot_r12, r12_plane_size); break; + case 7: launch_spin3_forces_typed<7>(model, box, type, position, spin, data, force, mforce, virial, slot_r12, r12_plane_size); break; + case 8: launch_spin3_forces_typed<8>(model, box, type, position, spin, data, force, mforce, virial, slot_r12, r12_plane_size); break; + case 9: launch_spin3_forces_typed<9>(model, box, type, position, spin, data, force, mforce, virial, slot_r12, r12_plane_size); break; + } + const bool has_inactive_dof = std::any_of( + model.spin_dof_type_active.begin(), + model.spin_dof_type_active.end(), + [](const int active) { return active == 0; }); + if (has_inactive_dof) { + constexpr int block_size = 128; + const int grid_size = (type.size() - 1) / block_size + 1; + mask_inactive_spin_mforce<<>>( + type.size(), type.size(), type.data(), data.spin_dof_type_active.data(), mforce.data()); + } + GPU_CHECK_KERNEL +} + +template +__global__ void find_spin_zbl_force( + const NEP::ParaMB paramb, + const int atom_count, + const NEP::ZBL zbl, + const Box box, + const int* neighbor_count, + const int* neighbor_list, + const int* type, + const double* x, + const double* y, + const double* z, + const double* r12x, + const double* r12y, + const double* r12z, + double* force_x, + double* force_y, + double* force_z, + double* virial, + double* potential) +{ + const int atom1 = blockIdx.x * blockDim.x + threadIdx.x; + if (atom1 >= atom_count) { + return; + } + float energy = 0.0f; + float force_sum[3] = {}; + float virial_sum[9] = {}; + const int type1 = type[atom1]; + const int atomic_number1 = zbl.atomic_numbers[type1]; + const float atomic_number_power1 = powf(static_cast(atomic_number1), 0.23f); + for (int neighbor = 0; neighbor < neighbor_count[atom1]; ++neighbor) { + const int index = atom1 + atom_count * neighbor; + const int atom2 = neighbor_list[index]; + float displacement[3]; + if (SmallBox) { + displacement[0] = static_cast(r12x[index]); + displacement[1] = static_cast(r12y[index]); + displacement[2] = static_cast(r12z[index]); + } else { + displacement[0] = static_cast(x[atom2] - x[atom1]); + displacement[1] = static_cast(y[atom2] - y[atom1]); + displacement[2] = static_cast(z[atom2] - z[atom1]); + apply_mic(box, displacement[0], displacement[1], displacement[2]); + } + const float distance = sqrtf( + displacement[0] * displacement[0] + + displacement[1] * displacement[1] + + displacement[2] * displacement[2]); + const float inverse_distance = 1.0f / distance; + const int type2 = type[atom2]; + const int atomic_number2 = zbl.atomic_numbers[type2]; + const float inverse_screening_length = + (atomic_number_power1 + powf(static_cast(atomic_number2), 0.23f)) * + 2.134563f; + const float charge_product = K_C_SP * atomic_number1 * atomic_number2; + float pair_energy = 0.0f; + float pair_derivative = 0.0f; + float inner_cutoff = zbl.rc_inner; + float outer_cutoff = zbl.rc_outer; + if (paramb.use_typewise_cutoff_zbl) { + outer_cutoff = min( + (COVALENT_RADIUS[atomic_number1 - 1] + + COVALENT_RADIUS[atomic_number2 - 1]) * + paramb.typewise_cutoff_zbl_factor, + outer_cutoff); + inner_cutoff = 0.0f; + } + find_f_and_fp_zbl( + charge_product, + inverse_screening_length, + inner_cutoff, + outer_cutoff, + distance, + inverse_distance, + pair_energy, + pair_derivative); + const float force_scale = 0.5f * pair_derivative * inverse_distance; + const float pair_force[3] = { + displacement[0] * force_scale, + displacement[1] * force_scale, + displacement[2] * force_scale}; + energy += 0.5f * pair_energy; + if (SmallBox) { + atomicAdd(&force_x[atom1], static_cast(pair_force[0])); + atomicAdd(&force_y[atom1], static_cast(pair_force[1])); + atomicAdd(&force_z[atom1], static_cast(pair_force[2])); + atomicAdd(&force_x[atom2], static_cast(-pair_force[0])); + atomicAdd(&force_y[atom2], static_cast(-pair_force[1])); + atomicAdd(&force_z[atom2], static_cast(-pair_force[2])); + atomicAdd(&virial[atom2], static_cast(-displacement[0] * pair_force[0])); + atomicAdd(&virial[atom_count + atom2], static_cast(-displacement[1] * pair_force[1])); + atomicAdd(&virial[2 * atom_count + atom2], static_cast(-displacement[2] * pair_force[2])); + atomicAdd(&virial[3 * atom_count + atom2], static_cast(-displacement[0] * pair_force[1])); + atomicAdd(&virial[4 * atom_count + atom2], static_cast(-displacement[0] * pair_force[2])); + atomicAdd(&virial[5 * atom_count + atom2], static_cast(-displacement[1] * pair_force[2])); + atomicAdd(&virial[6 * atom_count + atom2], static_cast(-displacement[1] * pair_force[0])); + atomicAdd(&virial[7 * atom_count + atom2], static_cast(-displacement[2] * pair_force[0])); + atomicAdd(&virial[8 * atom_count + atom2], static_cast(-displacement[2] * pair_force[1])); + } else { + force_sum[0] += 2.0f * pair_force[0]; + force_sum[1] += 2.0f * pair_force[1]; + force_sum[2] += 2.0f * pair_force[2]; + virial_sum[0] -= displacement[0] * pair_force[0]; + virial_sum[1] -= displacement[1] * pair_force[1]; + virial_sum[2] -= displacement[2] * pair_force[2]; + virial_sum[3] -= displacement[0] * pair_force[1]; + virial_sum[4] -= displacement[0] * pair_force[2]; + virial_sum[5] -= displacement[1] * pair_force[2]; + virial_sum[6] -= displacement[1] * pair_force[0]; + virial_sum[7] -= displacement[2] * pair_force[0]; + virial_sum[8] -= displacement[2] * pair_force[1]; + } + } + potential[atom1] += energy; + if (!SmallBox) { + force_x[atom1] += force_sum[0]; + force_y[atom1] += force_sum[1]; + force_z[atom1] += force_sum[2]; +#pragma unroll + for (int component = 0; component < 9; ++component) { + virial[component * atom_count + atom1] += virial_sum[component]; + } + } +} + +} // namespace + +int NEP_Spin::Body_Channels::count(void) const +{ + return l_max_3body + static_cast(has_q_222) + static_cast(has_q_1111) + + static_cast(has_q_112) + static_cast(has_q_123) + + static_cast(has_q_233) + static_cast(has_q_134); +} + +NEP_Spin::NEP_Spin(const char* file_potential, const int num_atoms) : num_atoms_(num_atoms) +{ + try { + read_model(file_potential); + } catch (const std::exception& error) { + PRINT_INPUT_ERROR(error.what()); + } + CHECK(gpuStreamCreate(&structural_descriptor_stream_)); + CHECK(gpuStreamCreate(&spin_descriptor_stream_)); + + rc = std::max({model_.cutoff_radial, model_.cutoff_angular, model_.spin_cutoff}); + input_neighbor_capacity_ = model_.neighbor_capacity; + resize_domain(num_atoms_); + std::vector spin_cutoff_pair( + static_cast(model_.num_types) * model_.num_types); + for (int type_i = 0; type_i < model_.num_types; ++type_i) { + for (int type_j = 0; type_j < model_.num_types; ++type_j) { + spin_cutoff_pair[type_i * model_.num_types + type_j] = static_cast( + 0.5 * (model_.spin_cutoff_by_type[type_i] + model_.spin_cutoff_by_type[type_j])); + } + } + data_.spin_cutoff_pair.resize(spin_cutoff_pair.size()); + data_.spin_cutoff_pair.copy_from_host(spin_cutoff_pair.data(), spin_cutoff_pair.size()); + + printf( + "Use NEP4 Spin3 potential with %d atom type%s.\n", + model_.num_types, + model_.num_types == 1 ? "" : "s"); + printf( + " structural/spin descriptor dimensions = %d/%d.\n", + model_.struct_descriptor_dim, + model_.spin_descriptor_dim); + printf( + " radial/angular/spin cutoffs = %g/%g/%g A.\n", + model_.cutoff_radial, + model_.cutoff_angular, + model_.spin_cutoff); +} + +void NEP_Spin::resize_domain(int num_atoms) +{ + num_atoms_ = num_atoms; + small_box_initialized_ = false; + neighbor_.initialize(rc, num_atoms_, input_neighbor_capacity_); + model_.neighbor_capacity = neighbor_.get_capacity(); + const std::size_t slots = + static_cast(num_atoms_) * static_cast(model_.neighbor_capacity); + data_.NN_radial.resize_with_capacity(num_atoms_); + data_.NN_angular.resize_with_capacity(num_atoms_); + data_.NN_spin.resize_with_capacity(num_atoms_); + data_.NL_radial.resize_with_capacity(slots); + data_.NL_angular.resize_with_capacity(slots); + data_.NL_spin.resize_with_capacity(slots); + data_.descriptor.resize_with_capacity(static_cast(num_atoms_) * model_.descriptor_dim); + data_.Fp.resize_with_capacity(static_cast(num_atoms_) * model_.descriptor_dim); + data_.f12x.resize_with_capacity(slots); + data_.f12y.resize_with_capacity(slots); + data_.f12z.resize_with_capacity(slots); + const std::size_t N = static_cast(num_atoms_); + const std::size_t spin3_state_size = + N * static_cast(model_.spin_polynomial_layout.moment_count); + data_.spin3_moments.resize_with_capacity(spin3_state_size); + const std::size_t sum_fxyz_size = + N * static_cast(model_.n_max_angular + 1) * + static_cast( + (model_.body.l_max_3body + 1) * (model_.body.l_max_3body + 1) - 1); + data_.sum_fxyz.resize_with_capacity(std::max(sum_fxyz_size, 1)); +} + +NEP_Spin::~NEP_Spin(void) +{ + if (structural_descriptor_stream_ != nullptr) { + CHECK(gpuStreamDestroy(structural_descriptor_stream_)); + } + if (spin_descriptor_stream_ != nullptr) { + CHECK(gpuStreamDestroy(spin_descriptor_stream_)); + } +} + +void NEP_Spin::read_model(const char* file_potential) +{ + std::istringstream input(read_nep_spin_model_input(file_potential)); + + std::vector tokens = next_tokens(input); + const bool has_zbl = !tokens.empty() && tokens[0] == "nep4_spin3_zbl"; + if (tokens.size() < 3 || + (tokens[0] != "nep4_spin3" && !has_zbl)) { + throw std::runtime_error("NEP_Spin accepts only nep4_spin3[/zbl] models"); + } + zbl_.enabled = has_zbl; + model_.num_types = parse_int(tokens[1]); + if ( + model_.num_types < 1 || model_.num_types > NUM_ELEMENTS || + tokens.size() != static_cast(model_.num_types + 2)) { + throw std::runtime_error("invalid NEP_Spin model type count"); + } + model_.elements.assign(tokens.begin() + 2, tokens.end()); + check_unique_elements(model_.elements); + zbl_.num_types = model_.num_types; + for (int type = 0; type < model_.num_types; ++type) { + for (int element = 0; element < NUM_ELEMENTS; ++element) { + if (model_.elements[type] == kElementSymbols[element]) { + zbl_.atomic_numbers[type] = element + 1; + break; + } + } + if (zbl_.atomic_numbers[type] == 0) { + throw std::runtime_error("unknown element in NEP_Spin ZBL model"); + } + } + + tokens = next_tokens(input); + require_line(tokens, "spin_mode", 3); + if (parse_int(tokens[1]) != model_.spin_mode) { + throw std::runtime_error("spin_mode metadata does not match the model tag"); + } + const int spin_header_lines = parse_int(tokens[2]); + constexpr int minimum_spin_header_lines = 9; + const int maximum_spin_header_lines = minimum_spin_header_lines + 2; + if (spin_header_lines < minimum_spin_header_lines || + spin_header_lines > maximum_spin_header_lines) { + throw std::runtime_error("counted spin header has an invalid line count"); + } + + bool seen_baseline = false; + bool seen_basis_size = false; + bool seen_l_max = false; + bool seen_compress = false; + bool seen_cutoff = false; + bool seen_scaler = false; + bool seen_dof = false; + bool seen_env = false; + bool seen_order = false; + bool seen_soc = false; + bool seen_projection_size = false; + for (int line = 0; line < spin_header_lines; ++line) { + tokens = next_tokens(input); + if (tokens.empty()) { + throw std::runtime_error("truncated counted spin header"); + } + const std::string& name = tokens[0]; + if (name == "spin_baseline") { + if (seen_baseline || tokens.size() != static_cast(model_.num_types + 1)) { + throw std::runtime_error("energy_reference must occur once with one value per type"); + } + seen_baseline = true; + for (int type = 0; type < model_.num_types; ++type) { + model_.energy_reference.push_back(parse_double(tokens[type + 1])); + } + } else if (name == "spin_basis_size") { + require_line(tokens, "spin_basis_size", 2); + if (seen_basis_size) + throw std::runtime_error("duplicate spin_basis_size"); + seen_basis_size = true; + model_.spin_basis_size[0] = parse_int(tokens[1]); + } else if (name == "spin_l_max") { + require_line(tokens, "spin_l_max", 2); + if (seen_l_max) + throw std::runtime_error("duplicate spin_l_max"); + seen_l_max = true; + model_.spin_l_max[0] = parse_int(tokens[1]); + } else if (name == "spin_compress") { + require_line(tokens, "spin_compress", 2); + if (seen_compress) + throw std::runtime_error("duplicate spin_compress"); + seen_compress = true; + model_.spin_compress = parse_int(tokens[1]); + } else if (name == "spin_cutoff") { + if (seen_cutoff) + throw std::runtime_error("duplicate spin_cutoff"); + seen_cutoff = true; + if (tokens.size() != 2 && + tokens.size() != static_cast(model_.num_types + 1)) { + throw std::runtime_error( + "spin_cutoff requires one value or one value per atom type"); + } + model_.spin_cutoff_by_type.resize(model_.num_types); + for (int type = 0; type < model_.num_types; ++type) { + const std::size_t value_index = tokens.size() == 2 ? 1 : type + 1; + model_.spin_cutoff_by_type[type] = parse_double(tokens[value_index]); + if (!(model_.spin_cutoff_by_type[type] > 0.0) || + !std::isfinite(model_.spin_cutoff_by_type[type])) { + throw std::runtime_error("spin_cutoff values must be finite and positive"); + } + } + model_.spin_cutoff = *std::max_element( + model_.spin_cutoff_by_type.begin(), model_.spin_cutoff_by_type.end()); + } else if (name == "spin_order") { + require_line(tokens, "spin_order", 2); + if (seen_order) + throw std::runtime_error("duplicate spin_order"); + seen_order = true; + model_.spin_order = parse_int(tokens[1]); + } else if (name == "spin_soc") { + require_line(tokens, "spin_soc", 2); + if (seen_soc) + throw std::runtime_error("duplicate spin_soc"); + seen_soc = true; + model_.spin_soc = parse_flag(tokens[1], "spin_soc"); + } else if (name == "spin_projection_size") { + require_line(tokens, "spin_projection_size", 2); + if (seen_projection_size) + throw std::runtime_error("duplicate spin_projection_size"); + seen_projection_size = true; + model_.spin_projection_size = parse_int(tokens[1]); + } else if (name == "spin_scaler") { + require_line(tokens, "spin_scaler", 2); + if (seen_scaler || parse_int(tokens[1]) != 1) + throw std::runtime_error("spin_scaler must occur once and equal 1"); + seen_scaler = true; + } else if (name == "spin_dof_type") { + if (seen_dof) + throw std::runtime_error("duplicate spin_dof_type"); + seen_dof = true; + model_.spin_dof_type_active = + parse_active_types(tokens, model_.elements, "spin_dof_type"); + } else if (name == "spin_env_type") { + if (seen_env) + throw std::runtime_error("duplicate spin_env_type"); + seen_env = true; + model_.spin_env_type_active = + parse_active_types(tokens, model_.elements, "spin_env_type"); + } else { + throw std::runtime_error("unknown or unsupported spin header line: " + name); + } + } + if ( + !seen_baseline || !seen_basis_size || !seen_l_max || !seen_compress || + !seen_cutoff || !seen_scaler || !seen_order || !seen_soc || + !seen_projection_size) { + throw std::runtime_error("counted spin header is missing a required line"); + } + if (!seen_dof) { + model_.spin_dof_type_active.assign(model_.num_types, 1); + } + if (!seen_env) { + model_.spin_env_type_active = model_.spin_dof_type_active; + } + for (int type = 0; type < model_.num_types; ++type) { + if ( + model_.spin_dof_type_active[type] != 0 && + model_.spin_env_type_active[type] == 0) { + throw std::runtime_error("spin_dof_type must be a subset of spin_env_type"); + } + } + + if (zbl_.enabled) { + tokens = next_tokens(input); + if ((tokens.size() != 3 && tokens.size() != 4) || tokens[0] != "zbl") { + throw std::runtime_error( + "nep4_spin3_zbl requires zbl rc_inner rc_outer [zbl_factor]"); + } + zbl_.rc_inner = parse_float(tokens[1]); + zbl_.rc_outer = parse_float(tokens[2]); + if (zbl_.rc_inner == 0.0f && zbl_.rc_outer == 0.0f) { + throw std::runtime_error("NEP-spin does not support flexible ZBL (zbl 0 0)."); + } + if (!(zbl_.rc_inner >= 0.0f && zbl_.rc_inner < zbl_.rc_outer)) { + throw std::runtime_error("invalid spin3 ZBL inner/outer cutoffs"); + } + if (tokens.size() == 4) { + paramb_.use_typewise_cutoff_zbl = true; + paramb_.typewise_cutoff_zbl_factor = parse_float(tokens[3]); + if (paramb_.typewise_cutoff_zbl_factor < 0.5f) { + throw std::runtime_error("spin3 ZBL typewise cutoff factor must be >= 0.5"); + } + } + } + + tokens = next_tokens(input); + require_line(tokens, "cutoff", 5); + model_.cutoff_radial = parse_double(tokens[1]); + model_.cutoff_angular = parse_double(tokens[2]); + model_.max_neighbors_global = parse_int(tokens[3]); + model_.max_neighbors_angular = parse_int(tokens[4]); + + tokens = next_tokens(input); + require_line(tokens, "n_max", 3); + model_.n_max_radial = parse_int(tokens[1]); + model_.n_max_angular = parse_int(tokens[2]); + + tokens = next_tokens(input); + require_line(tokens, "basis_size", 3); + model_.basis_size_radial = parse_int(tokens[1]); + model_.basis_size_angular = parse_int(tokens[2]); + + tokens = next_tokens(input); + if (tokens.size() < 2 || tokens.size() > 8 || tokens[0] != "l_max") { + throw std::runtime_error("invalid l_max line"); + } + model_.body.l_max_3body = parse_int(tokens[1]); + if (tokens.size() >= 3) + model_.body.has_q_222 = parse_flag(tokens[2], "q_222", true); + if (tokens.size() >= 4) + model_.body.has_q_1111 = parse_flag(tokens[3], "q_1111"); + if (tokens.size() >= 5) + model_.body.has_q_112 = parse_flag(tokens[4], "q_112"); + if (tokens.size() >= 6) + model_.body.has_q_123 = parse_flag(tokens[5], "q_123"); + if (tokens.size() >= 7) + model_.body.has_q_233 = parse_flag(tokens[6], "q_233"); + if (tokens.size() >= 8) + model_.body.has_q_134 = parse_flag(tokens[7], "q_134"); + + tokens = next_tokens(input); + require_line(tokens, "ANN", 3); + model_.hidden_neurons = parse_int(tokens[1]); + if (parse_int(tokens[2]) != 0) { + throw std::runtime_error("NEP_Spin supports only a single hidden ANN layer"); + } + + if ( + model_.cutoff_radial <= 0.0 || model_.cutoff_angular <= 0.0 || + model_.spin_cutoff <= 0.0 || + model_.max_neighbors_global <= 0 || model_.max_neighbors_angular <= 0) { + throw std::runtime_error("cutoffs and neighbor capacities must be finite and positive"); + } + if (model_.n_max_radial < 0 || model_.n_max_radial > 12 || + model_.n_max_angular < 0 || model_.n_max_angular > 8 || + model_.basis_size_radial < 0 || model_.basis_size_radial > 16 || + model_.basis_size_angular < 0 || model_.basis_size_angular > 12 || + model_.body.l_max_3body < 0 || model_.body.l_max_3body > 8 || + model_.hidden_neurons < 1 || model_.hidden_neurons > 120) { + throw std::runtime_error("ordinary NEP_Spin shape is outside the supported range"); + } + if ((model_.body.has_q_222 || model_.body.has_q_112) && model_.body.l_max_3body < 2) + throw std::runtime_error("q_222/q_112 require l_max_3body >= 2"); + if (model_.body.has_q_1111 && model_.body.l_max_3body < 1) + throw std::runtime_error("q_1111 requires l_max_3body >= 1"); + if ((model_.body.has_q_123 || model_.body.has_q_233) && model_.body.l_max_3body < 3) + throw std::runtime_error("q_123/q_233 require l_max_3body >= 3"); + if (model_.body.has_q_134 && model_.body.l_max_3body < 4) + throw std::runtime_error("q_134 requires l_max_3body >= 4"); + + if ( + model_.spin_compress < 1 || model_.spin_compress > 9 || + model_.spin_basis_size[0] != 8 || model_.spin_l_max[0] < 0 || + model_.spin_l_max[0] > 2 || model_.spin_order < 1 || + model_.spin_order > 3 || (model_.spin_soc != 0 && model_.spin_soc != 1) || + model_.spin_projection_size != 4 * model_.spin_compress * model_.spin_compress) { + throw std::runtime_error("Spin3 O/C descriptor shape is outside the supported range"); + } + + model_.struct_descriptor_dim = + model_.n_max_radial + 1 + (model_.n_max_angular + 1) * model_.body.count(); + if ((model_.n_max_angular + 1) * model_.body.count() > 90) { + throw std::runtime_error("structural angular descriptor dimension exceeds 90"); + } + model_.spin_polynomial_layout = make_spin_polynomial_layout( + model_.spin_compress, model_.spin_l_max[0], model_.spin_order, model_.spin_soc); + model_.spin_descriptor_dim = model_.spin_polynomial_layout.descriptor_dim; + model_.descriptor_dim = model_.struct_descriptor_dim + model_.spin_descriptor_dim; + if (model_.descriptor_dim > MAX_DIM_SPIN) { + throw std::runtime_error( + "combined structural and spin descriptor dimension exceeds GPUMD MAX_DIM_SPIN"); + } + + const std::size_t types = static_cast(model_.num_types); + const std::size_t type_pairs = types * types; + model_.ann_parameter_count = + static_cast(model_.descriptor_dim + 2) * model_.hidden_neurons * types + 1; + model_.radial_parameter_count = static_cast(model_.n_max_radial + 1) * + (model_.basis_size_radial + 1) * type_pairs; + model_.angular_parameter_count = static_cast(model_.n_max_angular + 1) * + (model_.basis_size_angular + 1) * type_pairs; + model_.spin_parameter_count = static_cast(model_.spin_compress) * + (model_.spin_basis_size[0] + 1) * type_pairs; + model_.spin_projection_parameter_count = + static_cast(model_.spin_projection_size); + model_.model_parameter_count = model_.ann_parameter_count + model_.radial_parameter_count + + model_.angular_parameter_count + model_.spin_parameter_count + + model_.spin_projection_parameter_count; + + std::vector parameters; + parameters.reserve(model_.model_parameter_count + model_.descriptor_dim); + for (std::size_t i = 0; i < model_.model_parameter_count + model_.descriptor_dim; ++i) { + tokens = next_tokens(input); + if (tokens.size() != 1) { + throw std::runtime_error("truncated or malformed NEP_Spin numeric payload"); + } + parameters.push_back(parse_float(tokens[0])); + } + if (!next_tokens(input).empty()) { + throw std::runtime_error("extra header or numeric payload after NEP_Spin model"); + } + data_.parameters.resize(parameters.size()); + data_.parameters.copy_from_host(parameters.data()); + + const std::size_t descriptor_offset = model_.ann_parameter_count; + const std::size_t ordinary_count = + model_.radial_parameter_count + model_.angular_parameter_count; + std::vector descriptor_parameters(ordinary_count + model_.spin_parameter_count); + const std::size_t radial_basis = + static_cast(model_.n_max_radial + 1) * (model_.basis_size_radial + 1); + const std::size_t angular_basis = + static_cast(model_.n_max_angular + 1) * (model_.basis_size_angular + 1); + for (std::size_t pair = 0; pair < type_pairs; ++pair) { + for (std::size_t basis = 0; basis < radial_basis; ++basis) { + descriptor_parameters[pair * radial_basis + basis] = + parameters[descriptor_offset + basis * type_pairs + pair]; + } + for (std::size_t basis = 0; basis < angular_basis; ++basis) { + descriptor_parameters[ + model_.radial_parameter_count + pair * angular_basis + basis] = + parameters[ + descriptor_offset + model_.radial_parameter_count + basis * type_pairs + pair]; + } + } + std::copy( + parameters.begin() + descriptor_offset + ordinary_count, + parameters.begin() + descriptor_offset + ordinary_count + model_.spin_parameter_count, + descriptor_parameters.begin() + ordinary_count); + data_.descriptor_parameters_type_pair.resize(descriptor_parameters.size()); + data_.descriptor_parameters_type_pair.copy_from_host(descriptor_parameters.data()); + if (model_.spin_projection_parameter_count > 0) { + const std::size_t projection_offset = descriptor_offset + ordinary_count + + model_.spin_parameter_count; + std::vector projection_parameters( + parameters.begin() + projection_offset, + parameters.begin() + projection_offset + model_.spin_projection_parameter_count); + data_.spin_projection_parameters.resize(projection_parameters.size()); + data_.spin_projection_parameters.copy_from_host(projection_parameters.data()); + } + + const auto& energy_reference = model_.energy_reference; + data_.energy_reference.resize(energy_reference.size()); + data_.energy_reference.copy_from_host(energy_reference.data()); + data_.spin_dof_type_active.resize(model_.spin_dof_type_active.size()); + data_.spin_dof_type_active.copy_from_host(model_.spin_dof_type_active.data()); + data_.spin_env_type_active.resize(model_.spin_env_type_active.size()); + data_.spin_env_type_active.copy_from_host(model_.spin_env_type_active.data()); + + paramb_.num_types = model_.num_types; + paramb_.num_types_sq = model_.num_types * model_.num_types; + paramb_.n_max_radial = model_.n_max_radial; + paramb_.n_max_angular = model_.n_max_angular; + paramb_.basis_size_radial = model_.basis_size_radial; + paramb_.basis_size_angular = model_.basis_size_angular; + paramb_.L_max = model_.body.l_max_3body; + paramb_.num_L = model_.body.count(); + paramb_.has_q_222 = model_.body.has_q_222; + paramb_.has_q_1111 = model_.body.has_q_1111; + paramb_.has_q_112 = model_.body.has_q_112; + paramb_.has_q_123 = model_.body.has_q_123; + paramb_.has_q_233 = model_.body.has_q_233; + paramb_.has_q_134 = model_.body.has_q_134; + paramb_.dim_angular = (model_.n_max_angular + 1) * model_.body.count(); + paramb_.num_c_radial = static_cast(model_.radial_parameter_count); + paramb_.MN_radial = model_.neighbor_capacity; + paramb_.MN_angular = model_.neighbor_capacity; + paramb_.rc_radial_max = model_.cutoff_radial; + paramb_.rc_radial_max_inv = 1.0f / model_.cutoff_radial; + for (int type = 0; type < model_.num_types; ++type) { + paramb_.rc_radial[type] = model_.cutoff_radial; + paramb_.rc_angular[type] = model_.cutoff_angular; + } + + ann_.dim = model_.descriptor_dim; + ann_.num_neurons1 = model_.hidden_neurons; + ann_.num_para_ann = static_cast(model_.ann_parameter_count); + ann_.num_para = static_cast(model_.model_parameter_count); + float* pointer = data_.parameters.data(); + for (int type = 0; type < model_.num_types; ++type) { + ann_.w0[type] = pointer; + pointer += model_.hidden_neurons * model_.descriptor_dim; + ann_.b0[type] = pointer; + pointer += model_.hidden_neurons; + ann_.w1[type] = pointer; + pointer += model_.hidden_neurons; + } + ann_.b1 = pointer; + ann_.c_type_pair = data_.descriptor_parameters_type_pair.data(); + ann_.q_scaler = data_.parameters.data() + model_.model_parameter_count; + + const double enlarged = std::ceil(static_cast(model_.max_neighbors_global) * 1.25); + if (enlarged > std::numeric_limits::max()) { + throw std::runtime_error("neighbor capacity is too large"); + } + model_.neighbor_capacity = static_cast(enlarged); +} + +void NEP_Spin::compute( + Box&, + const GPU_Vector&, + const GPU_Vector&, + GPU_Vector&, + GPU_Vector&, + GPU_Vector&) +{ + PRINT_INPUT_ERROR("NEP_Spin requires spin inputs."); +} + +void NEP_Spin::initialize_small_box(const Box& box) +{ + const double volume = box.get_volume(); + const double thickness[3] = { + volume / box.get_area(0), volume / box.get_area(1), volume / box.get_area(2)}; + expanded_box_.num_cells[0] = + box.pbc_x ? static_cast(std::ceil(2.0 * rc / thickness[0])) : 1; + expanded_box_.num_cells[1] = + box.pbc_y ? static_cast(std::ceil(2.0 * rc / thickness[1])) : 1; + expanded_box_.num_cells[2] = + box.pbc_z ? static_cast(std::ceil(2.0 * rc / thickness[2])) : 1; + + const std::size_t cell_count = + static_cast(expanded_box_.num_cells[0]) * + static_cast(expanded_box_.num_cells[1]) * + static_cast(expanded_box_.num_cells[2]); + if ( + cell_count == 0 || + cell_count > (std::numeric_limits::max() - 1) / + static_cast(num_atoms_)) { + PRINT_INPUT_ERROR("NEP_Spin small-box image count overflows size_t."); + } + const std::size_t capacity = + static_cast(num_atoms_) * cell_count - 1; + if (capacity > static_cast(std::numeric_limits::max())) { + PRINT_INPUT_ERROR("NEP_Spin small-box neighbor capacity exceeds int."); + } + const std::size_t plane_size = static_cast(num_atoms_) * capacity; + if (capacity != 0 && plane_size / capacity != static_cast(num_atoms_)) { + PRINT_INPUT_ERROR("NEP_Spin small-box slot count overflows size_t."); + } + if (plane_size > std::numeric_limits::max() / (3 * sizeof(double))) { + PRINT_INPUT_ERROR("NEP_Spin small-box displacement storage overflows size_t."); + } + if (plane_size > static_cast(std::numeric_limits::max())) { + PRINT_INPUT_ERROR("NEP_Spin small-box slot plane exceeds int indexing."); + } + const int new_capacity = static_cast(capacity); + const bool resize_storage = + !small_box_initialized_ || small_box_capacity_ != new_capacity; + small_box_capacity_ = new_capacity; + + expanded_box_.h[0] = box.cpu_h[0] * expanded_box_.num_cells[0]; + expanded_box_.h[3] = box.cpu_h[3] * expanded_box_.num_cells[0]; + expanded_box_.h[6] = box.cpu_h[6] * expanded_box_.num_cells[0]; + expanded_box_.h[1] = box.cpu_h[1] * expanded_box_.num_cells[1]; + expanded_box_.h[4] = box.cpu_h[4] * expanded_box_.num_cells[1]; + expanded_box_.h[7] = box.cpu_h[7] * expanded_box_.num_cells[1]; + expanded_box_.h[2] = box.cpu_h[2] * expanded_box_.num_cells[2]; + expanded_box_.h[5] = box.cpu_h[5] * expanded_box_.num_cells[2]; + expanded_box_.h[8] = box.cpu_h[8] * expanded_box_.num_cells[2]; + expanded_box_.h[9] = + expanded_box_.h[4] * expanded_box_.h[8] - expanded_box_.h[5] * expanded_box_.h[7]; + expanded_box_.h[10] = + expanded_box_.h[2] * expanded_box_.h[7] - expanded_box_.h[1] * expanded_box_.h[8]; + expanded_box_.h[11] = + expanded_box_.h[1] * expanded_box_.h[5] - expanded_box_.h[2] * expanded_box_.h[4]; + expanded_box_.h[12] = + expanded_box_.h[5] * expanded_box_.h[6] - expanded_box_.h[3] * expanded_box_.h[8]; + expanded_box_.h[13] = + expanded_box_.h[0] * expanded_box_.h[8] - expanded_box_.h[2] * expanded_box_.h[6]; + expanded_box_.h[14] = + expanded_box_.h[2] * expanded_box_.h[3] - expanded_box_.h[0] * expanded_box_.h[5]; + expanded_box_.h[15] = + expanded_box_.h[3] * expanded_box_.h[7] - expanded_box_.h[4] * expanded_box_.h[6]; + expanded_box_.h[16] = + expanded_box_.h[1] * expanded_box_.h[6] - expanded_box_.h[0] * expanded_box_.h[7]; + expanded_box_.h[17] = + expanded_box_.h[0] * expanded_box_.h[4] - expanded_box_.h[1] * expanded_box_.h[3]; + const double determinant = + expanded_box_.h[0] * + (expanded_box_.h[4] * expanded_box_.h[8] - + expanded_box_.h[5] * expanded_box_.h[7]) + + expanded_box_.h[1] * + (expanded_box_.h[5] * expanded_box_.h[6] - + expanded_box_.h[3] * expanded_box_.h[8]) + + expanded_box_.h[2] * + (expanded_box_.h[3] * expanded_box_.h[7] - + expanded_box_.h[4] * expanded_box_.h[6]); + for (int index = 9; index < 18; ++index) { + expanded_box_.h[index] /= determinant; + } + + if (resize_storage) { + data_.NL_radial.resize(plane_size); + data_.NL_angular.resize(plane_size); + data_.NL_spin.resize(plane_size); + data_.r12_radial.resize(3 * plane_size); + data_.r12_angular.resize(3 * plane_size); + data_.r12_spin.resize(3 * plane_size); + data_.f12x.resize(plane_size); + data_.f12y.resize(plane_size); + data_.f12z.resize(plane_size); + } + small_box_initialized_ = true; +} + +void NEP_Spin::compute( + Box& box, + const GPU_Vector& type, + const GPU_Vector& position, + const GPU_Vector& spin, + GPU_Vector& potential, + GPU_Vector& force, + GPU_Vector& virial, + GPU_Vector& mforce) +{ + const int N = type.size(); + if ( + N != num_atoms_ || position.size() != static_cast(3 * N) || + spin.size() != static_cast(3 * N)) { + PRINT_INPUT_ERROR("NEP_Spin input sizes do not match the initialized atom count."); + } + if (!(box.pbc_x && box.pbc_y && box.pbc_z)) { + PRINT_INPUT_ERROR("NEP_Spin requires periodic boundary conditions in all three directions."); + } + const double volume = box.get_volume(); + const double thickness_x = volume / box.get_area(0); + const double thickness_y = volume / box.get_area(1); + const double thickness_z = volume / box.get_area(2); + const double minimum_safe_thickness = neighbor_.minimum_safe_box_thickness(rc); + const bool is_small_box = + (box.pbc_x && thickness_x < minimum_safe_thickness) || + (box.pbc_y && thickness_y < minimum_safe_thickness) || + (box.pbc_z && thickness_z < minimum_safe_thickness); + + constexpr int block_size = 64; + const int grid_size = (N - 1) / block_size + 1; + if (is_small_box) { + initialize_small_box(box); + int* gpu_required_capacity = nullptr; + CHECK(gpuGetSymbolAddress( + reinterpret_cast(&gpu_required_capacity), required_small_box_capacity)); + const int zero = 0; + CHECK(gpuMemcpy(gpu_required_capacity, &zero, sizeof(int), gpuMemcpyHostToDevice)); + find_neighbor_list_spin_small_box<<>>( + paramb_, + static_cast(model_.spin_cutoff), + N, + box, + expanded_box_, + small_box_capacity_, + type.data(), + position.data(), + position.data() + N, + position.data() + 2 * N, + data_.NN_radial.data(), + data_.NL_radial.data(), + data_.NN_angular.data(), + data_.NL_angular.data(), + data_.NN_spin.data(), + data_.NL_spin.data(), + data_.r12_radial.data(), + data_.r12_angular.data(), + data_.r12_spin.data(), + gpu_required_capacity); + GPU_CHECK_KERNEL + int required_capacity = 0; + CHECK(gpuMemcpy( + &required_capacity, gpu_required_capacity, sizeof(int), gpuMemcpyDeviceToHost)); + if (required_capacity > small_box_capacity_) { + PRINT_INPUT_ERROR( + ("NEP_Spin small-box neighbor capacity overflow: required " + + std::to_string(required_capacity) + " slots but capacity is " + + std::to_string(small_box_capacity_) + ".") + .c_str()); + } + const int plane_size = N * small_box_capacity_; + find_structural_descriptor<<>>( + paramb_, + ann_, + N, + box, + data_.NN_radial.data(), + data_.NL_radial.data(), + data_.NN_angular.data(), + data_.NL_angular.data(), + data_.r12_radial.data(), + data_.r12_angular.data(), + plane_size, + type.data(), + position.data(), + position.data() + N, + position.data() + 2 * N, + data_.descriptor.data(), + data_.sum_fxyz.data()); + GPU_CHECK_KERNEL + launch_spin3_descriptors( + model_, box, type, position, spin, data_, data_.r12_spin.data(), plane_size); + find_potential<<>>( + N, + model_.descriptor_dim, + model_.hidden_neurons, + model_.num_types, + type.data(), + data_.descriptor.data(), + data_.parameters.data(), + data_.parameters.data() + model_.model_parameter_count, + data_.energy_reference.data(), + potential.data(), + data_.Fp.data()); + GPU_CHECK_KERNEL + nep_spin_small_box::find_force_radial_small_box<<>>( + paramb_, + ann_, + N, + 0, + N, + data_.NN_radial.data(), + data_.NL_radial.data(), + type.data(), + data_.r12_radial.data(), + data_.r12_radial.data() + plane_size, + data_.r12_radial.data() + 2 * plane_size, + data_.Fp.data(), + force.data(), + force.data() + N, + force.data() + 2 * N, + virial.data()); + GPU_CHECK_KERNEL + nep_spin_small_box::find_force_angular_small_box<<>>( + paramb_, + ann_, + N, + 0, + N, + data_.NN_angular.data(), + data_.NL_angular.data(), + type.data(), + data_.r12_angular.data(), + data_.r12_angular.data() + plane_size, + data_.r12_angular.data() + 2 * plane_size, + data_.Fp.data(), + data_.sum_fxyz.data(), + force.data(), + force.data() + N, + force.data() + 2 * N, + virial.data()); + GPU_CHECK_KERNEL + launch_spin3_forces( + model_, box, type, position, spin, data_, force, mforce, virial, + data_.r12_spin.data(), plane_size); + if (zbl_.enabled) { + find_spin_zbl_force<<>>( + paramb_, + N, + zbl_, + box, + data_.NN_radial.data(), + data_.NL_radial.data(), + type.data(), + nullptr, + nullptr, + nullptr, + data_.r12_radial.data(), + data_.r12_radial.data() + plane_size, + data_.r12_radial.data() + 2 * plane_size, + force.data(), + force.data() + N, + force.data() + 2 * N, + virial.data(), + potential.data()); + GPU_CHECK_KERNEL + } + return; + } + + neighbor_.find_neighbor_global(rc, box, type, position); + constexpr int neighbor_block_size = 128; + const int neighbor_grid_size = (N - 1) / neighbor_block_size + 1; + find_local_neighbors_spin<<>>( + N, + box, + static_cast(model_.cutoff_radial * model_.cutoff_radial), + static_cast(model_.cutoff_angular * model_.cutoff_angular), + static_cast(model_.spin_cutoff * model_.spin_cutoff), + position.data(), + position.data() + N, + position.data() + 2 * N, + neighbor_.NN.data(), + neighbor_.NL.data(), + data_.NN_radial.data(), + data_.NL_radial.data(), + data_.NN_angular.data(), + data_.NL_angular.data(), + data_.NN_spin.data(), + data_.NL_spin.data()); + GPU_CHECK_KERNEL + + find_structural_descriptor<<< + grid_size, block_size, 0, structural_descriptor_stream_>>>( + paramb_, + ann_, + N, + box, + data_.NN_radial.data(), + data_.NL_radial.data(), + data_.NN_angular.data(), + data_.NL_angular.data(), + nullptr, + nullptr, + 0, + type.data(), + position.data(), + position.data() + N, + position.data() + 2 * N, + data_.descriptor.data(), + data_.sum_fxyz.data()); + GPU_CHECK_KERNEL + + launch_spin3_descriptors( + model_, box, type, position, spin, data_, nullptr, 0, spin_descriptor_stream_); +#ifdef USE_HIP + CHECK(hipStreamSynchronize(structural_descriptor_stream_)); + CHECK(hipStreamSynchronize(spin_descriptor_stream_)); +#else + CHECK(cudaStreamSynchronize(structural_descriptor_stream_)); + CHECK(cudaStreamSynchronize(spin_descriptor_stream_)); +#endif + constexpr int potential_lanes_per_atom = 4; + constexpr int potential_block_size = 128; + constexpr int potential_atoms_per_block = + potential_block_size / potential_lanes_per_atom; + const int potential_grid_size = + (N - 1) / potential_atoms_per_block + 1; + const std::size_t potential_shared_size = + static_cast(potential_atoms_per_block) * + (model_.descriptor_dim + model_.hidden_neurons) * sizeof(float); + constexpr std::size_t maximum_potential_shared_size = 48 * 1024; + if (potential_shared_size <= maximum_potential_shared_size) { + find_potential_warp + <<>>( + N, + model_.descriptor_dim, + model_.hidden_neurons, + model_.num_types, + type.data(), + data_.descriptor.data(), + data_.parameters.data(), + data_.parameters.data() + model_.model_parameter_count, + data_.energy_reference.data(), + potential.data(), + data_.Fp.data()); + } else { + find_potential<<>>( + N, + model_.descriptor_dim, + model_.hidden_neurons, + model_.num_types, + type.data(), + data_.descriptor.data(), + data_.parameters.data(), + data_.parameters.data() + model_.model_parameter_count, + data_.energy_reference.data(), + potential.data(), + data_.Fp.data()); + } + GPU_CHECK_KERNEL + + find_force_radial<<>>( + paramb_, + ann_, + N, + 0, + N, + box, + data_.NN_radial.data(), + data_.NL_radial.data(), + type.data(), + position.data(), + position.data() + N, + position.data() + 2 * N, + data_.Fp.data(), + force.data(), + force.data() + N, + force.data() + 2 * N, + virial.data()); + GPU_CHECK_KERNEL + + constexpr int angular_atoms_per_warp = 4; + constexpr int angular_edge_lanes = 8; + constexpr int angular_block_size = 128; + constexpr int angular_centers_per_block = + angular_block_size / 32 * angular_atoms_per_warp; + const int angular_grid_size = + (N - 1) / angular_centers_per_block + 1; + const int angular_state_size = + paramb_.dim_angular + (paramb_.n_max_angular + 1) * NUM_OF_ABC; + const std::size_t angular_shared_size = + static_cast(angular_centers_per_block) * angular_state_size * sizeof(float); + constexpr std::size_t maximum_angular_shared_size = 48 * 1024; + const bool use_direct_angular_force = + angular_shared_size <= maximum_angular_shared_size; + if (use_direct_angular_force) { + // The body-channel signature comes from l_max in the model input. Keep a + // generic instance for every signature other than the common L4+q222 case. + const bool l4_q222_only = + paramb_.L_max == 4 && paramb_.has_q_222 && !paramb_.has_q_1111 && + !paramb_.has_q_112 && !paramb_.has_q_123 && !paramb_.has_q_233 && + !paramb_.has_q_134 && paramb_.num_L == 5; + if (l4_q222_only) { + launch_force_angular_warp( + paramb_, + ann_, + box, + type, + position, + data_, + force, + virial, + angular_grid_size, + angular_block_size, + angular_shared_size); + } else { + launch_force_angular_warp( + paramb_, + ann_, + box, + type, + position, + data_, + force, + virial, + angular_grid_size, + angular_block_size, + angular_shared_size); + } + } else { + find_partial_force_angular<<>>( + paramb_, + ann_, + N, + 0, + N, + box, + data_.NN_angular.data(), + data_.NL_angular.data(), + type.data(), + position.data(), + position.data() + N, + position.data() + 2 * N, + data_.Fp.data(), + data_.sum_fxyz.data(), + data_.f12x.data(), + data_.f12y.data(), + data_.f12z.data()); + } + GPU_CHECK_KERNEL + if (!use_direct_angular_force) { + find_properties_many_body( + box, + data_.NN_angular.data(), + data_.NL_angular.data(), + data_.f12x.data(), + data_.f12y.data(), + data_.f12z.data(), + position, + force, + virial); + } + + launch_spin3_forces(model_, box, type, position, spin, data_, force, mforce, virial); + if (zbl_.enabled) { + find_spin_zbl_force<<>>( + paramb_, + N, + zbl_, + box, + neighbor_.NN.data(), + neighbor_.NL.data(), + type.data(), + position.data(), + position.data() + N, + position.data() + 2 * N, + nullptr, + nullptr, + nullptr, + force.data(), + force.data() + N, + force.data() + 2 * N, + virial.data(), + potential.data()); + GPU_CHECK_KERNEL + } +} diff --git a/src/force/nep_spin/nep_spin.cuh b/src/force/nep_spin/nep_spin.cuh new file mode 100644 index 000000000..570d7979f --- /dev/null +++ b/src/force/nep_spin/nep_spin.cuh @@ -0,0 +1,180 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + Copyright 2026 NEPAdapters contributors + This file is part of GPUMD and is distributed under LGPLv3 or later. +*/ + +#pragma once + +#include "force/neighbor.cuh" +#include "force/nep.cuh" +#include "force/potential.cuh" +#include "utilities/common.cuh" +#include "utilities/gpu_vector.cuh" +#include +#include +#include + +struct NEP_Spin_Data { + GPU_Vector parameters; + GPU_Vector descriptor_parameters_type_pair; + GPU_Vector descriptor; + GPU_Vector Fp; + GPU_Vector sum_fxyz; + GPU_Vector f12x; + GPU_Vector f12y; + GPU_Vector f12z; + GPU_Vector energy_reference; + GPU_Vector spin_dof_type_active; + GPU_Vector spin_env_type_active; + GPU_Vector spin_cutoff_pair; + GPU_Vector spin_projection_parameters; + GPU_Vector spin3_moments; + GPU_Vector NN_radial; + GPU_Vector NL_radial; + GPU_Vector NN_angular; + GPU_Vector NL_angular; + GPU_Vector NN_spin; + GPU_Vector NL_spin; + GPU_Vector r12_radial; + GPU_Vector r12_angular; + GPU_Vector r12_spin; +}; + +class NEP_Spin : public Potential +{ +public: + struct Spin_Polynomial_Layout { + int channels = 0; + int pair_count = 0; + int density_stride = 38; + int moment_count = 0; + int local_s2 = -1; + int edge_l0_dot = -1; + int edge_l0_neighbor_s2 = -1; + int edge_l2_pair = -1; + int center_l2_environment = -1; + int edge_l0_dot2 = -1; + int density_l0_self = -1; + int density_l1_longitudinal_self = -1; + int density_l1_axial_self = -1; + int density_l1_stf_self = -1; + int density_l1_product_self = -1; + int density_l2_product_self = -1; + int density_l0_dot_response = -1; + int correlation_same_edge = -1; + int correlation_distinct_neighbor = -1; + int correlation_distinct_l1 = -1; + int correlation_distinct_l2 = -1; + int angular_l1_moment_offset = -1; + int angular_l2_moment_offset = -1; + int coupling_l11_axial = -1; + int edge_l11_axial = -1; + int coupling_l22_axial = -1; + int edge_l22_axial = -1; + int edge_l0_moment_gate = -1; + int coupling_l11_dot_response = -1; + int coupling_l111_p_m_x = -1; + int coupling_l22_dot_response = -1; + int coupling_l111_p_qs_x = -1; + int coupling_l112_edge_response = -1; + int coupling_l111_bulk = -1; + int descriptor_dim = 0; + }; + + struct Body_Channels { + int l_max_3body = 0; + bool has_q_222 = false; + bool has_q_1111 = false; + bool has_q_112 = false; + bool has_q_123 = false; + bool has_q_233 = false; + bool has_q_134 = false; + + int count(void) const; + }; + + struct Model { + int spin_mode = 3; + int num_types = 0; + int n_max_radial = 0; + int n_max_angular = 0; + int basis_size_radial = 0; + int basis_size_angular = 0; + int hidden_neurons = 0; + int max_neighbors_global = 0; + int max_neighbors_angular = 0; + int neighbor_capacity = 0; + int spin_basis_size[2] = {0, 0}; + int spin_l_max[3] = {0, 0, 0}; + int spin_compress = 0; + int spin_order = 0; + int spin_soc = 0; + int spin_projection_size = 0; + double cutoff_radial = 0.0; + double cutoff_angular = 0.0; + double spin_cutoff = 0.0; + int struct_descriptor_dim = 0; + int spin_descriptor_dim = 0; + int descriptor_dim = 0; + std::size_t ann_parameter_count = 0; + std::size_t radial_parameter_count = 0; + std::size_t angular_parameter_count = 0; + std::size_t spin_parameter_count = 0; + std::size_t spin_projection_parameter_count = 0; + std::size_t model_parameter_count = 0; + std::vector elements; + std::vector energy_reference; + std::vector spin_dof_type_active; + std::vector spin_env_type_active; + std::vector spin_cutoff_by_type; + Body_Channels body; + Spin_Polynomial_Layout spin_polynomial_layout; + }; + + NEP_Spin(const char* file_potential, const int num_atoms); + virtual ~NEP_Spin(void); + + using Potential::compute; + + void compute( + Box& box, + const GPU_Vector& type, + const GPU_Vector& position, + GPU_Vector& potential, + GPU_Vector& force, + GPU_Vector& virial) override; + + void compute( + Box& box, + const GPU_Vector& type, + const GPU_Vector& position, + const GPU_Vector& spin, + GPU_Vector& potential, + GPU_Vector& force, + GPU_Vector& virial, + GPU_Vector& mforce) override; + + void resize_domain(int num_atoms); + void invalidate_neighbors() { neighbor_.invalidate(); } + + const Model& model(void) const { return model_; } + +private: + Model model_; + NEP_Spin_Data data_; + Neighbor neighbor_; + NEP::ParaMB paramb_; + NEP::ANN ann_; + NEP::ZBL zbl_; + int num_atoms_ = 0; + int input_neighbor_capacity_ = 0; + gpuStream_t structural_descriptor_stream_ = nullptr; + gpuStream_t spin_descriptor_stream_ = nullptr; + bool small_box_initialized_ = false; + int small_box_capacity_ = 0; + NEP::ExpandedBox expanded_box_; + + void read_model(const char* file_potential); + void initialize_small_box(const Box& box); +}; diff --git a/src/force/nep_spin/nep_spin3_common.cuh b/src/force/nep_spin/nep_spin3_common.cuh new file mode 100644 index 000000000..49eeb05f8 --- /dev/null +++ b/src/force/nep_spin/nep_spin3_common.cuh @@ -0,0 +1,63 @@ +/* + This file is part of GPUMD. + SPDX-License-Identifier: LGPL-3.0-or-later +*/ + +#pragma once + +// Small device helpers shared by the Spin3 runtime and training paths. + +__device__ __forceinline__ void minimum_image_delta( + const SimulationBox& box, + const double x, + const double y, + const double z, + float& dx, + float& dy, + float& dz) +{ + dx = static_cast(x); + dy = static_cast(y); + dz = static_cast(z); + apply_mic(box, dx, dy, dz); +} + +__device__ __forceinline__ void compute_spin_edge_geometry_f32( + const int atom, + const int neighbor, + const int atom_stride, + const SimulationBox box, + const double* __restrict__ positions, + float* rhat, + float& distance) +{ + float dx; + float dy; + float dz; + minimum_image_delta( + box, + positions[neighbor] - positions[atom], + positions[atom_stride + neighbor] - positions[atom_stride + atom], + positions[2 * atom_stride + neighbor] - positions[2 * atom_stride + atom], + dx, + dy, + dz); + distance = sqrtf(dx * dx + dy * dy + dz * dz); + const float inverse_distance = distance > 0.0f ? 1.0f / distance : 0.0f; + rhat[0] = dx * inverse_distance; + rhat[1] = dy * inverse_distance; + rhat[2] = dz * inverse_distance; +} + +__device__ __forceinline__ int virial_internal_component( + const int row_major) +{ + return row_major == 0 ? 0 : + row_major == 1 ? 3 : + row_major == 2 ? 4 : + row_major == 3 ? 6 : + row_major == 4 ? 1 : + row_major == 5 ? 5 : + row_major == 6 ? 7 : + row_major == 7 ? 8 : 2; +} diff --git a/src/force/nep_spin/nep_spin3_descriptor.cuh b/src/force/nep_spin/nep_spin3_descriptor.cuh new file mode 100644 index 000000000..cbb4d1571 --- /dev/null +++ b/src/force/nep_spin/nep_spin3_descriptor.cuh @@ -0,0 +1,577 @@ +/* + This file is part of GPUMD. + SPDX-License-Identifier: LGPL-3.0-or-later +*/ + +#pragma once + +// Unified O/C spin3 descriptor kernels. Included from nep_spin.cu. +// Unified spin3 follows the Torch magnetic-polynomial STF5 ABI: five orthonormal +// components, not the historical spin3 compact-matrix coordinates. +__device__ __forceinline__ void spin3_oc_stf5_outer( + const float* left, + const float* right, + float* out) { + constexpr float InvSqrt6 = 0.40824829046386301637f; + constexpr float InvSqrt2 = 0.70710678118654752440f; + const float xx = left[0] * right[0]; + const float yy = left[1] * right[1]; + const float zz = left[2] * right[2]; + out[0] = (2.0f * zz - xx - yy) * InvSqrt6; + out[1] = (xx - yy) * InvSqrt2; + out[2] = (left[0] * right[1] + left[1] * right[0]) * InvSqrt2; + out[3] = (left[1] * right[2] + left[2] * right[1]) * InvSqrt2; + out[4] = (left[2] * right[0] + left[0] * right[2]) * InvSqrt2; +} + +__device__ __forceinline__ void spin3_oc_expand_stf5( + const float* value, + float* out) { + constexpr float InvSqrt6 = 0.40824829046386301637f; + constexpr float InvSqrt2 = 0.70710678118654752440f; + const float xx = -value[0] * InvSqrt6 + value[1] * InvSqrt2; + const float yy = -value[0] * InvSqrt6 - value[1] * InvSqrt2; + const float zz = 2.0f * value[0] * InvSqrt6; + const float xy = value[2] * InvSqrt2; + const float yz = value[3] * InvSqrt2; + const float zx = value[4] * InvSqrt2; + out[0] = xx; out[1] = xy; out[2] = zx; + out[3] = xy; out[4] = yy; out[5] = yz; + out[6] = zx; out[7] = yz; out[8] = zz; +} + +__device__ __forceinline__ void spin3_oc_stf5_matvec( + const float* matrix, + const float* vector, + float* out) { + float full[9]; + spin3_oc_expand_stf5(matrix, full); + for (int a = 0; a < 3; ++a) { + out[a] = 0.0f; + for (int b = 0; b < 3; ++b) { + out[a] += full[3 * a + b] * vector[b]; + } + } +} + +__device__ __forceinline__ void spin3_oc_add_stf5_outer_pull( + const float* left, + const float* right, + const float* pull, + float scale, + float* pull_left, + float* pull_right) { + constexpr float InvSqrt6 = 0.40824829046386301637f; + constexpr float InvSqrt2 = 0.70710678118654752440f; + const float g0 = scale * pull[0]; + const float g1 = scale * pull[1]; + const float g2 = scale * pull[2]; + const float g3 = scale * pull[3]; + const float g4 = scale * pull[4]; +#define NEP_SPIN3_OC_STF_SIDE(target, other) \ + do { \ + (target)[0] += (-g0 * InvSqrt6 + g1 * InvSqrt2) * (other)[0] + \ + g2 * InvSqrt2 * (other)[1] + g4 * InvSqrt2 * (other)[2]; \ + (target)[1] += g2 * InvSqrt2 * (other)[0] + \ + (-g0 * InvSqrt6 - g1 * InvSqrt2) * (other)[1] + \ + g3 * InvSqrt2 * (other)[2]; \ + (target)[2] += g4 * InvSqrt2 * (other)[0] + \ + g3 * InvSqrt2 * (other)[1] + 2.0f * g0 * InvSqrt6 * (other)[2]; \ + } while (false) + NEP_SPIN3_OC_STF_SIDE(pull_left, right); + NEP_SPIN3_OC_STF_SIDE(pull_right, left); +#undef NEP_SPIN3_OC_STF_SIDE +} + +__device__ __forceinline__ void spin3_oc_add_full_matrix_pull_to_stf5( + const float* full, + float* pull) { + constexpr float InvSqrt6 = 0.40824829046386301637f; + constexpr float InvSqrt2 = 0.70710678118654752440f; + pull[0] += (-full[0] - full[4] + 2.0f * full[8]) * InvSqrt6; + pull[1] += (full[0] - full[4]) * InvSqrt2; + pull[2] += (full[1] + full[3]) * InvSqrt2; + pull[3] += (full[5] + full[7]) * InvSqrt2; + pull[4] += (full[2] + full[6]) * InvSqrt2; +} + +__device__ __forceinline__ void spin3_oc_axial_commutator( + const float* left, + const float* right, + float* out) { + float l[9], r[9], comm[9] = {}; + spin3_oc_expand_stf5(left, l); + spin3_oc_expand_stf5(right, r); + for (int a = 0; a < 3; ++a) { + for (int b = 0; b < 3; ++b) { + for (int k = 0; k < 3; ++k) { + comm[3 * a + b] += + l[3 * a + k] * r[3 * k + b] - + r[3 * a + k] * l[3 * k + b]; + } + } + } + out[0] = comm[7]; + out[1] = comm[2]; + out[2] = comm[3]; +} + +__device__ __forceinline__ void spin3_oc_add_commutator_axial_pull( + const float* left, + const float* right, + const float* pull, + float* pull_left, + float* pull_right) { + float l[9], r[9], gl[9] = {}, gr[9] = {}, h[9] = {}; + spin3_oc_expand_stf5(left, l); + spin3_oc_expand_stf5(right, r); + h[7] = pull[0]; + h[2] = pull[1]; + h[3] = pull[2]; + for (int a = 0; a < 3; ++a) { + for (int b = 0; b < 3; ++b) { + for (int k = 0; k < 3; ++k) { + gl[3 * a + k] += h[3 * a + b] * r[3 * k + b]; + gr[3 * k + b] += h[3 * a + b] * l[3 * a + k]; + gr[3 * a + k] -= h[3 * a + b] * l[3 * k + b]; + gl[3 * k + b] -= h[3 * a + b] * r[3 * a + k]; + } + } + } + spin3_oc_add_full_matrix_pull_to_stf5(gl, pull_left); + spin3_oc_add_full_matrix_pull_to_stf5(gr, pull_right); +} + +template +__device__ __forceinline__ void spin3_oc_project_density( + const float* __restrict__ center, + const float* __restrict__ projection, + int channels, + int density_offset, + int leg, + int row, + float* __restrict__ out) { + for (int k = 0; k < Width; ++k) { + out[k] = 0.0f; + for (int source = 0; source < channels; ++source) { + out[k] += spin3_oc_mix(projection, channels, leg, row, source) * + center[spin3_oc_channel_offset(source) + density_offset + k]; + } + } +} + +template +__device__ __forceinline__ float spin3_oc_dotn( + const float* left, + const float* right) { + float value = 0.0f; + for (int k = 0; k < Width; ++k) { + value += left[k] * right[k]; + } + return value; +} + +__device__ __forceinline__ void spin3_oc_qp_matrix( + const float* qp, + int spin_component, + float* matrix) { + float coefficients[5]; + for (int k = 0; k < 5; ++k) { + coefficients[k] = qp[3 * k + spin_component]; + } + spin3_oc_expand_stf5(coefficients, matrix); +} + +__device__ __forceinline__ void spin3_oc_qp_vector( + const float* qp, + float* vector) { + vector[0] = 0.0f; + vector[1] = 0.0f; + vector[2] = 0.0f; + for (int spin_component = 0; spin_component < 3; ++spin_component) { + float matrix[9]; + spin3_oc_qp_matrix(qp, spin_component, matrix); + for (int a = 0; a < 3; ++a) { + vector[a] += matrix[3 * a + spin_component]; + } + } +} + +__device__ __forceinline__ void spin3_oc_l11_axis_from_canonical( + const float* si, + float longitudinal, + const float* axial, + const float* stf_first, + float* axis) { + float matrix[9], matrix_on_spin[3], axial_cross_spin[3]; + spin3_oc_expand_stf5(stf_first, matrix); + for (int a = 0; a < 3; ++a) { + matrix_on_spin[a] = matrix[3 * a] * si[0] + + matrix[3 * a + 1] * si[1] + matrix[3 * a + 2] * si[2]; + } + spin3_cross3(axial, si, axial_cross_spin); + for (int d = 0; d < 3; ++d) { + axis[d] = (2.0f / 3.0f) * longitudinal * si[d] - + matrix_on_spin[d] - 0.5f * axial_cross_spin[d]; + } +} + +__device__ __forceinline__ void spin3_oc_qp_raw_matrix( + const float* moment, + const float* qp, + int spin_component, + float* matrix) { + spin3_oc_qp_matrix(qp, spin_component, matrix); + for (int a = 0; a < 3; ++a) { + matrix[3 * a + a] += moment[spin_component] / 3.0f; + } +} + +__device__ __forceinline__ float spin3_oc_l22_scalar_from_canonical( + const float* si, + const float* moment, + const float* projected_q, + const float* projected_qp) { + float q_matrix[9], q_on_spin[3]; + spin3_oc_expand_stf5(projected_q, q_matrix); + for (int a = 0; a < 3; ++a) { + q_on_spin[a] = 0.0f; + for (int b = 0; b < 3; ++b) { + q_on_spin[a] += q_matrix[3 * a + b] * si[b]; + } + } + float value = 0.0f; + for (int spin_component = 0; spin_component < 3; ++spin_component) { + float raw_second[9]; + spin3_oc_qp_raw_matrix( + moment, projected_qp, spin_component, raw_second); + for (int a = 0; a < 3; ++a) { + value -= raw_second[3 * spin_component + a] * q_on_spin[a]; + for (int b = 0; b < 3; ++b) { + value += q_matrix[3 * spin_component + a] * + raw_second[3 * a + b] * si[b]; + } + } + } + return value; +} + + +template +__global__ void build_spin3_oc_density_bank( + SpinPolynomialLayout layout, + int atom_count, + int atom_stride, + int struct_dim, + int num_types, + int spin_basis_size, + float spin_cutoff, + const float* __restrict__ spin_cutoff_pair, + int spin_coefficient_offset, + SimulationBox box, + const int* __restrict__ types, + const int* __restrict__ spin_dof_type_active, + const int* __restrict__ spin_env_type_active, + const double* __restrict__ positions_soa3, + const double* __restrict__ slot_r12, + int r12_plane_size, + const double* __restrict__ spins_soa3, + const int* __restrict__ nn_radial, + const int* __restrict__ nl_radial_slot_major, + const float* __restrict__ descriptor_coefficients, + float* __restrict__ descriptors, + float* __restrict__ moments) { + const int work = blockIdx.x * blockDim.x + threadIdx.x; + const int atom = work / C; + const int channel = work - atom * C; + if (atom >= atom_count) return; + + float density[kSpin3OcDensityStride] = {}; + float same[C * (C + 1) / 2] = {}; + float edge_sj2 = 0.0f; + float edge_dot2 = 0.0f; + float edge_gate = 0.0f; + float angular_l1[3] = {}; + float angular_l2[5] = {}; + const bool active = spin_dof_type_active[types[atom]] != 0; + if (active) { + const int neighbor_count = nn_radial[atom]; + for (int slot = 0; slot < neighbor_count; ++slot) { + const int neighbor = nl_radial_slot_major[slot * atom_stride + atom]; + if (neighbor < 0 || spin_env_type_active[types[neighbor]] == 0) continue; + float r[3], dist, si[3], sj[3], weights[C], derivatives[C]; + if (!load_spin3_edge_f32( + atom, neighbor, atom_stride, num_types, spin_basis_size, + spin_cutoff, spin_cutoff_pair, box, types, positions_soa3, slot_r12, + r12_plane_size, slot * atom_stride + atom, spins_soa3, + descriptor_coefficients, spin_coefficient_offset, r, dist, si, + sj, weights, derivatives)) continue; + const float weight = weights[channel]; + const float si2 = spin3_dot3(si, si); + const float sj2 = spin3_dot3(sj, sj); + const float dot = spin3_dot3(si, sj); + const float longitudinal = spin3_dot3(r, sj); + float axial[3], qrr[5], edge_stf[5]; + spin3_cross3(r, sj, axial); + spin3_oc_stf5_outer(r, r, qrr); + spin3_oc_stf5_outer(r, sj, edge_stf); + for (int d = 0; d < 3; ++d) { + density[kSpin3OcM + d] += weight * sj[d]; + density[kSpin3OcP + d] += weight * r[d]; + density[kSpin3OcX + d] += weight * axial[d]; + density[kSpin3OcDM + d] += weight * dot * sj[d]; + if (layout.angular_l1_moment_offset >= 0) { + angular_l1[d] += weight * dot * r[d]; + } + } + density[kSpin3OcL] += weight * longitudinal; + for (int k = 0; k < 5; ++k) { + density[kSpin3OcT + k] += weight * edge_stf[k]; + density[kSpin3OcQ + k] += weight * qrr[k]; + if (layout.angular_l2_moment_offset >= 0) { + angular_l2[k] += weight * dot * qrr[k]; + } + for (int d = 0; d < 3; ++d) { + density[kSpin3OcQP + 3 * k + d] += weight * qrr[k] * sj[d]; + } + } + edge_sj2 += weight * sj2; + edge_dot2 += weight * dot * dot; + edge_gate += weight * dot * (si2 + sj2); + if (channel == 0 && layout.correlation_same_edge >= 0) { + for (int left = 0; left < C; ++left) { + for (int right = left; right < C; ++right) { + same[spin3_oc_pair_index(C, left, right)] += + weights[left] * weights[right] * dot * dot; + } + } + } + } + } + float* center = moments + atom * layout.moment_count; + const int base = spin3_oc_channel_offset(channel); + for (int k = 0; k < kSpin3OcDensityStride; ++k) center[base + k] = density[k]; + if (layout.angular_l1_moment_offset >= 0) { + for (int d = 0; d < 3; ++d) { + center[layout.angular_l1_moment_offset + 3 * channel + d] = angular_l1[d]; + } + } + if (layout.angular_l2_moment_offset >= 0) { + for (int k = 0; k < 5; ++k) { + center[layout.angular_l2_moment_offset + 5 * channel + k] = angular_l2[k]; + } + } + if (channel == 0) { + const int same_offset = spin3_oc_same_offset(C); + for (int pair = 0; pair < layout.pair_count; ++pair) { + center[same_offset + pair] = same[pair]; + } + } +#define NEP_SPIN3_OC_STORE_DYNAMIC(index, value) \ + do { if ((index) >= 0) descriptors[atom + atom_stride * \ + (struct_dim + (index) + channel)] = active ? (value) : 0.0f; } while (false) + NEP_SPIN3_OC_STORE_DYNAMIC(layout.edge_l0_neighbor_s2, edge_sj2); + NEP_SPIN3_OC_STORE_DYNAMIC(layout.edge_l0_dot2, edge_dot2); + NEP_SPIN3_OC_STORE_DYNAMIC(layout.edge_l0_moment_gate, edge_gate); +#undef NEP_SPIN3_OC_STORE_DYNAMIC +} + +template +__global__ void contract_spin3_oc_descriptors( + SpinPolynomialLayout layout, + int atom_count, + int atom_stride, + int struct_dim, + const int* __restrict__ types, + const int* __restrict__ spin_dof_type_active, + const double* __restrict__ spins_soa3, + const float* __restrict__ projection, + const float* __restrict__ moments, + float* __restrict__ descriptors) { + const int atom = blockIdx.x * blockDim.x + threadIdx.x; + if (atom >= atom_count) return; + const bool active = spin_dof_type_active[types[atom]] != 0; + const float* center = moments + atom * layout.moment_count; + float si[3] = { + static_cast(spins_soa3[atom]), + static_cast(spins_soa3[atom_stride + atom]), + static_cast(spins_soa3[2 * atom_stride + atom])}; +#define NEP_SPIN3_OC_STORE_AT(index, value) \ + do { if ((index) >= 0) descriptors[atom + atom_stride * \ + (struct_dim + (index))] = active ? (value) : 0.0f; } while (false) + NEP_SPIN3_OC_STORE_AT(layout.local_s2, spin3_dot3(si, si)); + float local_q[5]; + float first_dot[C]; + spin3_oc_stf5_outer(si, si, local_q); + for (int c = 0; c < C; ++c) { + const int base = spin3_oc_channel_offset(c); + const float* m = center + base + kSpin3OcM; + first_dot[c] = spin3_dot3(si, m); + NEP_SPIN3_OC_STORE_AT(layout.edge_l0_dot + c, first_dot[c]); + if (layout.edge_l2_pair >= 0) { + float q_on_spin[3]; + spin3_oc_qp_vector(center + base + kSpin3OcQP, q_on_spin); + NEP_SPIN3_OC_STORE_AT( + layout.edge_l2_pair + c, spin3_dot3(si, q_on_spin)); + NEP_SPIN3_OC_STORE_AT( + layout.center_l2_environment + c, + spin3_oc_dotn<5>(center + base + kSpin3OcQ, local_q)); + } + if (layout.density_l0_self >= 0) { + NEP_SPIN3_OC_STORE_AT( + layout.density_l0_self + c, spin3_oc_dotn<3>(m, m)); + if (layout.density_l1_longitudinal_self >= 0) { + NEP_SPIN3_OC_STORE_AT( + layout.density_l1_longitudinal_self + c, + center[base + kSpin3OcL] * center[base + kSpin3OcL]); + NEP_SPIN3_OC_STORE_AT( + layout.density_l1_axial_self + c, + spin3_oc_dotn<3>(center + base + kSpin3OcX, + center + base + kSpin3OcX)); + NEP_SPIN3_OC_STORE_AT( + layout.density_l1_stf_self + c, + spin3_oc_dotn<5>(center + base + kSpin3OcT, + center + base + kSpin3OcT)); + } + if (layout.density_l1_product_self >= 0) { + const float raw_norm = + center[base + kSpin3OcL] * center[base + kSpin3OcL] / 3.0f + + spin3_oc_dotn<3>(center + base + kSpin3OcX, + center + base + kSpin3OcX) * 0.5f + + spin3_oc_dotn<5>(center + base + kSpin3OcT, + center + base + kSpin3OcT); + NEP_SPIN3_OC_STORE_AT(layout.density_l1_product_self + c, raw_norm); + } + if (layout.density_l2_product_self >= 0) { + NEP_SPIN3_OC_STORE_AT( + layout.density_l2_product_self + c, + spin3_oc_dotn<15>(center + base + kSpin3OcQP, + center + base + kSpin3OcQP)); + } + NEP_SPIN3_OC_STORE_AT( + layout.density_l0_dot_response + c, + spin3_oc_dotn<3>(m, center + base + kSpin3OcDM)); + } + } + if (layout.correlation_same_edge >= 0) { + const int same_offset = spin3_oc_same_offset(C); + for (int left = 0; left < C; ++left) { + for (int right = left; right < C; ++right) { + const int pair = spin3_oc_pair_index(C, left, right); + const float same = center[same_offset + pair]; + NEP_SPIN3_OC_STORE_AT(layout.correlation_same_edge + pair, same); + NEP_SPIN3_OC_STORE_AT( + layout.correlation_distinct_neighbor + pair, + first_dot[left] * first_dot[right] - same); + if (layout.correlation_distinct_l1 >= 0) { + NEP_SPIN3_OC_STORE_AT( + layout.correlation_distinct_l1 + pair, + spin3_oc_dotn<3>( + center + layout.angular_l1_moment_offset + 3 * left, + center + layout.angular_l1_moment_offset + 3 * right) - same); + } + if (layout.correlation_distinct_l2 >= 0) { + NEP_SPIN3_OC_STORE_AT( + layout.correlation_distinct_l2 + pair, + 1.5f * spin3_oc_dotn<5>( + center + layout.angular_l2_moment_offset + 5 * left, + center + layout.angular_l2_moment_offset + 5 * right) - same); + } + } + } + } + for (int row = 0; row < C; ++row) { + if (layout.edge_l11_axial >= 0) { + float m0[3], p0[3], p1[3], x0[3], l0[1], t0[5], w0[3]; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcM, 0, row, m0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 0, row, p0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 1, row, p1); + spin3_oc_project_density<1>(center, projection, C, kSpin3OcL, 0, row, l0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 0, row, x0); + spin3_oc_project_density<5>(center, projection, C, kSpin3OcT, 0, row, t0); + spin3_cross3(si, m0, w0); + float p_axis[3], l11_axis[3]; + spin3_cross3(p0, p1, p_axis); + spin3_oc_l11_axis_from_canonical(si, l0[0], x0, t0, l11_axis); + if (layout.coupling_l11_axial >= 0) { + NEP_SPIN3_OC_STORE_AT( + layout.coupling_l11_axial + row, spin3_dot3(p_axis, w0)); + } + NEP_SPIN3_OC_STORE_AT( + layout.edge_l11_axial + row, spin3_dot3(p0, l11_axis)); + if (layout.coupling_l11_dot_response >= 0) { + float dm0[3], dw0[3]; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcDM, 0, row, dm0); + spin3_cross3(si, dm0, dw0); + NEP_SPIN3_OC_STORE_AT( + layout.coupling_l11_dot_response + row, + spin3_dot3(p_axis, dw0)); + } + if (layout.coupling_l111_p_m_x >= 0) { + float m1[3], x2[3], cross_value[3]; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcM, 1, row, m1); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 2, row, x2); + spin3_cross3(m1, x2, cross_value); + NEP_SPIN3_OC_STORE_AT( + layout.coupling_l111_p_m_x + row, + spin3_dot3(p0, cross_value)); + } + if (layout.coupling_l111_bulk >= 0) { + float p2[3], x3[3], cross12[3]; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 2, row, p2); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 3, row, x3); + spin3_cross3(p1, p2, cross12); + NEP_SPIN3_OC_STORE_AT( + layout.coupling_l111_bulk + row, + -spin3_dot3(p0, cross12) * spin3_dot3(si, x3)); + } + } + if (layout.edge_l22_axial >= 0) { + float m0[3], p0[3], p1[3], x0[3], q0[5], q1[5], qp0[15]; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcM, 0, row, m0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 0, row, p0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 1, row, p1); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 0, row, x0); + spin3_oc_project_density<5>(center, projection, C, kSpin3OcQ, 0, row, q0); + spin3_oc_project_density<5>(center, projection, C, kSpin3OcQ, 1, row, q1); + spin3_oc_project_density<15>(center, projection, C, kSpin3OcQP, 0, row, qp0); + float q_axis[3], w0[3]; + spin3_oc_axial_commutator(q0, q1, q_axis); + spin3_cross3(si, m0, w0); + if (layout.coupling_l22_axial >= 0) { + NEP_SPIN3_OC_STORE_AT( + layout.coupling_l22_axial + row, spin3_dot3(q_axis, w0)); + } + NEP_SPIN3_OC_STORE_AT( + layout.edge_l22_axial + row, + spin3_oc_l22_scalar_from_canonical(si, m0, q0, qp0)); + if (layout.coupling_l22_dot_response >= 0) { + float dm0[3], dw0[3]; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcDM, 0, row, dm0); + spin3_cross3(si, dm0, dw0); + NEP_SPIN3_OC_STORE_AT( + layout.coupling_l22_dot_response + row, + spin3_dot3(q_axis, dw0)); + } + if (layout.coupling_l111_p_qs_x >= 0) { + float qp1[15], qs1[3], x2[3], cross_value[3]; + spin3_oc_project_density<15>(center, projection, C, kSpin3OcQP, 1, row, qp1); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 2, row, x2); + spin3_oc_qp_vector(qp1, qs1); + spin3_cross3(qs1, x2, cross_value); + NEP_SPIN3_OC_STORE_AT( + layout.coupling_l111_p_qs_x + row, + spin3_dot3(p0, cross_value)); + } + if (layout.coupling_l112_edge_response >= 0) { + float q_on_p1[3], mixed_axis[3]; + spin3_oc_stf5_matvec(q0, p1, q_on_p1); + spin3_cross3(p1, q_on_p1, mixed_axis); + NEP_SPIN3_OC_STORE_AT( + layout.coupling_l112_edge_response + row, + -spin3_dot3(p0, mixed_axis) * spin3_dot3(si, x0)); + } + } + } +#undef NEP_SPIN3_OC_STORE_AT +} diff --git a/src/force/nep_spin/nep_spin3_force.cuh b/src/force/nep_spin/nep_spin3_force.cuh new file mode 100644 index 000000000..0f96f4bf3 --- /dev/null +++ b/src/force/nep_spin/nep_spin3_force.cuh @@ -0,0 +1,858 @@ +/* + This file is part of GPUMD. + SPDX-License-Identifier: LGPL-3.0-or-later +*/ + +#pragma once + +// Unified O/C spin3 analytical force and magnetic-force kernels. +template +__device__ __forceinline__ void spin3_oc_accumulate_pull( + float* target, + float value) { + if (AtomicPull) { + atomicAdd(target, value); + } else { + *target += value; + } +} + +template +__device__ __forceinline__ void spin3_oc_add_projected_pull( + float* __restrict__ pull, + const float* __restrict__ projection, + int density_offset, + int leg, + int row, + const float* __restrict__ projected_pull) { + for (int source = 0; source < C; ++source) { + const float scale = spin3_oc_mix(projection, C, leg, row, source); + for (int k = 0; k < Width; ++k) { + float* target = + pull + spin3_oc_channel_offset(source) + density_offset + k; + if (AtomicPull) { + atomicAdd(target, scale * projected_pull[k]); + } else { + *target += scale * projected_pull[k]; + } + } + } +} + +__device__ __forceinline__ void spin3_oc_reverse_mixed_chirality( + const float* p0, + const float* p1, + const float* q0, + float scale, + float* gp0, + float* gp1, + float* gq0) { + float q_on_p1[3], cross_value[3]; + spin3_oc_stf5_matvec(q0, p1, q_on_p1); + spin3_cross3(p1, q_on_p1, cross_value); + float cross_pull[3] = { + scale * p0[0], scale * p0[1], scale * p0[2]}; + for (int d = 0; d < 3; ++d) { + gp0[d] += scale * cross_value[d]; + } + float gy[3] = {}; + spin3_add_cross_pull(p1, q_on_p1, cross_pull, gp1, gy); + float matrix_pull[9]; + for (int a = 0; a < 3; ++a) { + for (int b = 0; b < 3; ++b) { + matrix_pull[3 * a + b] = gy[a] * p1[b]; + } + } + spin3_oc_add_full_matrix_pull_to_stf5(matrix_pull, gq0); + float q_times_gy[3]; + spin3_oc_stf5_matvec(q0, gy, q_times_gy); + for (int d = 0; d < 3; ++d) { + gp1[d] += q_times_gy[d]; + } +} + +__device__ __forceinline__ void spin3_oc_reverse_triple_product( + const float* left, + const float* middle, + const float* right, + float alpha, + float* gleft, + float* gmiddle, + float* gright) { + float cross_value[3], cross_pull[3]; + spin3_cross3(middle, right, cross_value); + for (int d = 0; d < 3; ++d) { + gleft[d] += alpha * cross_value[d]; + cross_pull[d] = alpha * left[d]; + } + spin3_add_cross_pull(middle, right, cross_pull, gmiddle, gright); +} + +__device__ __forceinline__ void spin3_oc_add_qp_vector_pull( + const float* vector_pull, + float* qp_pull) { + for (int spin_component = 0; spin_component < 3; ++spin_component) { + float matrix_pull[9] = {}, component_pull[5] = {}; + for (int a = 0; a < 3; ++a) { + matrix_pull[3 * a + spin_component] = vector_pull[a]; + } + spin3_oc_add_full_matrix_pull_to_stf5(matrix_pull, component_pull); + for (int k = 0; k < 5; ++k) { + qp_pull[3 * k + spin_component] += component_pull[k]; + } + } +} + +__device__ __forceinline__ void spin3_oc_reverse_l11_axis_from_canonical( + const float* si, + float longitudinal, + const float* axial, + const float* stf_first, + const float* axis_pull, + float* spin_pull, + float* longitudinal_pull, + float* axial_pull, + float* stf_first_pull) { + float matrix[9], matrix_on_pull[3]; + spin3_oc_expand_stf5(stf_first, matrix); + for (int a = 0; a < 3; ++a) { + matrix_on_pull[a] = matrix[3 * a] * axis_pull[0] + + matrix[3 * a + 1] * axis_pull[1] + + matrix[3 * a + 2] * axis_pull[2]; + spin_pull[a] += + (2.0f / 3.0f) * longitudinal * axis_pull[a] - matrix_on_pull[a]; + } + longitudinal_pull[0] += + (2.0f / 3.0f) * spin3_dot3(axis_pull, si); + float matrix_pull[9]; + for (int a = 0; a < 3; ++a) { + for (int b = 0; b < 3; ++b) { + matrix_pull[3 * a + b] = -axis_pull[a] * si[b]; + } + } + spin3_oc_add_full_matrix_pull_to_stf5(matrix_pull, stf_first_pull); + float cross_pull[3] = { + -0.5f * axis_pull[0], + -0.5f * axis_pull[1], + -0.5f * axis_pull[2]}; + spin3_add_cross_pull(axial, si, cross_pull, axial_pull, spin_pull); +} + +__device__ __forceinline__ void spin3_oc_reverse_l22_scalar_from_canonical( + const float* si, + const float* moment, + const float* projected_q, + const float* projected_qp, + float scale, + float* spin_pull, + float* moment_pull, + float* q_pull, + float* qp_pull) { + float q_matrix[9], q_matrix_pull[9] = {}; + float q_on_spin[3], q_on_spin_pull[3] = {}; + spin3_oc_expand_stf5(projected_q, q_matrix); + for (int a = 0; a < 3; ++a) { + q_on_spin[a] = 0.0f; + for (int b = 0; b < 3; ++b) { + q_on_spin[a] += q_matrix[3 * a + b] * si[b]; + } + } + for (int spin_component = 0; spin_component < 3; ++spin_component) { + float raw_second[9], raw_second_pull[9] = {}; + spin3_oc_qp_raw_matrix( + moment, projected_qp, spin_component, raw_second); + for (int a = 0; a < 3; ++a) { + raw_second_pull[3 * spin_component + a] -= + scale * q_on_spin[a]; + q_on_spin_pull[a] -= + scale * raw_second[3 * spin_component + a]; + for (int b = 0; b < 3; ++b) { + q_matrix_pull[3 * spin_component + a] += + scale * raw_second[3 * a + b] * si[b]; + raw_second_pull[3 * a + b] += + scale * q_matrix[3 * spin_component + a] * si[b]; + spin_pull[b] += + scale * q_matrix[3 * spin_component + a] * + raw_second[3 * a + b]; + } + } + moment_pull[spin_component] += + (raw_second_pull[0] + raw_second_pull[4] + + raw_second_pull[8]) / 3.0f; + float component_pull[5] = {}; + spin3_oc_add_full_matrix_pull_to_stf5( + raw_second_pull, component_pull); + for (int k = 0; k < 5; ++k) { + qp_pull[3 * k + spin_component] += component_pull[k]; + } + } + for (int a = 0; a < 3; ++a) { + for (int b = 0; b < 3; ++b) { + q_matrix_pull[3 * a + b] += q_on_spin_pull[a] * si[b]; + spin_pull[b] += q_on_spin_pull[a] * q_matrix[3 * a + b]; + } + } + spin3_oc_add_full_matrix_pull_to_stf5(q_matrix_pull, q_pull); +} + + +template +__device__ __noinline__ void build_spin3_oc_center_pull_row( + SpinPolynomialLayout layout, + int atom, + int row, + unsigned active_mask, + int atom_stride, + int struct_dim, + const double* __restrict__ spins_soa3, + const float* __restrict__ fp, + const float* __restrict__ projection, + const float* __restrict__ moments, + float* __restrict__ pull, + double* __restrict__ mforce_soa3) { + const float* center = moments + atom * layout.moment_count; + float si[3] = { + static_cast(spins_soa3[atom]), + static_cast(spins_soa3[atom_stride + atom]), + static_cast(spins_soa3[2 * atom_stride + atom])}; + float direct_spin_pull[3] = {}; +#define NEP_SPIN3_OC_FP_DYNAMIC(index) \ + fp[atom + atom_stride * (struct_dim + (index))] + + if (row == 0) { + float first_dot[C], first_dot_pull[C] = {}; + float local_q[5]; + spin3_oc_stf5_outer(si, si, local_q); + for (int c = 0; c < C; ++c) { + const int base = spin3_oc_channel_offset(c); + const float* moment = center + base + kSpin3OcM; + first_dot[c] = spin3_dot3(si, moment); + const float a_dot = NEP_SPIN3_OC_FP_DYNAMIC(layout.edge_l0_dot + c); + first_dot_pull[c] += a_dot; + if (layout.edge_l2_pair >= 0) { + float qp_vector[3], qp_vector_pull[3]; + spin3_oc_qp_vector(center + base + kSpin3OcQP, qp_vector); + const float a_pair = + NEP_SPIN3_OC_FP_DYNAMIC(layout.edge_l2_pair + c); + for (int d = 0; d < 3; ++d) { + qp_vector_pull[d] = a_pair * si[d]; + direct_spin_pull[d] += a_pair * qp_vector[d]; + } + float qp_pull[15] = {}; + spin3_oc_add_qp_vector_pull(qp_vector_pull, qp_pull); + for (int k = 0; k < 15; ++k) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcQP + k, qp_pull[k]); + } + const float a_env = + NEP_SPIN3_OC_FP_DYNAMIC(layout.center_l2_environment + c); + for (int k = 0; k < 5; ++k) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcQ + k, a_env * local_q[k]); + } + float left_pull[3] = {}, right_pull[3] = {}; + spin3_oc_add_stf5_outer_pull( + si, si, center + base + kSpin3OcQ, a_env, + left_pull, right_pull); + for (int d = 0; d < 3; ++d) { + direct_spin_pull[d] += left_pull[d] + right_pull[d]; + } + } + if (layout.density_l0_self >= 0) { + const float a_m = + NEP_SPIN3_OC_FP_DYNAMIC(layout.density_l0_self + c); + const float a_dm = + NEP_SPIN3_OC_FP_DYNAMIC(layout.density_l0_dot_response + c); + for (int d = 0; d < 3; ++d) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcM + d, + 2.0f * a_m * center[base + kSpin3OcM + d] + + a_dm * center[base + kSpin3OcDM + d]); + spin3_oc_accumulate_pull(pull + base + kSpin3OcDM + d, + a_dm * center[base + kSpin3OcM + d]); + } + if (layout.density_l1_longitudinal_self >= 0) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcL, + 2.0f * NEP_SPIN3_OC_FP_DYNAMIC( + layout.density_l1_longitudinal_self + c) * + center[base + kSpin3OcL]); + const float a_x = NEP_SPIN3_OC_FP_DYNAMIC( + layout.density_l1_axial_self + c); + const float a_t = NEP_SPIN3_OC_FP_DYNAMIC( + layout.density_l1_stf_self + c); + for (int d = 0; d < 3; ++d) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcX + d, + 2.0f * a_x * center[base + kSpin3OcX + d]); + } + for (int k = 0; k < 5; ++k) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcT + k, + 2.0f * a_t * center[base + kSpin3OcT + k]); + } + } + if (layout.density_l1_product_self >= 0) { + const float a = NEP_SPIN3_OC_FP_DYNAMIC( + layout.density_l1_product_self + c); + spin3_oc_accumulate_pull(pull + base + kSpin3OcL, + (2.0f / 3.0f) * a * center[base + kSpin3OcL]); + for (int d = 0; d < 3; ++d) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcX + d, + a * center[base + kSpin3OcX + d]); + } + for (int k = 0; k < 5; ++k) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcT + k, + 2.0f * a * center[base + kSpin3OcT + k]); + } + } + if (layout.density_l2_product_self >= 0) { + const float a = NEP_SPIN3_OC_FP_DYNAMIC( + layout.density_l2_product_self + c); + for (int k = 0; k < 15; ++k) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcQP + k, + 2.0f * a * center[base + kSpin3OcQP + k]); + } + } + } + } + if (layout.correlation_same_edge >= 0) { + const int same_offset = spin3_oc_same_offset(C); + for (int left = 0; left < C; ++left) { + for (int right = left; right < C; ++right) { + const int pair = spin3_oc_pair_index(C, left, right); + const float a_same = NEP_SPIN3_OC_FP_DYNAMIC( + layout.correlation_same_edge + pair); + const float a_distinct = NEP_SPIN3_OC_FP_DYNAMIC( + layout.correlation_distinct_neighbor + pair); + const float a_l1 = layout.correlation_distinct_l1 >= 0 + ? NEP_SPIN3_OC_FP_DYNAMIC(layout.correlation_distinct_l1 + pair) + : 0.0f; + const float a_l2 = layout.correlation_distinct_l2 >= 0 + ? NEP_SPIN3_OC_FP_DYNAMIC(layout.correlation_distinct_l2 + pair) + : 0.0f; + spin3_oc_accumulate_pull( + pull + same_offset + pair, a_same - a_distinct - a_l1 - a_l2); + first_dot_pull[left] += a_distinct * first_dot[right]; + first_dot_pull[right] += a_distinct * first_dot[left]; + if (layout.correlation_distinct_l1 >= 0) { + for (int d = 0; d < 3; ++d) { + const float left_value = center[ + layout.angular_l1_moment_offset + 3 * left + d]; + const float right_value = center[ + layout.angular_l1_moment_offset + 3 * right + d]; + spin3_oc_accumulate_pull( + pull + layout.angular_l1_moment_offset + 3 * left + d, + a_l1 * right_value); + spin3_oc_accumulate_pull( + pull + layout.angular_l1_moment_offset + 3 * right + d, + a_l1 * left_value); + } + } + if (layout.correlation_distinct_l2 >= 0) { + for (int k = 0; k < 5; ++k) { + const float left_value = center[ + layout.angular_l2_moment_offset + 5 * left + k]; + const float right_value = center[ + layout.angular_l2_moment_offset + 5 * right + k]; + spin3_oc_accumulate_pull( + pull + layout.angular_l2_moment_offset + 5 * left + k, + 1.5f * a_l2 * right_value); + spin3_oc_accumulate_pull( + pull + layout.angular_l2_moment_offset + 5 * right + k, + 1.5f * a_l2 * left_value); + } + } + } + } + } + for (int c = 0; c < C; ++c) { + const int base = spin3_oc_channel_offset(c); + for (int d = 0; d < 3; ++d) { + spin3_oc_accumulate_pull(pull + base + kSpin3OcM + d, + first_dot_pull[c] * si[d]); + direct_spin_pull[d] += + first_dot_pull[c] * center[base + kSpin3OcM + d]; + } + } + } + + __syncwarp(active_mask); + + if (layout.edge_l11_axial >= 0) { + float m0[3], p0[3], p1[3], x0[3], l0[1], t0[5], w0[3]; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcM, 0, row, m0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 0, row, p0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 1, row, p1); + spin3_oc_project_density<1>(center, projection, C, kSpin3OcL, 0, row, l0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 0, row, x0); + spin3_oc_project_density<5>(center, projection, C, kSpin3OcT, 0, row, t0); + spin3_cross3(si, m0, w0); + float gm0[3] = {}, gp0[3] = {}, gp1[3] = {}, gx0[3] = {}; + float gl0[1] = {}, gt0[5] = {}, gw0[3] = {}; + float p_axis[3], p_axis_pull[3] = {}; + spin3_cross3(p0, p1, p_axis); + if (layout.coupling_l11_axial >= 0) { + const float a_l11 = NEP_SPIN3_OC_FP_DYNAMIC( + layout.coupling_l11_axial + row); + for (int d = 0; d < 3; ++d) { + p_axis_pull[d] += a_l11 * w0[d]; + gw0[d] += a_l11 * p_axis[d]; + } + } + float l11_axis[3], l11_axis_pull[3]; + spin3_oc_l11_axis_from_canonical(si, l0[0], x0, t0, l11_axis); + const float a_edge = NEP_SPIN3_OC_FP_DYNAMIC(layout.edge_l11_axial + row); + for (int d = 0; d < 3; ++d) { + gp0[d] += a_edge * l11_axis[d]; + l11_axis_pull[d] = a_edge * p0[d]; + } + spin3_oc_reverse_l11_axis_from_canonical( + si, l0[0], x0, t0, l11_axis_pull, direct_spin_pull, + gl0, gx0, gt0); + if (layout.coupling_l11_dot_response >= 0) { + float dm0[3], dw0[3]; + float gdm0[3] = {}, gdw0[3] = {}; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcDM, 0, row, dm0); + spin3_cross3(si, dm0, dw0); + const float a_dot = NEP_SPIN3_OC_FP_DYNAMIC( + layout.coupling_l11_dot_response + row); + for (int d = 0; d < 3; ++d) { + p_axis_pull[d] += a_dot * dw0[d]; + gdw0[d] += a_dot * p_axis[d]; + } + spin3_add_cross_pull(si, dm0, gdw0, direct_spin_pull, gdm0); + spin3_oc_add_projected_pull( + pull, projection, kSpin3OcDM, 0, row, gdm0); + } + if (layout.coupling_l111_p_m_x >= 0) { + float m1[3], x2[3], gm1[3] = {}, gx2[3] = {}; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcM, 1, row, m1); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 2, row, x2); + spin3_oc_reverse_triple_product( + p0, m1, x2, + NEP_SPIN3_OC_FP_DYNAMIC(layout.coupling_l111_p_m_x + row), + gp0, gm1, gx2); + spin3_oc_add_projected_pull( + pull, projection, kSpin3OcM, 1, row, gm1); + spin3_oc_add_projected_pull( + pull, projection, kSpin3OcX, 2, row, gx2); + } + if (layout.coupling_l111_bulk >= 0) { + float p2[3], x3[3], gp2[3] = {}, gx3[3] = {}; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 2, row, p2); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 3, row, x3); + float cross12[3]; + spin3_cross3(p1, p2, cross12); + const float chirality = spin3_dot3(p0, cross12); + const float edge_response = -spin3_dot3(si, x3); + const float alpha = NEP_SPIN3_OC_FP_DYNAMIC( + layout.coupling_l111_bulk + row); + spin3_oc_reverse_triple_product( + p0, p1, p2, alpha * edge_response, gp0, gp1, gp2); + for (int d = 0; d < 3; ++d) { + gx3[d] -= alpha * chirality * si[d]; + direct_spin_pull[d] -= alpha * chirality * x3[d]; + } + spin3_oc_add_projected_pull( + pull, projection, kSpin3OcP, 2, row, gp2); + spin3_oc_add_projected_pull( + pull, projection, kSpin3OcX, 3, row, gx3); + } + spin3_add_cross_pull(p0, p1, p_axis_pull, gp0, gp1); + spin3_add_cross_pull(si, m0, gw0, direct_spin_pull, gm0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcM, 0, row, gm0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcP, 0, row, gp0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcP, 1, row, gp1); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcL, 0, row, gl0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcX, 0, row, gx0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcT, 0, row, gt0); + } + + if (layout.edge_l22_axial >= 0) { + float m0[3], p0[3], p1[3], x0[3], q0[5], q1[5], qp0[15], w0[3]; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcM, 0, row, m0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 0, row, p0); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcP, 1, row, p1); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 0, row, x0); + spin3_oc_project_density<5>(center, projection, C, kSpin3OcQ, 0, row, q0); + spin3_oc_project_density<5>(center, projection, C, kSpin3OcQ, 1, row, q1); + spin3_oc_project_density<15>(center, projection, C, kSpin3OcQP, 0, row, qp0); + spin3_cross3(si, m0, w0); + float gm0[3] = {}, gp0[3] = {}, gp1[3] = {}, gx0[3] = {}; + float gq0[5] = {}, gq1[5] = {}, gqp0[15] = {}, gw0[3] = {}; + float q_axis[3], q_axis_pull[3] = {}; + spin3_oc_axial_commutator(q0, q1, q_axis); + if (layout.coupling_l22_axial >= 0) { + const float a_l22 = NEP_SPIN3_OC_FP_DYNAMIC( + layout.coupling_l22_axial + row); + for (int d = 0; d < 3; ++d) { + q_axis_pull[d] += a_l22 * w0[d]; + gw0[d] += a_l22 * q_axis[d]; + } + } + spin3_oc_reverse_l22_scalar_from_canonical( + si, m0, q0, qp0, + NEP_SPIN3_OC_FP_DYNAMIC(layout.edge_l22_axial + row), + direct_spin_pull, gm0, gq0, gqp0); + if (layout.coupling_l22_dot_response >= 0) { + float dm0[3], dw0[3]; + float gdm0[3] = {}, gdw0[3] = {}; + spin3_oc_project_density<3>(center, projection, C, kSpin3OcDM, 0, row, dm0); + spin3_cross3(si, dm0, dw0); + const float a_dot = NEP_SPIN3_OC_FP_DYNAMIC( + layout.coupling_l22_dot_response + row); + for (int d = 0; d < 3; ++d) { + q_axis_pull[d] += a_dot * dw0[d]; + gdw0[d] += a_dot * q_axis[d]; + } + spin3_add_cross_pull(si, dm0, gdw0, direct_spin_pull, gdm0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcDM, 0, row, gdm0); + } + if (layout.coupling_l111_p_qs_x >= 0) { + float qp1[15], qs1[3], x2[3]; + float gqp1[15] = {}, gqs1[3] = {}, gx2[3] = {}; + spin3_oc_project_density<15>(center, projection, C, kSpin3OcQP, 1, row, qp1); + spin3_oc_project_density<3>(center, projection, C, kSpin3OcX, 2, row, x2); + spin3_oc_qp_vector(qp1, qs1); + spin3_oc_reverse_triple_product( + p0, qs1, x2, + NEP_SPIN3_OC_FP_DYNAMIC(layout.coupling_l111_p_qs_x + row), + gp0, gqs1, gx2); + spin3_oc_add_qp_vector_pull(gqs1, gqp1); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcQP, 1, row, gqp1); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcX, 2, row, gx2); + } + if (layout.coupling_l112_edge_response >= 0) { + float q_on_p1[3], mixed_axis[3]; + spin3_oc_stf5_matvec(q0, p1, q_on_p1); + spin3_cross3(p1, q_on_p1, mixed_axis); + const float mixed = spin3_dot3(p0, mixed_axis); + const float edge_sum = -spin3_dot3(si, x0); + const float a_edge = NEP_SPIN3_OC_FP_DYNAMIC( + layout.coupling_l112_edge_response + row); + spin3_oc_reverse_mixed_chirality( + p0, p1, q0, a_edge * edge_sum, gp0, gp1, gq0); + const float edge_pull = a_edge * mixed; + for (int d = 0; d < 3; ++d) { + gx0[d] -= edge_pull * si[d]; + direct_spin_pull[d] -= edge_pull * x0[d]; + } + } + spin3_oc_add_commutator_axial_pull(q0, q1, q_axis_pull, gq0, gq1); + spin3_add_cross_pull(si, m0, gw0, direct_spin_pull, gm0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcM, 0, row, gm0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcP, 0, row, gp0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcP, 1, row, gp1); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcX, 0, row, gx0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcQ, 0, row, gq0); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcQ, 1, row, gq1); + spin3_oc_add_projected_pull(pull, projection, kSpin3OcQP, 0, row, gqp0); + } + for (int d = 0; d < 3; ++d) { + atomicAdd(mforce_soa3 + d * atom_stride + atom, + -static_cast(direct_spin_pull[d])); + } +#undef NEP_SPIN3_OC_FP_DYNAMIC +} + +// Keep runtime and training on the same edge/pull tiling policy. Only the +// output ownership (e.g. per-atom training virial) differs between callers. +template +struct Spin3ForceTile { + static constexpr int block_size = 128; + static constexpr int edge_lanes = C <= 4 ? 8 : (C <= 8 ? 16 : 32); + static constexpr int atoms_per_warp = 32 / edge_lanes; + static constexpr int centers_per_block = block_size / 32 * atoms_per_warp; +}; + +template < + int C, + SpinVirialMode VirialMode, + bool AccumulateSpinTransfer, + int AtomsPerWarp> +__global__ void accumulate_spin3_oc_native_forces( + SpinPolynomialLayout layout, + int atom_count, + int atom_stride, + int struct_dim, + int num_types, + int spin_basis_size, + float spin_cutoff, + const float* __restrict__ spin_cutoff_pair, + SimulationBox box, + const int* __restrict__ types, + const int* __restrict__ spin_dof_type_active, + const int* __restrict__ spin_env_type_active, + const double* __restrict__ positions_soa3, + const double* __restrict__ slot_r12, + int r12_plane_size, + const double* __restrict__ spins_soa3, + const int* __restrict__ nn_radial, + const int* __restrict__ nl_radial, + const float* __restrict__ fp, + const float* __restrict__ descriptor_coefficients, + const float* __restrict__ projection, + const float* __restrict__ moments, + int spin_coefficient_offset, + double* __restrict__ force_soa3, + double* __restrict__ mforce_soa3, + double* __restrict__ virial_soa9, + float* __restrict__ virial_float_soa9, + float* __restrict__ spin_transfer_soa9) { + constexpr bool AccumulateCenterVirial = + VirialMode == SpinVirialMode::center_owned || + VirialMode == SpinVirialMode::center_and_neighbor_float_sink; + static_assert(32 % AtomsPerWarp == 0, "one warp must contain complete center tiles"); + constexpr int EdgeLanes = 32 / AtomsPerWarp; + static_assert(EdgeLanes >= C, + "inline pull construction requires at least one lane per compression row"); + constexpr int WarpsPerBlock = 4; + constexpr int CentersPerBlock = WarpsPerBlock * AtomsPerWarp; + const int warp = threadIdx.x >> 5; + const int lane = threadIdx.x & 31; + const int atom_lane = lane / EdgeLanes; + const int edge_lane = lane - atom_lane * EdgeLanes; + const int center_local = warp * AtomsPerWarp + atom_lane; + const int atom = blockIdx.x * CentersPerBlock + center_local; + const unsigned int center_mask = + (0xffffffffu >> (32 - EdgeLanes)) << (atom_lane * EdgeLanes); + const bool active = + atom < atom_count && spin_dof_type_active[types[atom]] != 0; + if (!active) return; + + extern __shared__ float inline_pull_state[]; + float* inline_pull = + inline_pull_state + static_cast(center_local) * layout.moment_count; + const float* pull = inline_pull; + { + for (int k = edge_lane; k < layout.moment_count; k += EdgeLanes) { + inline_pull[k] = 0.0f; + } + __syncwarp(center_mask); + if (edge_lane < C) { + const unsigned int row_mask = + (0xffffffffu >> (32 - C)) << (atom_lane * EdgeLanes); + build_spin3_oc_center_pull_row( + layout, + atom, + edge_lane, + row_mask, + atom_stride, + struct_dim, + spins_soa3, + fp, + projection, + moments, + inline_pull, + mforce_soa3); + } + __syncwarp(center_mask); + if (edge_lane == 0) { + const double scale = 2.0 * static_cast( + fp[atom + atom_stride * (struct_dim + layout.local_s2)]); + for (int d = 0; d < 3; ++d) { + // Other center tiles can already scatter to this atom in this kernel. + atomicAdd(mforce_soa3 + d * atom_stride + atom, + -scale * spins_soa3[d * atom_stride + atom]); + } + } + } + float center_force[3] = {}; + float center_mforce[3] = {}; + float center_virial[AccumulateCenterVirial ? 9 : 1] = {}; +#define NEP_SPIN3_OC_FP_EDGE(index) \ + fp[atom + atom_stride * (struct_dim + (index))] + const int neighbor_count = nn_radial[atom]; + for (int slot = edge_lane; slot < neighbor_count; slot += EdgeLanes) { + const int neighbor = nl_radial[slot * atom_stride + atom]; + if (neighbor < 0 || spin_env_type_active[types[neighbor]] == 0) continue; + float r[3], dist, si[3], sj[3], weights[C], derivatives[C]; + if (!load_spin3_edge_f32( + atom, neighbor, atom_stride, num_types, spin_basis_size, + spin_cutoff, spin_cutoff_pair, box, types, positions_soa3, slot_r12, + r12_plane_size, slot * atom_stride + atom, spins_soa3, + descriptor_coefficients, spin_coefficient_offset, r, dist, si, + sj, weights, derivatives)) continue; + const float si2 = spin3_dot3(si, si); + const float sj2 = spin3_dot3(sj, sj); + const float dot = spin3_dot3(si, sj); + const float longitudinal = spin3_dot3(r, sj); + float axial[3], qrr[5], edge_stf[5]; + spin3_cross3(r, sj, axial); + spin3_oc_stf5_outer(r, r, qrr); + spin3_oc_stf5_outer(r, sj, edge_stf); + float grad_weight[C] = {}; + float grad_r[3] = {}, grad_si[3] = {}, grad_sj[3] = {}; + float grad_q[5] = {}; + float grad_dot = 0.0f; + float grad_longitudinal = 0.0f; + for (int c = 0; c < C; ++c) { + const int base = spin3_oc_channel_offset(c); + const float w = weights[c]; + const float a_sj2 = + NEP_SPIN3_OC_FP_EDGE(layout.edge_l0_neighbor_s2 + c); + grad_weight[c] += a_sj2 * sj2; + for (int d = 0; d < 3; ++d) grad_sj[d] += 2.0f * w * a_sj2 * sj[d]; + if (layout.edge_l0_dot2 >= 0) { + const float a = NEP_SPIN3_OC_FP_EDGE(layout.edge_l0_dot2 + c); + grad_weight[c] += a * dot * dot; + grad_dot += 2.0f * w * a * dot; + } + if (layout.edge_l0_moment_gate >= 0) { + const float a = NEP_SPIN3_OC_FP_EDGE(layout.edge_l0_moment_gate + c); + const float gate = dot * (si2 + sj2); + grad_weight[c] += a * gate; + grad_dot += w * a * (si2 + sj2); + for (int d = 0; d < 3; ++d) { + grad_si[d] += 2.0f * w * a * dot * si[d]; + grad_sj[d] += 2.0f * w * a * dot * sj[d]; + } + } + const float* gm = pull + base + kSpin3OcM; + const float* gp = pull + base + kSpin3OcP; + const float gl = pull[base + kSpin3OcL]; + const float* gx = pull + base + kSpin3OcX; + const float* gt = pull + base + kSpin3OcT; + const float* gq = pull + base + kSpin3OcQ; + const float* gqp = pull + base + kSpin3OcQP; + const float* gdm = pull + base + kSpin3OcDM; + const float* ga1 = layout.angular_l1_moment_offset >= 0 + ? pull + layout.angular_l1_moment_offset + 3 * c + : nullptr; + const float* ga2 = layout.angular_l2_moment_offset >= 0 + ? pull + layout.angular_l2_moment_offset + 5 * c + : nullptr; + grad_weight[c] += spin3_dot3(gm, sj) + spin3_dot3(gp, r) + + gl * longitudinal + spin3_dot3(gx, axial) + + spin3_oc_dotn<5>(gt, edge_stf) + spin3_oc_dotn<5>(gq, qrr) + + dot * spin3_dot3(gdm, sj); + for (int k = 0; k < 5; ++k) { + for (int d = 0; d < 3; ++d) { + grad_weight[c] += gqp[3 * k + d] * qrr[k] * sj[d]; + } + } + for (int d = 0; d < 3; ++d) { + grad_sj[d] += w * gm[d]; + grad_r[d] += w * gp[d]; + if (ga1 != nullptr) { + grad_weight[c] += ga1[d] * dot * r[d]; + grad_dot += w * ga1[d] * r[d]; + grad_r[d] += w * dot * ga1[d]; + } + } + grad_longitudinal += w * gl; + float gx_r[3] = {}, gx_s[3] = {}; + spin3_add_cross_pull(r, sj, gx, gx_r, gx_s); + for (int d = 0; d < 3; ++d) { + grad_r[d] += w * gx_r[d]; + grad_sj[d] += w * gx_s[d]; + } + float gt_r[3] = {}, gt_s[3] = {}; + spin3_oc_add_stf5_outer_pull(r, sj, gt, w, gt_r, gt_s); + for (int d = 0; d < 3; ++d) { + grad_r[d] += gt_r[d]; + grad_sj[d] += gt_s[d]; + } + for (int k = 0; k < 5; ++k) { + grad_q[k] += w * gq[k]; + if (ga2 != nullptr) { + grad_weight[c] += ga2[k] * dot * qrr[k]; + grad_dot += w * ga2[k] * qrr[k]; + grad_q[k] += w * dot * ga2[k]; + } + for (int d = 0; d < 3; ++d) { + grad_q[k] += w * gqp[3 * k + d] * sj[d]; + grad_sj[d] += w * gqp[3 * k + d] * qrr[k]; + } + } + const float dm_contract = spin3_dot3(gdm, sj); + grad_dot += w * dm_contract; + for (int d = 0; d < 3; ++d) grad_sj[d] += w * dot * gdm[d]; + } + if (layout.correlation_same_edge >= 0) { + const int same_offset = spin3_oc_same_offset(C); + const float dot2 = dot * dot; + for (int left = 0; left < C; ++left) { + for (int right = left; right < C; ++right) { + const float a = pull[same_offset + + spin3_oc_pair_index(C, left, right)]; + if (left == right) { + grad_weight[left] += 2.0f * a * weights[left] * dot2; + } else { + grad_weight[left] += a * weights[right] * dot2; + grad_weight[right] += a * weights[left] * dot2; + } + grad_dot += 2.0f * a * weights[left] * weights[right] * dot; + } + } + } + float qr_left[3] = {}, qr_right[3] = {}; + spin3_oc_add_stf5_outer_pull(r, r, grad_q, 1.0f, qr_left, qr_right); + for (int d = 0; d < 3; ++d) { + grad_r[d] += qr_left[d] + qr_right[d] + grad_longitudinal * sj[d]; + grad_sj[d] += grad_longitudinal * r[d]; + grad_si[d] += grad_dot * sj[d]; + grad_sj[d] += grad_dot * si[d]; + } + float grad_dist = 0.0f; + for (int c = 0; c < C; ++c) grad_dist += grad_weight[c] * derivatives[c]; + const float dot_r = spin3_dot3(grad_r, r); + float grad_rij[3]; + for (int d = 0; d < 3; ++d) { + grad_rij[d] = grad_dist * r[d] + (grad_r[d] - dot_r * r[d]) / dist; + center_force[d] += grad_rij[d]; + center_mforce[d] -= grad_si[d]; + atomicAdd(force_soa3 + d * atom_stride + neighbor, + -static_cast(grad_rij[d])); + atomicAdd(mforce_soa3 + d * atom_stride + neighbor, + -static_cast(grad_sj[d])); + } + if (AccumulateSpinTransfer) { + atomic_add_spin_transfer_float( + atom_stride, neighbor, r[0] * dist, r[1] * dist, r[2] * dist, + grad_sj, spin_transfer_soa9); + } + if (VirialMode == SpinVirialMode::neighbor_owned) { + atomic_add_per_atom_virial_double( + atom_stride, neighbor, r[0] * dist, r[1] * dist, r[2] * dist, + grad_rij[0], grad_rij[1], grad_rij[2], virial_soa9); + } else if ( + VirialMode == SpinVirialMode::center_and_neighbor_float_sink) { + atomic_add_per_atom_virial_float( + atom_stride, neighbor, r[0] * dist, r[1] * dist, r[2] * dist, + grad_rij[0], grad_rij[1], grad_rij[2], virial_float_soa9); + } + if (AccumulateCenterVirial) { + for (int a = 0; a < 3; ++a) { + for (int b = 0; b < 3; ++b) { + center_virial[virial_internal_component(3 * a + b)] -= + r[a] * dist * grad_rij[b]; + } + } + } + } + for (int offset = EdgeLanes / 2; offset > 0; offset >>= 1) { + for (int d = 0; d < 3; ++d) { + center_force[d] += + __shfl_down_sync(center_mask, center_force[d], offset, EdgeLanes); + center_mforce[d] += + __shfl_down_sync(center_mask, center_mforce[d], offset, EdgeLanes); + } + if (AccumulateCenterVirial) { + for (int component = 0; component < 9; ++component) { + center_virial[component] += __shfl_down_sync( + center_mask, center_virial[component], offset, EdgeLanes); + } + } + } + if (edge_lane == 0) { + for (int d = 0; d < 3; ++d) { + atomicAdd(force_soa3 + d * atom_stride + atom, + static_cast(center_force[d])); + atomicAdd(mforce_soa3 + d * atom_stride + atom, + static_cast(center_mforce[d])); + } + if (AccumulateCenterVirial) { + for (int component = 0; component < 9; ++component) { + atomicAdd(virial_soa9 + component * atom_stride + atom, + static_cast(center_virial[component])); + } + } + } +#undef NEP_SPIN3_OC_FP_EDGE +} diff --git a/src/force/nep_spin/nep_spin3_layout.cuh b/src/force/nep_spin/nep_spin3_layout.cuh new file mode 100644 index 000000000..16c61c44e --- /dev/null +++ b/src/force/nep_spin/nep_spin3_layout.cuh @@ -0,0 +1,167 @@ +/* + This file is part of GPUMD. + SPDX-License-Identifier: LGPL-3.0-or-later +*/ + +#pragma once + +// Adapted from NEPAdapters' unified nep4_spin3 O/C CUDA implementation. +__device__ __forceinline__ float spin3_dot3( + const float* left, + const float* right) { + return left[0] * right[0] + left[1] * right[1] + left[2] * right[2]; +} + +__device__ __forceinline__ void spin3_cross3( + const float* left, + const float* right, + float* out) { + out[0] = left[1] * right[2] - left[2] * right[1]; + out[1] = left[2] * right[0] - left[0] * right[2]; + out[2] = left[0] * right[1] - left[1] * right[0]; +} + +__device__ __forceinline__ void spin3_add_cross_pull( + const float* left, + const float* right, + const float* pull, + float* pull_left, + float* pull_right) { + float right_cross_pull[3], pull_cross_left[3]; + spin3_cross3(right, pull, right_cross_pull); + spin3_cross3(pull, left, pull_cross_left); + for (int d = 0; d < 3; ++d) { + pull_left[d] += right_cross_pull[d]; + pull_right[d] += pull_cross_left[d]; + } +} + +// Canonical center state for the unified nep4_spin3 O/C descriptor. +// linear contractions of these moments (W, DW, QS and the edge-anchored +// L11/L22/L112 responses) are reconstructed after the neighbor reduction. +// This keeps the edge traversal and analytical VJP on the minimum closed +// moment set instead of storing several equivalent representations. +enum Spin3OcDensityOffset : int { + kSpin3OcM = 0, + kSpin3OcP = 3, + kSpin3OcL = 6, + kSpin3OcX = 7, + kSpin3OcT = 10, + kSpin3OcQ = 15, + kSpin3OcQP = 20, + kSpin3OcDM = 35, + kSpin3OcDensityStride = 38, +}; + +__device__ __forceinline__ int spin3_oc_channel_offset(int channel) { + return channel * kSpin3OcDensityStride; +} + +__device__ __forceinline__ int spin3_oc_same_offset(int channels) { + return channels * kSpin3OcDensityStride; +} + +__device__ __forceinline__ int spin3_oc_pair_index( + int channels, + int left, + int right) { + return left * channels - left * (left - 1) / 2 + right - left; +} + +__device__ __forceinline__ float spin3_oc_mix( + const float* projection, + int channels, + int leg, + int row, + int source) { + // Torch flatten order for radial_leg_mix[4][C][C] is + // [leg][output row][input/source channel]. + return projection[(leg * channels + row) * channels + source]; +} + +// Shared descriptor and moment indexing for training and MD. +template +Layout make_spin_polynomial_layout( + const int channels, const int l_max, const int order, const int soc) +{ + Layout layout; + layout.channels = channels; + layout.pair_count = channels * (channels + 1) / 2; + layout.moment_count = layout.density_stride * channels + layout.pair_count; + if (order >= 2 && l_max >= 1) { + layout.angular_l1_moment_offset = layout.moment_count; + layout.moment_count += 3 * channels; + } + if (order >= 2 && l_max >= 2) { + layout.angular_l2_moment_offset = layout.moment_count; + layout.moment_count += 5 * channels; + } + int offset = 0; + layout.local_s2 = offset++; + layout.edge_l0_dot = offset; offset += channels; + layout.edge_l0_neighbor_s2 = offset; offset += channels; + if (soc != 0 && l_max >= 2) { + layout.edge_l2_pair = offset; offset += channels; + layout.center_l2_environment = offset; offset += channels; + } + if (order >= 2) { + layout.edge_l0_dot2 = offset; offset += channels; + layout.density_l0_self = offset; offset += channels; + if (l_max >= 1) { + if (soc != 0) { + layout.density_l1_longitudinal_self = offset; offset += channels; + layout.density_l1_axial_self = offset; offset += channels; + layout.density_l1_stf_self = offset; offset += channels; + } else { + layout.density_l1_product_self = offset; offset += channels; + } + } + if (l_max >= 2) { + layout.density_l2_product_self = offset; offset += channels; + } + layout.density_l0_dot_response = offset; offset += channels; + layout.correlation_same_edge = offset; offset += layout.pair_count; + layout.correlation_distinct_neighbor = offset; offset += layout.pair_count; + if (l_max >= 1) { + layout.correlation_distinct_l1 = offset; offset += layout.pair_count; + } + if (l_max >= 2) { + layout.correlation_distinct_l2 = offset; offset += layout.pair_count; + } + if (soc != 0 && l_max >= 1) { + if (channels >= 2) { + layout.coupling_l11_axial = offset; offset += channels; + } + layout.edge_l11_axial = offset; offset += channels; + } + if (soc != 0 && l_max >= 2) { + if (channels >= 2) { + layout.coupling_l22_axial = offset; offset += channels; + } + layout.edge_l22_axial = offset; offset += channels; + } + } + if (order >= 3) { + layout.edge_l0_moment_gate = offset; offset += channels; + if (soc != 0 && l_max >= 1) { + if (channels >= 2) { + layout.coupling_l11_dot_response = offset; offset += channels; + } + layout.coupling_l111_p_m_x = offset; offset += channels; + } + if (soc != 0 && l_max >= 2) { + if (channels >= 2) { + layout.coupling_l22_dot_response = offset; offset += channels; + } + layout.coupling_l111_p_qs_x = offset; offset += channels; + if (channels >= 2) { + layout.coupling_l112_edge_response = offset; offset += channels; + } + } + if (soc != 0 && l_max >= 1 && channels >= 3) { + layout.coupling_l111_bulk = offset; offset += channels; + } + } + layout.descriptor_dim = offset; + return layout; +} diff --git a/src/force/nep_spin/nep_spin_multigpu.cu b/src/force/nep_spin/nep_spin_multigpu.cu new file mode 100644 index 000000000..36df39311 --- /dev/null +++ b/src/force/nep_spin/nep_spin_multigpu.cu @@ -0,0 +1,239 @@ +/* Single-process spatial decomposition for NEP-Spin. LGPL-3.0-or-later. */ +#include "nep_spin_multigpu.cuh" +#include "force/nep_partition.cuh" +#include +#include +#include + +namespace { +// The sorted index map stays on GPU 0. Geometry and spins always travel together, +// including the second (chord-midpoint) force evaluation of SIB. +__global__ void pack_domain(int n, int local, int start, const int* order, + const int* type, const double* position, const double* spin, + int* local_type, double* local_position, double* local_spin) +{ + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i >= local) return; + int id = order[(start + i) % n]; + local_type[i] = type[id]; + for (int d = 0; d < 3; ++d) { + local_position[i + size_t(d) * local] = position[id + size_t(d) * n]; + local_spin[i + size_t(d) * local] = spin[id + size_t(d) * n]; + } +} + +// Ownership may stay fixed while atoms move through slab faces. The 2.5*rc +// halo contains every two-hop environment while each atom moves < 0.2*rc: +// an initial separation can grow to at most 2*rc + 2*(0.2*rc) < 2.5*rc. +__global__ void check_partition_displacement(int n, Box box, double limit_squared, + const double* position, const double* reference, int* changed) +{ + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i >= n) return; + double dx = position[i] - reference[i]; + double dy = position[i + n] - reference[i + n]; + double dz = position[i + 2 * n] - reference[i + 2 * n]; + apply_mic(box, dx, dy, dz); + if (dx * dx + dy * dy + dz * dz >= limit_squared) atomicExch(changed, 1); +} + +__global__ void collect_domain(int n, int count, int first, const int* order, + const double* packed, double* energy, double* force, double* virial, double* mforce) +{ + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i >= count) return; + int id = order[first + i]; + energy[id] += packed[i]; + for (int d = 0; d < 3; ++d) { + force[id + size_t(d) * n] += packed[i + size_t(1 + d) * count]; + mforce[id + size_t(d) * n] += packed[i + size_t(4 + d) * count]; + } + for (int d = 0; d < 9; ++d) + virial[id + size_t(d) * n] += packed[i + size_t(7 + d) * count]; +} + +void transfer(void* dst, int dst_gpu, const void* src, int src_gpu, size_t bytes) +{ + if (!bytes) return; + if (dst_gpu == src_gpu) { + CHECK(gpuMemcpy(dst, src, bytes, gpuMemcpyDeviceToDevice)); + } else { + // The runtime stages through host memory if direct peer transfer is unavailable. +#ifdef USE_HIP + CHECK(hipMemcpyPeer(dst, dst_gpu, src, src_gpu, bytes)); +#else + CHECK(cudaMemcpyPeer(dst, dst_gpu, src, src_gpu, bytes)); +#endif + } +} +} // namespace + +void NEP_Spin_MultiGPU::Domain::resize(int count) +{ + if (type.size() == size_t(count)) return; + type.resize_with_capacity(count); + position.resize_with_capacity(size_t(count) * 3); + spin.resize_with_capacity(size_t(count) * 3); + energy.resize_with_capacity(count); + force.resize_with_capacity(size_t(count) * 3); + mforce.resize_with_capacity(size_t(count) * 3); + virial.resize_with_capacity(size_t(count) * 9); + potential->resize_domain(count); +} + +NEP_Spin_MultiGPU::NEP_Spin_MultiGPU(int devices, const char* model, int atoms, int direction) + : devices_(devices), atoms_(atoms), direction_(direction) +{ + if (devices < 2 || atoms <= 0 || direction < -1 || direction > 2) + PRINT_INPUT_ERROR("Invalid NEP-Spin multi-GPU partition."); + for (int gpu = 0; gpu < devices_; ++gpu) { + CHECK(gpuSetDevice(gpu)); + domains_.emplace_back(new Domain); + domains_.back()->potential.reset(new NEP_Spin(model, 1)); + } + rc = domains_[0]->potential->rc; + CHECK(gpuSetDevice(0)); + CHECK(gpuStreamCreate(&partition_stream_)); + order_.resize(atoms_); + partition_position_.resize(size_t(atoms_) * 3); + partition_changed_.resize(1); + cell_count_.resize(1); + cell_sum_.resize(1); + printf("NEP-Spin: spatial decomposition over %d GPUs; two-cutoff geometry/spin halos.\n", devices_); +} + +NEP_Spin_MultiGPU::~NEP_Spin_MultiGPU() +{ + for (int gpu = 0; gpu < devices_; ++gpu) { + CHECK(gpuSetDevice(gpu)); + domains_[gpu].reset(); + } + CHECK(gpuSetDevice(0)); + CHECK(gpuStreamDestroy(partition_stream_)); +} + +void NEP_Spin_MultiGPU::compute(Box& box, const GPU_Vector& type, + const GPU_Vector& position, const GPU_Vector& spin, + GPU_Vector& energy, GPU_Vector& force, + GPU_Vector& virial, GPU_Vector& mforce) +{ + CHECK(gpuSetDevice(0)); + const int n = type.size(); + if (n != atoms_ || position.size() != size_t(n) * 3 || spin.size() != size_t(n) * 3) + PRINT_INPUT_ERROR("NEP-Spin multi-GPU atom count mismatch."); + if (!(box.pbc_x && box.pbc_y && box.pbc_z)) + PRINT_INPUT_ERROR("NEP_Spin requires periodic boundary conditions in all three directions."); + bool repartition = !partition_valid_ || + !std::equal(box.cpu_h, box.cpu_h + 9, partition_box_); + if (!repartition) { + partition_changed_.fill(0); + const double displacement_limit = 0.2 * rc; + check_partition_displacement<<<(n + 127) / 128, 128>>>(n, box, + displacement_limit * displacement_limit, position.data(), + partition_position_.data(), partition_changed_.data()); + GPU_CHECK_KERNEL + int changed = 0; + partition_changed_.copy_to_host(&changed); + repartition = changed != 0; + } + if (repartition) { + int bins[3]; + const double cell_width = 0.5 * rc; + box.get_num_bins(cell_width, bins); + for (int d = 0; d < 3; ++d) bins[d] = std::max(1, bins[d]); + const long long cells = static_cast(bins[0]) * bins[1] * bins[2]; + if (cells > std::numeric_limits::max()) + PRINT_INPUT_ERROR("NEP-Spin partition cell count exceeds the supported int range."); + if (direction_ < 0) direction_ = std::max_element(bins, bins + 3) - bins; + find_cell_list(partition_stream_, direction_, cell_width, bins, box, n, position, + cell_count_, cell_sum_, order_); +#ifdef USE_HIP + CHECK(hipStreamSynchronize(partition_stream_)); +#else + CHECK(cudaStreamSynchronize(partition_stream_)); +#endif + prefix_.resize(cells + 1); + cell_sum_.copy_to_host(prefix_.data(), cells); + prefix_[cells] = n; + const int longitudinal = bins[direction_]; + const int transverse = cells / longitudinal; + // Four half-cutoff cells span 2*rc; the fifth supplies displacement + // skin plus a rounding margin. If halos overlap, copy each global atom once and retain full PBC. + constexpr int halo = 5; + for (int gpu = 0; gpu < devices_; ++gpu) { + Domain& dom = *domains_[gpu]; + int b0 = static_cast(gpu) * longitudinal / devices_; + int b1 = static_cast(gpu + 1) * longitudinal / devices_; + dom.global_first = prefix_[b0 * transverse]; + dom.owned = prefix_[b1 * transverse] - dom.global_first; + if (!dom.owned) { dom.size = 0; continue; } + if (b1 - b0 + 2 * halo >= longitudinal) { + dom.start = 0; + dom.size = n; + dom.first = dom.global_first; + } else { + int lo = (b0 - halo + longitudinal) % longitudinal; + int hi = (b1 + halo) % longitudinal; + dom.start = prefix_[lo * transverse]; + dom.size = prefix_[hi * transverse] - dom.start; + if (hi < lo) dom.size += n; + dom.first = (dom.global_first - dom.start + n) % n; + } + } + partition_position_.copy_from_device(position.data()); + std::copy(box.cpu_h, box.cpu_h + 9, partition_box_); + partition_valid_ = true; + } + for (int gpu = 0; gpu < devices_; ++gpu) { + Domain& dom = *domains_[gpu]; + if (!dom.owned) continue; + CHECK(gpuSetDevice(gpu)); + dom.resize(dom.size); + CHECK(gpuSetDevice(0)); + packed_type_.resize_with_capacity(dom.size); + packed_position_.resize_with_capacity(size_t(dom.size) * 3); + packed_spin_.resize_with_capacity(size_t(dom.size) * 3); + pack_domain<<<(dom.size + 127) / 128, 128>>>(n, dom.size, dom.start, order_.data(), + type.data(), position.data(), spin.data(), packed_type_.data(), + packed_position_.data(), packed_spin_.data()); + GPU_CHECK_KERNEL + CHECK(gpuDeviceSynchronize()); + transfer(dom.type.data(), gpu, packed_type_.data(), 0, size_t(dom.size) * sizeof(int)); + transfer(dom.position.data(), gpu, packed_position_.data(), 0, size_t(dom.size) * 3 * sizeof(double)); + transfer(dom.spin.data(), gpu, packed_spin_.data(), 0, size_t(dom.size) * 3 * sizeof(double)); + } + std::vector> workers; + for (int gpu = 0; gpu < devices_; ++gpu) { + if (!domains_[gpu]->owned) continue; + workers.emplace_back(std::async(std::launch::async, [&, gpu] { + CHECK(gpuSetDevice(gpu)); + Domain& dom = *domains_[gpu]; + dom.energy.fill(0.0); dom.force.fill(0.0); dom.virial.fill(0.0); dom.mforce.fill(0.0); + if (repartition) dom.potential->invalidate_neighbors(); + Box local_box = box; // Neighbor/box bookkeeping is local to each host worker. + dom.potential->compute(local_box, dom.type, dom.position, dom.spin, + dom.energy, dom.force, dom.virial, dom.mforce); + CHECK(gpuDeviceSynchronize()); + })); + } + for (auto& worker : workers) worker.get(); + CHECK(gpuSetDevice(0)); + for (int gpu = 0; gpu < devices_; ++gpu) { + const Domain& dom = *domains_[gpu]; + if (!dom.owned) continue; + collected_.resize_with_capacity(size_t(dom.owned) * 16); + auto copy_planes = [&](const GPU_Vector& src, int planes, int offset) { + for (int d = 0; d < planes; ++d) + transfer(collected_.data() + size_t(offset + d) * dom.owned, 0, + src.data() + size_t(d) * dom.size + dom.first, gpu, size_t(dom.owned) * sizeof(double)); + }; + copy_planes(dom.energy, 1, 0); copy_planes(dom.force, 3, 1); + copy_planes(dom.mforce, 3, 4); copy_planes(dom.virial, 9, 7); + // Only owner outputs are collected. Every owner's neighbors and their + // descriptors are complete inside 2*rc; ghost output must never be summed. + collect_domain<<<(dom.owned + 127) / 128, 128>>>(n, dom.owned, dom.global_first, + order_.data(), collected_.data(), energy.data(), force.data(), virial.data(), mforce.data()); + GPU_CHECK_KERNEL + CHECK(gpuDeviceSynchronize()); + } +} diff --git a/src/force/nep_spin/nep_spin_multigpu.cuh b/src/force/nep_spin/nep_spin_multigpu.cuh new file mode 100644 index 000000000..f09fbc726 --- /dev/null +++ b/src/force/nep_spin/nep_spin_multigpu.cuh @@ -0,0 +1,36 @@ +/* Single-process spatial decomposition for NEP-Spin. LGPL-3.0-or-later. */ +#pragma once +#include "nep_spin.cuh" +#include + +class NEP_Spin_MultiGPU : public Potential +{ +public: + NEP_Spin_MultiGPU(int devices, const char* model, int atoms, int direction); + ~NEP_Spin_MultiGPU() override; + using Potential::compute; + void compute(Box&, const GPU_Vector&, const GPU_Vector&, + GPU_Vector&, GPU_Vector&, GPU_Vector&) override + { PRINT_INPUT_ERROR("NEP_Spin requires spin inputs."); } + void compute(Box&, const GPU_Vector&, const GPU_Vector&, + const GPU_Vector&, GPU_Vector&, GPU_Vector&, + GPU_Vector&, GPU_Vector&) override; +private: + struct Domain { + std::unique_ptr potential; + GPU_Vector type; + GPU_Vector position, spin, energy, force, virial, mforce; + int start = 0, size = 0, first = 0, owned = 0, global_first = 0; + void resize(int count); + }; + int devices_, atoms_, direction_; + std::vector> domains_; + GPU_Vector cell_count_, cell_sum_, order_, packed_type_; + GPU_Vector packed_position_, packed_spin_, collected_; + std::vector prefix_; + GPU_Vector partition_position_; + GPU_Vector partition_changed_; + double partition_box_[9] = {}; + bool partition_valid_ = false; + gpuStream_t partition_stream_ = nullptr; +}; diff --git a/src/force/nep_spin/nep_spin_small_box.cuh b/src/force/nep_spin/nep_spin_small_box.cuh new file mode 100644 index 000000000..dd9fd4399 --- /dev/null +++ b/src/force/nep_spin/nep_spin_small_box.cuh @@ -0,0 +1,415 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once + +#include "force/nep_small_box.cuh" + +// Spin retains double displacement and force accumulation in small periodic cells. +// Ordinary NEP uses its unchanged small-box kernels. +namespace nep_spin_small_box { +template +static __device__ __forceinline__ void accumulate_one_angular_channel_in_double( + const int n, + const int n_max_angular_plus_1, + const double d12inv, + const double fn, + const double fnp, + const float* Fp, + const float* sum_fxyz, + const double* r12unit, + double* f12) +{ + double s[2 * L + 1]; + double contribution[3] = {0.0, 0.0, 0.0}; + calculate_s_one(n, n_max_angular_plus_1, Fp, sum_fxyz, s); + accumulate_f12_one(d12inv, fn, fnp, s, r12unit, contribution); + for (int d = 0; d < 3; ++d) { + f12[d] += static_cast(contribution[d]); + } +} +static __device__ __forceinline__ void find_fn_and_fnp_in_double( + const int n_max, + const double rc, + const double distance, + double* fn, + double* fnp) +{ + const double rcinv = 1.0 / rc; + const double scaled = distance * rcinv; + const double fc = + distance < rc ? 0.5 * cos(3.14159265358979323846 * scaled) + 0.5 : 0.0; + const double fcp = + distance < rc + ? -1.57079632679489661923 * sin(3.14159265358979323846 * scaled) * rcinv + : 0.0; + const double x = 2.0 * (scaled - 1.0) * (scaled - 1.0) - 1.0; + fn[0] = fc; + fnp[0] = fcp; + fn[1] = (x + 1.0) * 0.5 * fc; + fnp[1] = + 2.0 * (scaled - 1.0) * rcinv * fc + (x + 1.0) * 0.5 * fcp; + double u0 = 1.0; + double u1 = 2.0 * x; + double t0 = 1.0; + double t1 = x; + for (int m = 2; m <= n_max; ++m) { + const double t2 = 2.0 * x * t1 - t0; + t0 = t1; + t1 = t2; + const double derivative_chebyshev = m * u1; + const double u2 = 2.0 * x * u1 - u0; + u0 = u1; + u1 = u2; + const double basis = (t2 + 1.0) * 0.5; + fnp[m] = + derivative_chebyshev * 2.0 * (scaled - 1.0) * rcinv * fc + basis * fcp; + fn[m] = basis * fc; + } +} +static __device__ __forceinline__ void accumulate_f12_small_box_in_double( + const int L_max, + const int has_q_222, + const int has_q_1111, + const int has_q_112, + const int has_q_123, + const int has_q_233, + const int has_q_134, + const int num_L, + const int n, + const int n_max_angular_plus_1, + const double d12, + const double* r12, + const double fn, + const double fnp, + const float* Fp, + const float* sum_fxyz, + double* f12) +{ + const bool only_supported_extra = + !has_q_1111 && !has_q_112 && !has_q_123 && !has_q_233 && !has_q_134 && + num_L == L_max + static_cast(has_q_222); + if (!only_supported_extra) { + float fallback[3] = {0.0f}; + const float d12_float = static_cast(d12); + const float r12_float[3] = { + static_cast(r12[0]), + static_cast(r12[1]), + static_cast(r12[2])}; + accumulate_f12( + L_max, + has_q_222, + has_q_1111, + has_q_112, + has_q_123, + has_q_233, + has_q_134, + num_L, + n, + n_max_angular_plus_1, + d12_float, + r12_float, + static_cast(fn), + static_cast(fnp), + Fp, + sum_fxyz, + fallback); + for (int d = 0; d < 3; ++d) { + f12[d] += static_cast(fallback[d]); + } + return; + } + const double d12inv = 1.0 / d12; + const double r12unit[3] = { + r12[0] * d12inv, r12[1] * d12inv, r12[2] * d12inv}; + if (L_max >= 1) + accumulate_one_angular_channel_in_double<1>( + n, n_max_angular_plus_1, d12inv, fn, fnp, Fp, sum_fxyz, r12unit, f12); + if (L_max >= 2) + accumulate_one_angular_channel_in_double<2>( + n, n_max_angular_plus_1, d12inv, fn, fnp, Fp, sum_fxyz, r12unit, f12); + if (L_max >= 3) + accumulate_one_angular_channel_in_double<3>( + n, n_max_angular_plus_1, d12inv, fn, fnp, Fp, sum_fxyz, r12unit, f12); + if (L_max >= 4) + accumulate_one_angular_channel_in_double<4>( + n, n_max_angular_plus_1, d12inv, fn, fnp, Fp, sum_fxyz, r12unit, f12); + if (L_max >= 5) + accumulate_one_angular_channel_in_double<5>( + n, n_max_angular_plus_1, d12inv, fn, fnp, Fp, sum_fxyz, r12unit, f12); + if (L_max >= 6) + accumulate_one_angular_channel_in_double<6>( + n, n_max_angular_plus_1, d12inv, fn, fnp, Fp, sum_fxyz, r12unit, f12); + if (L_max >= 7) + accumulate_one_angular_channel_in_double<7>( + n, n_max_angular_plus_1, d12inv, fn, fnp, Fp, sum_fxyz, r12unit, f12); + if (L_max >= 8) + accumulate_one_angular_channel_in_double<8>( + n, n_max_angular_plus_1, d12inv, fn, fnp, Fp, sum_fxyz, r12unit, f12); + if (has_q_222) { + double radial_fn = fn * d12inv; + double radial_fnp = fnp * d12inv - fn * d12inv * d12inv; + const double fn2 = radial_fn * d12inv; + const double fnp2 = + radial_fnp * d12inv - radial_fn * d12inv * d12inv; + const double s2[5] = { + sum_fxyz[n * NUM_OF_ABC + 3], + sum_fxyz[n * NUM_OF_ABC + 4], + sum_fxyz[n * NUM_OF_ABC + 5], + sum_fxyz[n * NUM_OF_ABC + 6], + sum_fxyz[n * NUM_OF_ABC + 7]}; + double contribution[3] = {0.0, 0.0, 0.0}; + get_f12_4body( + d12, + d12inv, + fn2, + fnp2, + static_cast(Fp[L_max * n_max_angular_plus_1 + n]), + s2, + r12, + contribution); + for (int d = 0; d < 3; ++d) { + f12[d] += static_cast(contribution[d]); + } + } +} +static __global__ void find_force_radial_small_box( + NEP::ParaMB paramb, + NEP::ANN annmb, + const int N, + const int N1, + const int N2, + const int* g_NN, + const int* g_NL, + const int* __restrict__ g_type, + const double* __restrict__ g_x12, + const double* __restrict__ g_y12, + const double* __restrict__ g_z12, + const float* __restrict__ g_Fp, + double* g_fx, + double* g_fy, + double* g_fz, + double* g_virial) +{ + int n1 = blockIdx.x * blockDim.x + threadIdx.x + N1; + if (n1 < N2) { + int t1 = g_type[n1]; + for (int i1 = 0; i1 < g_NN[n1]; ++i1) { + int index = i1 * N + n1; + int n2 = g_NL[index]; + int t2 = g_type[n2]; + double r12_double[3] = { + static_cast(g_x12[index]), + static_cast(g_y12[index]), + static_cast(g_z12[index])}; + const double d12_double = sqrt( + r12_double[0] * r12_double[0] + + r12_double[1] * r12_double[1] + + r12_double[2] * r12_double[2]); + double f12_double[3] = {0.0, 0.0, 0.0}; + float rc = (paramb.rc_radial[t1] + paramb.rc_radial[t2]) * 0.5f; + double fn12_double[MAX_NUM_N] = {0.0}; + double fnp12_double[MAX_NUM_N] = {0.0}; + find_fn_and_fnp_in_double( + paramb.basis_size_radial, + static_cast(rc), + d12_double, + fn12_double, + fnp12_double); + for (int n = 0; n <= paramb.n_max_radial; ++n) { + double gnp12_double = 0.0; + for (int k = 0; k <= paramb.basis_size_radial; ++k) { + int c_index = get_c_index( + t1 * paramb.num_types + t2, n, k, paramb.n_max_radial, paramb.basis_size_radial); + gnp12_double += + fnp12_double[k] * static_cast(annmb.c_type_pair[c_index]); + } + const double tmp12_double = + static_cast(g_Fp[n1 + n * N]) * gnp12_double / d12_double; + for (int d = 0; d < 3; ++d) { + f12_double[d] += tmp12_double * r12_double[d]; + } + } + double s_sxx = 0.0; + double s_sxy = 0.0; + double s_sxz = 0.0; + double s_syx = 0.0; + double s_syy = 0.0; + double s_syz = 0.0; + double s_szx = 0.0; + double s_szy = 0.0; + double s_szz = 0.0; + s_sxx -= r12_double[0] * f12_double[0]; + s_syy -= r12_double[1] * f12_double[1]; + s_szz -= r12_double[2] * f12_double[2]; + s_sxy -= r12_double[0] * f12_double[1]; + s_sxz -= r12_double[0] * f12_double[2]; + s_syz -= r12_double[1] * f12_double[2]; + s_syx -= r12_double[1] * f12_double[0]; + s_szx -= r12_double[2] * f12_double[0]; + s_szy -= r12_double[2] * f12_double[1]; + atomicAdd(&g_fx[n1], f12_double[0]); + atomicAdd(&g_fy[n1], f12_double[1]); + atomicAdd(&g_fz[n1], f12_double[2]); + atomicAdd(&g_fx[n2], -f12_double[0]); + atomicAdd(&g_fy[n2], -f12_double[1]); + atomicAdd(&g_fz[n2], -f12_double[2]); + // save virial + // xx xy xz 0 3 4 + // yx yy yz 6 1 5 + // zx zy zz 7 8 2 + atomicAdd(&g_virial[n2 + 0 * N], s_sxx); + atomicAdd(&g_virial[n2 + 1 * N], s_syy); + atomicAdd(&g_virial[n2 + 2 * N], s_szz); + atomicAdd(&g_virial[n2 + 3 * N], s_sxy); + atomicAdd(&g_virial[n2 + 4 * N], s_sxz); + atomicAdd(&g_virial[n2 + 5 * N], s_syz); + atomicAdd(&g_virial[n2 + 6 * N], s_syx); + atomicAdd(&g_virial[n2 + 7 * N], s_szx); + atomicAdd(&g_virial[n2 + 8 * N], s_szy); + } + } +} +static __global__ void find_force_angular_small_box( + NEP::ParaMB paramb, + NEP::ANN annmb, + const int N, + const int N1, + const int N2, + const int* g_NN_angular, + const int* g_NL_angular, + const int* __restrict__ g_type, + const double* __restrict__ g_x12, + const double* __restrict__ g_y12, + const double* __restrict__ g_z12, + const float* __restrict__ g_Fp, + const float* __restrict__ g_sum_fxyz, + double* g_fx, + double* g_fy, + double* g_fz, + double* g_virial) +{ + int n1 = blockIdx.x * blockDim.x + threadIdx.x + N1; + if (n1 < N2) { + float Fp[MAX_DIM_ANGULAR] = {0.0f}; + float sum_fxyz[NUM_OF_ABC * MAX_NUM_N]; + for (int d = 0; d < paramb.dim_angular; ++d) { + Fp[d] = g_Fp[(paramb.n_max_radial + 1 + d) * N + n1]; + } + for (int n = 0; n < paramb.n_max_angular + 1; ++n) { + for (int abc = 0; abc < (paramb.L_max + 1) * (paramb.L_max + 1) - 1; ++abc) { + sum_fxyz[n * NUM_OF_ABC + abc] = + g_sum_fxyz[(n * ((paramb.L_max + 1) * (paramb.L_max + 1) - 1) + abc) * N + n1]; + } + } + int t1 = g_type[n1]; + for (int i1 = 0; i1 < g_NN_angular[n1]; ++i1) { + int index = i1 * N + n1; + int n2 = g_NL_angular[n1 + N * i1]; + double r12_double[3] = { + static_cast(g_x12[index]), + static_cast(g_y12[index]), + static_cast(g_z12[index])}; + double f12_double[3] = {0.0, 0.0, 0.0}; + int t2 = g_type[n2]; + float rc = (paramb.rc_angular[t1] + paramb.rc_angular[t2]) * 0.5f; + const double d12_double = sqrt( + r12_double[0] * r12_double[0] + + r12_double[1] * r12_double[1] + + r12_double[2] * r12_double[2]); + double fn12_double[MAX_NUM_N] = {0.0}; + double fnp12_double[MAX_NUM_N] = {0.0}; + find_fn_and_fnp_in_double( + paramb.basis_size_angular, + static_cast(rc), + d12_double, + fn12_double, + fnp12_double); + for (int n = 0; n <= paramb.n_max_angular; ++n) { + double gn12_double = 0.0; + double gnp12_double = 0.0; + for (int k = 0; k <= paramb.basis_size_angular; ++k) { + int c_index = get_c_index( + t1 * paramb.num_types + t2, + n, + k, + paramb.n_max_angular, + paramb.basis_size_angular, + paramb.num_c_radial); + gn12_double += + fn12_double[k] * static_cast(annmb.c_type_pair[c_index]); + gnp12_double += + fnp12_double[k] * static_cast(annmb.c_type_pair[c_index]); + } + accumulate_f12_small_box_in_double( + paramb.L_max, + paramb.has_q_222, + paramb.has_q_1111, + paramb.has_q_112, + paramb.has_q_123, + paramb.has_q_233, + paramb.has_q_134, + paramb.num_L, + n, + paramb.n_max_angular + 1, + d12_double, + r12_double, + gn12_double, + gnp12_double, + Fp, + sum_fxyz, + f12_double); + } + double s_sxx = 0.0; + double s_sxy = 0.0; + double s_sxz = 0.0; + double s_syx = 0.0; + double s_syy = 0.0; + double s_syz = 0.0; + double s_szx = 0.0; + double s_szy = 0.0; + double s_szz = 0.0; + s_sxx -= r12_double[0] * f12_double[0]; + s_syy -= r12_double[1] * f12_double[1]; + s_szz -= r12_double[2] * f12_double[2]; + s_sxy -= r12_double[0] * f12_double[1]; + s_sxz -= r12_double[0] * f12_double[2]; + s_syz -= r12_double[1] * f12_double[2]; + s_syx -= r12_double[1] * f12_double[0]; + s_szx -= r12_double[2] * f12_double[0]; + s_szy -= r12_double[2] * f12_double[1]; + atomicAdd(&g_fx[n1], f12_double[0]); + atomicAdd(&g_fy[n1], f12_double[1]); + atomicAdd(&g_fz[n1], f12_double[2]); + atomicAdd(&g_fx[n2], -f12_double[0]); + atomicAdd(&g_fy[n2], -f12_double[1]); + atomicAdd(&g_fz[n2], -f12_double[2]); + // save virial + // xx xy xz 0 3 4 + // yx yy yz 6 1 5 + // zx zy zz 7 8 2 + atomicAdd(&g_virial[n2 + 0 * N], s_sxx); + atomicAdd(&g_virial[n2 + 1 * N], s_syy); + atomicAdd(&g_virial[n2 + 2 * N], s_szz); + atomicAdd(&g_virial[n2 + 3 * N], s_sxy); + atomicAdd(&g_virial[n2 + 4 * N], s_sxz); + atomicAdd(&g_virial[n2 + 5 * N], s_syz); + atomicAdd(&g_virial[n2 + 6 * N], s_syx); + atomicAdd(&g_virial[n2 + 7 * N], s_szx); + atomicAdd(&g_virial[n2 + 8 * N], s_szy); + } + } +} +} // namespace nep_spin_small_box diff --git a/src/force/potential.cu b/src/force/potential.cu index 7e7fe9342..bf7b7019b 100644 --- a/src/force/potential.cu +++ b/src/force/potential.cu @@ -32,6 +32,19 @@ Potential::~Potential(void) // nothing } +void Potential::compute( + Box&, + const GPU_Vector&, + const GPU_Vector&, + const GPU_Vector&, + GPU_Vector&, + GPU_Vector&, + GPU_Vector&, + GPU_Vector&) +{ + PRINT_INPUT_ERROR("This potential does not support spin."); +} + static __global__ void gpu_find_force_many_body( const int number_of_particles, const int N1, diff --git a/src/force/potential.cuh b/src/force/potential.cuh index 2593dab07..ab9844f8a 100644 --- a/src/force/potential.cuh +++ b/src/force/potential.cuh @@ -38,6 +38,16 @@ public: GPU_Vector& force, GPU_Vector& virial) = 0; + virtual void compute( + Box& box, + const GPU_Vector& type, + const GPU_Vector& position, + const GPU_Vector& spin, + GPU_Vector& potential, + GPU_Vector& force, + GPU_Vector& virial, + GPU_Vector& mforce); + virtual void compute( const float /* temperature */, Box& /* box */, diff --git a/src/integrate/ensemble_fixed_lattice.cu b/src/integrate/ensemble_fixed_lattice.cu new file mode 100644 index 000000000..09cdc85b0 --- /dev/null +++ b/src/integrate/ensemble_fixed_lattice.cu @@ -0,0 +1,48 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#include "ensemble_fixed_lattice.cuh" + +Ensemble_Fixed_Lattice::Ensemble_Fixed_Lattice(EnsembleType type) { this->type = type; } + +void Ensemble_Fixed_Lattice::compute1( + const double, + const int, + const int, + const std::vector&, + Box&, + Atom&, + GPU_Vector&) +{ +} + +void Ensemble_Fixed_Lattice::compute2( + const double, + const int, + const int, + const std::vector& group, + Box& box, + Atom& atom, + GPU_Vector& thermo, Force& force) +{ + find_thermo( + box.get_volume(), + group, + atom.mass, + atom.potential_per_atom, + atom.velocity_per_atom, + atom.virial_per_atom, + thermo); +} diff --git a/src/integrate/ensemble_fixed_lattice.cuh b/src/integrate/ensemble_fixed_lattice.cuh new file mode 100644 index 000000000..41455d6ad --- /dev/null +++ b/src/integrate/ensemble_fixed_lattice.cuh @@ -0,0 +1,42 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once + +#include "ensemble.cuh" + +class Ensemble_Fixed_Lattice : public Ensemble +{ +public: + explicit Ensemble_Fixed_Lattice(EnsembleType type); + + void compute1( + const double time_step, + const int step, + const int number_of_steps, + const std::vector& group, + Box& box, + Atom& atom, + GPU_Vector& thermo) override; + + void compute2( + const double time_step, + const int step, + const int number_of_steps, + const std::vector& group, + Box& box, + Atom& atom, + GPU_Vector& thermo, Force& force) override; +}; diff --git a/src/integrate/integrate.cu b/src/integrate/integrate.cu index 0268907ff..99541fa60 100644 --- a/src/integrate/integrate.cu +++ b/src/integrate/integrate.cu @@ -25,6 +25,7 @@ The driver class for the various integrators. #include "ensemble_msst.cuh" #include "ensemble_mttk.cuh" #include "ensemble_nhc.cuh" +#include "spin/lattice.cuh" #include "ensemble_nphug.cuh" #include "ensemble_npt_qtb.cuh" #include "ensemble_npt_scr.cuh" @@ -42,6 +43,7 @@ The driver class for the various integrators. #include "ensemble_wall_mirror.cuh" #include "ensemble_wall_piston.cuh" #include "integrate.cuh" +#include "spin_tspin.cuh" #include "model/atom.cuh" #include "utilities/common.cuh" #include "utilities/gpu_macro.cuh" @@ -94,6 +96,45 @@ double Integrate::get_temperature() const return temperature; } +bool Integrate::has_spin_mttk_driver() const +{ + return type == EnsembleType::MTTK && (use_spin_tspin); +} + +bool Integrate::has_spin_nhc_driver() const +{ + // lattice off uses Ensemble_Fixed_Lattice despite the NVT_NHC type tag. + return type == EnsembleType::NVT_NHC && spin_lattice_enabled && + (use_spin_tspin); +} + +std::string Integrate::spin_mttk_restart_state() const +{ + return has_spin_mttk_driver() ? static_cast(ensemble_.get())->restart_state() : ""; +} + +std::string Integrate::spin_nhc_restart_state() const +{ + return has_spin_nhc_driver() ? static_cast(ensemble_.get())->restart_state() : ""; +} + +double Integrate::spin_protocol_fraction(int step, int number_of_steps) const +{ + if (has_spin_mttk_driver()) + return static_cast(ensemble_.get())->protocol_fraction(step, number_of_steps); + if (has_spin_nhc_driver()) + return static_cast(ensemble_.get())->protocol_fraction(step, number_of_steps); + return double(step) / number_of_steps; +} + +void Integrate::restore_spin_time(const Atom& atom, double& global_time) const +{ + if (use_spin_tspin) { + if (!atom.spin_lattice_restart.mttk.empty()) global_time = atom.spin_lattice_restart.mttk_time; + if (!atom.spin_lattice_restart.nhc.empty()) global_time = atom.spin_lattice_restart.nhc_time; + } +} + double Integrate::get_target_temperature_of_step() const { return ensemble_->temperature; } int Integrate::get_number_of_atoms_for_temperature( @@ -197,7 +238,27 @@ void Integrate::initialize( ensemble.deform_xy = deform_xy; ensemble.deform_xz = deform_xz; ensemble.deform_yz = deform_yz; + if (!has_spin_mttk_driver() && !atom.spin_lattice_restart.mttk.empty()) { + printf("Discarding MTTK restart state for a different ensemble.\n"); + atom.spin_lattice_restart.mttk.clear(); + } + if (!has_spin_nhc_driver() && !atom.spin_lattice_restart.nhc.empty()) { + printf("Discarding NVT NHC restart state for a different ensemble or lattice off.\n"); + atom.spin_lattice_restart.nhc.clear(); + } ensemble.initialize_run(time_step, atom, box, group); + spin_integrator.reset(); + if (use_spin_tspin) { + spin_integrator.reset(new Spin_TSPIN( + temperature1, + temperature_coupling, + time_step, + spin_mass_factor_by_type, + spin_seed, + atom)); + spin_integrator->temperature = temperature; + } + } void Integrate::finalize(const Atom& atom, const Box& box) @@ -206,6 +267,8 @@ void Integrate::finalize(const Atom& atom, const Box& box) ensemble_->finalize_run(atom, box); } ensemble_.reset(); + spin_integrator.reset(); + use_spin_tspin = false; type = EnsembleType::UNKNOWN; fixed_group = -1; // no group has an index of -1 move_group = -1; @@ -229,22 +292,29 @@ void Integrate::compute1( GPU_Vector& thermo) { Ensemble& ensemble = *ensemble_; - const double step_over_number_of_steps = double(step) / number_of_steps; + if (step == 0 && has_spin_mttk_driver()) { + ensemble.initialize_before_first_step( + time_step, number_of_steps, group, box, atom, thermo); + } + const double step_over_number_of_steps = spin_protocol_fraction(step, number_of_steps); if ( type == EnsembleType::NVE || type == EnsembleType::RPMD || type == EnsembleType::TRPMD) { ensemble.temperature = temperature2; - } else if (is_standard_nvt(type) || is_standard_npt(type) || type == EnsembleType::PIMD) { + } else if (is_standard_nvt(type) || is_standard_npt(type) || type == EnsembleType::PIMD || + (type == EnsembleType::MTTK && (use_spin_tspin))) { ensemble.temperature = temperature1 + (temperature2 - temperature1) * step_over_number_of_steps; } - if (step == 0) { + if (step == 0 && !has_spin_mttk_driver()) { ensemble.initialize_before_first_step( time_step, number_of_steps, group, box, atom, thermo); } + if (spin_integrator) spin_integrator->temperature = ensemble.temperature; ensemble.compute1(time_step, step, number_of_steps, group, box, atom, thermo); + if (spin_integrator) spin_integrator->compute1(time_step, atom); } void Integrate::compute2( @@ -258,17 +328,20 @@ void Integrate::compute2( Force& force) { Ensemble& ensemble = *ensemble_; - const double step_over_number_of_steps = double(step) / number_of_steps; + const double step_over_number_of_steps = spin_protocol_fraction(step, number_of_steps); if ( type == EnsembleType::NVE || type == EnsembleType::RPMD || type == EnsembleType::TRPMD) { ensemble.temperature = temperature2; - } else if (is_standard_nvt(type) || is_standard_npt(type) || type == EnsembleType::PIMD) { + } else if (is_standard_nvt(type) || is_standard_npt(type) || type == EnsembleType::PIMD || + (type == EnsembleType::MTTK && (use_spin_tspin))) { ensemble.temperature = temperature1 + (temperature2 - temperature1) * step_over_number_of_steps; } + if (spin_integrator) spin_integrator->temperature = ensemble.temperature; ensemble.compute2(time_step, step, number_of_steps, group, box, atom, thermo, force); + if (spin_integrator) spin_integrator->compute2(time_step, atom); // A barostat can change the box in compute2. Force::compute refreshes the float copy of the box // only at the next step, and the measurements at the end of this step read it. box.set_is_orthogonal(); @@ -288,6 +361,12 @@ void Integrate::parse_ensemble( PRINT_INPUT_ERROR("Only one ensemble can be specified before each run."); } + use_spin_tspin = tokens[1] == "nvt_tspin" || tokens[1] == "npt_tspin"; + if (use_spin_tspin) { + parse_spin_ensemble(tokens, atom, box, group); + return; + } + // 1. Determine the integration method if (tokens[1] == "nve") { ensemble_ = std::make_unique(tokens); diff --git a/src/integrate/integrate.cuh b/src/integrate/integrate.cuh index 55c67b489..43762b364 100644 --- a/src/integrate/integrate.cuh +++ b/src/integrate/integrate.cuh @@ -16,6 +16,7 @@ #pragma once #include "ensemble.cuh" +#include "spin_integrator.cuh" #include "model/box.cuh" #include "model/group.cuh" #include @@ -50,8 +51,21 @@ private: // PIMD int number_of_beads; +private: + std::unique_ptr spin_integrator; + void parse_spin_ensemble(const std::vector&, const Atom&, const Box&, const std::vector&); + double temperature_coupling = 100.0; + std::vector spin_mass_factor_by_type; + int spin_seed = 12345; + bool has_spin_nhc_driver() const; + bool has_spin_mttk_driver() const; + double spin_protocol_fraction(int step, int number_of_steps) const; public: + bool use_spin_tspin = false, spin_lattice_enabled = true; bool has_ensemble() const; + void restore_spin_time(const Atom& atom, double& global_time) const; + std::string spin_mttk_restart_state() const; + std::string spin_nhc_restart_state() const; EnsembleType get_type() const; int get_fixed_group() const; int get_move_group() const; diff --git a/src/integrate/langevin_utilities.cuh b/src/integrate/langevin_utilities.cuh index 2bdcf4df1..32cd0bbc2 100644 --- a/src/integrate/langevin_utilities.cuh +++ b/src/integrate/langevin_utilities.cuh @@ -19,6 +19,7 @@ Some CUDA kernels for Langevin thermostats. #pragma once #include "model/box.cuh" +#include "utilities/fractional_region.cuh" #include "utilities/gpu_macro.cuh" #define CURAND_NORMAL(a) gpurand_normal_double(a) @@ -149,34 +150,6 @@ static __global__ void gpu_langevin( } } -static __device__ void get_fractional_position( - const Box& box, - const double x, - const double y, - const double z, - double& sa, - double& sb, - double& sc) -{ - sa = box.cpu_h[9] * x + box.cpu_h[10] * y + box.cpu_h[11] * z; - sb = box.cpu_h[12] * x + box.cpu_h[13] * y + box.cpu_h[14] * z; - sc = box.cpu_h[15] * x + box.cpu_h[16] * y + box.cpu_h[17] * z; -} - -static __device__ bool is_in_region( - const double sa, - const double sb, - const double sc, - const double amin, - const double amax, - const double bmin, - const double bmax, - const double cmin, - const double cmax) -{ - return sa >= amin && sa < amax && sb >= bmin && sb < bmax && sc >= cmin && sc < cmax; -} - // local Langevin thermostatting based on fractional-coordinate regions static __global__ void gpu_langevin_region( gpurandState* g_state, diff --git a/src/integrate/spin/input.cu b/src/integrate/spin/input.cu new file mode 100644 index 000000000..4dc39aabf --- /dev/null +++ b/src/integrate/spin/input.cu @@ -0,0 +1,203 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#include "integrate/integrate.cuh" +#include "integrate/ensemble_fixed_lattice.cuh" +#include "lattice.cuh" +#include "model/atom.cuh" +#include "utilities/common.cuh" +#include "utilities/read_file.cuh" +#include +#include +#include +#include + +namespace +{ +bool is_tspin_option(const char* value) +{ + return strcmp(value, "lattice") == 0 || + strcmp(value, "mass_factor") == 0 || strcmp(value, "seed") == 0; +} + + + +void print_spin_mass_factors( + const Atom& atom, + const std::vector& mass_factor_by_type) +{ + for (std::size_t type = 0; type < mass_factor_by_type.size(); ++type) { + for (int atom_index = 0; atom_index < atom.number_of_atoms; ++atom_index) { + if (atom.cpu_type[atom_index] == static_cast(type)) { + printf( + " spin mass factor for %s is %g.\n", + atom.cpu_atom_symbol[atom_index].c_str(), + mass_factor_by_type[type]); + break; + } + } + } +} +} // namespace + +void Integrate::parse_spin_ensemble( + const std::vector& tokens, const Atom& atom, + const Box& box, const std::vector& group) +{ + const int num_param = tokens.size(); + std::vector args; + for (const auto& token : tokens) args.push_back(token.c_str()); + const char** param = args.data(); + spin_lattice_enabled = true; + spin_mass_factor_by_type.assign(atom.cpu_type_size.size(), 1.0); + spin_seed = 12345; + const bool npt = tokens[1] == "npt_tspin"; + int spin_option_start = 5; + if (npt) { + spin_option_start = num_param; + for (int i = 2; i < num_param; ++i) { + if (is_tspin_option(param[i])) { + spin_option_start = i; + break; + } + } + } + if (num_param < spin_option_start) PRINT_INPUT_ERROR("Missing spin ensemble parameters."); + if (use_spin_tspin) { + bool has_lattice = false; + bool has_mass_factor = false; + bool has_seed = false; + int index = spin_option_start; + while (index < num_param) { + if (strcmp(param[index], "lattice") == 0) { + if (index + 1 >= num_param) { + PRINT_INPUT_ERROR("TSPIN lattice requires on or off."); + } + if (strcmp(param[1], "nvt_tspin") != 0) { + PRINT_INPUT_ERROR("TSPIN lattice is only valid for nvt_tspin."); + } + if (has_lattice) { + PRINT_INPUT_ERROR("TSPIN lattice cannot be repeated."); + } + has_lattice = true; + if (strcmp(param[index + 1], "on") == 0) { + spin_lattice_enabled = true; + } else if (strcmp(param[index + 1], "off") == 0) { + spin_lattice_enabled = false; + } else { + PRINT_INPUT_ERROR("TSPIN lattice should be on or off."); + } + index += 2; + } else if (strcmp(param[index], "mass_factor") == 0) { + if (has_mass_factor) { + PRINT_INPUT_ERROR("TSPIN mass_factor cannot be repeated."); + } + has_mass_factor = true; + if (index + 1 >= num_param) { + PRINT_INPUT_ERROR("TSPIN mass_factor requires a value or element-value pairs."); + } + double common_factor = 0.0; + if (is_valid_real(param[index + 1], &common_factor)) { + if (!std::isfinite(common_factor) || common_factor <= 0.0) { + PRINT_INPUT_ERROR("Scalar TSPIN mass_factor should be finite and > 0."); + } + std::fill( + spin_mass_factor_by_type.begin(), + spin_mass_factor_by_type.end(), + common_factor); + index += 2; + } else { + std::vector configured(atom.cpu_type_size.size(), 0); + ++index; + while (index < num_param && !is_tspin_option(param[index])) { + if (index + 1 >= num_param || is_tspin_option(param[index + 1])) { + PRINT_INPUT_ERROR( + "Element-wise TSPIN mass_factor requires element-value pairs."); + } + int type = -1; + for (int atom_index = 0; atom_index < atom.number_of_atoms; ++atom_index) { + if (atom.cpu_atom_symbol[atom_index] == param[index]) { + type = atom.cpu_type[atom_index]; + break; + } + } + if (type < 0) { + PRINT_INPUT_ERROR("Unknown element in TSPIN mass_factor."); + } + if (configured[type] != 0) { + PRINT_INPUT_ERROR("Element in TSPIN mass_factor cannot be repeated."); + } + double factor = 0.0; + if (!is_valid_real(param[index + 1], &factor) || + !std::isfinite(factor) || factor < 0.0) { + PRINT_INPUT_ERROR( + "Element-wise TSPIN mass_factor should be finite and >= 0."); + } + spin_mass_factor_by_type[type] = factor; + configured[type] = 1; + index += 2; + } + for (int atom_index = 0; atom_index < atom.number_of_atoms; ++atom_index) { + if (configured[atom.cpu_type[atom_index]] == 0) { + PRINT_INPUT_ERROR( + "Element-wise TSPIN mass_factor must list every element in model.xyz."); + } + } + } + } else if (strcmp(param[index], "seed") == 0) { + if (index + 1 >= num_param) { + PRINT_INPUT_ERROR("TSPIN seed requires a value."); + } + if (has_seed) { + PRINT_INPUT_ERROR("TSPIN seed cannot be repeated."); + } + has_seed = true; + if (!is_valid_int(param[index + 1], &spin_seed) || spin_seed <= 0) { + PRINT_INPUT_ERROR("TSPIN seed should be a positive integer."); + } + index += 2; + } else { + PRINT_INPUT_ERROR("Unknown TSPIN optional keyword."); + } + } + } + + + + + std::vector lattice(tokens.begin(), tokens.begin() + spin_option_start); + if (npt) { + lattice[1] = "npt_mttk"; + auto mttk = std::make_unique(lattice); + temperature1 = mttk->t_start; + temperature2 = mttk->t_stop; + temperature = temperature1; + temperature_coupling = mttk->get_temperature_period(); + type = EnsembleType::MTTK; + ensemble_ = std::move(mttk); + } else { + lattice[1] = "nvt_nhc"; + auto nhc = std::make_unique(lattice, group); + temperature1 = nhc->get_temperature1(); + temperature2 = nhc->get_temperature2(); + temperature = temperature1; + temperature_coupling = get_double_from_token(tokens[4], __FILE__, __LINE__); + type = EnsembleType::NVT_NHC; + if (spin_lattice_enabled) ensemble_ = std::move(nhc); + else ensemble_ = std::make_unique(type); + } + printf("Integrate spins with TSPIN.\n"); + print_spin_mass_factors(atom, spin_mass_factor_by_type); +} diff --git a/src/integrate/spin/lattice.cu b/src/integrate/spin/lattice.cu new file mode 100644 index 000000000..03799ab85 --- /dev/null +++ b/src/integrate/spin/lattice.cu @@ -0,0 +1,255 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#include "lattice.cuh" +#include "utilities/error.cuh" +#include +#include +#include +#include +#include + +void Spin_Lattice_NHC::initialize_run( + double time_step, Atom& atom, Box& box, const std::vector& group) +{ + Ensemble_NHC::initialize_run(time_step, atom, box, group); + restart_configuration_ = {double(NOSE_HOOVER_CHAIN_LENGTH), double(atom.number_of_atoms), + time_step, get_temperature1(), get_temperature2(), temperature_coupling, + double(fixed_group), double(move_group), double(fixed_grouping_method), double(move_grouping_method)}; + for (int i = 0; i < 3; ++i) restart_configuration_.push_back(move_group >= 0 ? move_velocity[i] : 0.0); + if (!atom.spin_lattice_restart.nhc.empty()) { + restore_restart(atom.spin_lattice_restart.nhc); + atom.spin_lattice_restart.nhc.clear(); + printf("Restored NVT NHC endpoint after %llu steps (protocol length %d).\n", + static_cast(restart_offset_), protocol_steps_); + } +} + +void Spin_Lattice_NHC::compute1(double time_step, int step, int number_of_steps, const std::vector& group, + Box& box, Atom& atom, GPU_Vector& thermo) +{ + if (protocol_steps_ == 0) protocol_steps_ = number_of_steps; + Ensemble_NHC::compute1(time_step, step, number_of_steps, group, box, atom, thermo); +} + +void Spin_Lattice_NHC::compute2(double time_step, int step, int number_of_steps, const std::vector& group, + Box& box, Atom& atom, GPU_Vector& thermo, Force& force) +{ + Ensemble_NHC::compute2(time_step, step, number_of_steps, group, box, atom, thermo, force); + completed_steps_ = restart_offset_ + static_cast(step) + 1; +} + +double Spin_Lattice_NHC::protocol_fraction(int step, int number_of_steps) const +{ + const int length = protocol_steps_ ? protocol_steps_ : number_of_steps; + return std::min(1.0, double(restart_offset_ + step) / length); +} + +std::string Spin_Lattice_NHC::restart_state() const +{ + if (type != EnsembleType::NVT_NHC || protocol_steps_ == 0) return ""; + std::vector values = {1.0, double(completed_steps_), double(protocol_steps_)}; + values.insert(values.end(), restart_configuration_.begin(), restart_configuration_.end()); + for (int i = 0; i < NOSE_HOOVER_CHAIN_LENGTH; ++i) { + // vel_nhc1 stores conjugate momentum: nhc() advances pos by dt * vel / mass. + values.insert(values.end(), {mas_nhc1[i], pos_nhc1[i], vel_nhc1[i]}); + } + std::ostringstream stream; + stream << std::setprecision(17); + for (size_t i = 0; i < values.size(); ++i) { + if (!std::isfinite(values[i])) PRINT_INPUT_ERROR("Cannot write non-finite NHC checkpoint."); + if (i) stream << ','; + stream << values[i]; + } + return stream.str(); +} + +void Spin_Lattice_NHC::restore_restart(const std::string& state) +{ + std::vector values; + std::istringstream input(state); + std::string token; + if (state.empty() || state.back() == ',') PRINT_INPUT_ERROR("Invalid NHC checkpoint."); + while (std::getline(input, token, ',')) { + try { + size_t end = 0; + const double value = std::stod(token, &end); + if (end != token.size() || !std::isfinite(value)) throw std::invalid_argument("value"); + values.push_back(value); + } catch (...) { PRINT_INPUT_ERROR("Invalid number in NHC checkpoint."); } + } + const size_t expected = 3 + restart_configuration_.size() + 3 * NOSE_HOOVER_CHAIN_LENGTH; + if (values.size() != expected || values[0] != 1.0) PRINT_INPUT_ERROR("Unsupported or truncated NHC checkpoint."); + if (values[1] < 0 || values[1] > 9007197107257343.0 || std::floor(values[1]) != values[1] || + values[2] < 1 || values[2] > 2147483647.0 || std::floor(values[2]) != values[2]) { + PRINT_INPUT_ERROR("Invalid NHC checkpoint step/protocol length."); + } + for (size_t i = 0; i < restart_configuration_.size(); ++i) { + if (values[3 + i] != restart_configuration_[i]) { + PRINT_INPUT_ERROR("NHC restart parameters, atom count or timestep do not match."); + } + } + restart_offset_ = completed_steps_ = static_cast(values[1]); + protocol_steps_ = static_cast(values[2]); + size_t index = 3 + restart_configuration_.size(); + for (int i = 0; i < NOSE_HOOVER_CHAIN_LENGTH; ++i) { + mas_nhc1[i] = values[index++]; pos_nhc1[i] = values[index++]; vel_nhc1[i] = values[index++]; + if (mas_nhc1[i] <= 0.0) PRINT_INPUT_ERROR("NHC checkpoint masses must be positive."); + } +} + +void Spin_Lattice_MTTK::initialize_before_first_step(double time_step, int number_of_steps, const std::vector& group, + Box& box, Atom& atom, GPU_Vector& thermo) +{ + Ensemble_MTTK::initialize_before_first_step(time_step, number_of_steps, group, box, atom, thermo); + protocol_steps = number_of_steps; + if (!atom.spin_lattice_restart.mttk.empty()) { + restore_restart(atom.spin_lattice_restart.mttk); + atom.spin_lattice_restart.mttk.clear(); + printf("Restored MTTK endpoint after %llu steps (protocol length %d).\n", + static_cast(restart_offset), protocol_steps); + } + initialized = true; +} + +void Spin_Lattice_MTTK::compute2(double time_step, int step, int number_of_steps, const std::vector& group, + Box& box, Atom& atom, GPU_Vector& thermo, Force& force) +{ + Ensemble_MTTK::compute2(time_step, step, number_of_steps, group, box, atom, thermo, force); + completed_steps = restart_offset + static_cast(step) + 1; +} + +void Spin_Lattice_MTTK::get_target_temp( + const int step, + const int number_of_steps, + const std::vector& group, + const Box& box, + const Atom& atom, + GPU_Vector& thermo) +{ + t_target = t_start + (t_stop - t_start) * protocol_fraction(step, number_of_steps); +} + +void Spin_Lattice_MTTK::get_target_pressure( + const int step, + const int number_of_steps, + const std::vector& group, + const Box& box, + const Atom& atom, + GPU_Vector& thermo) +{ + double delta = protocol_fraction(step, number_of_steps); + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + p_target[x][y] = p_start[x][y] + (p_stop[x][y] - p_start[x][y]) * delta; + } + } + get_p_hydro(); + if (non_hydrostatic) { + // get_sigma uses its step only for the reference-cell reset test. Reduce + // the absolute checkpoint counter before narrowing to the upstream int. + const int reset_step = h0_reset_interval > 0 ? + static_cast((restart_offset + step) % h0_reset_interval) : step; + get_sigma(reset_step, box); + } +} + +// Only persistent endpoint variables are serialized. Matrix scratch buffers, +// frequencies and substep sizes are recomputed from the checked configuration. +std::vector Spin_Lattice_MTTK::restart_configuration() const +{ + std::vector values = { + double(ensemble_type), double(use_thermostat), double(use_barostat), double(couple_type), + double(non_hydrostatic), double(h0_reset_interval), double(tchain), double(pchain), + double(temperature_dof), dt, t_start, t_stop, t_period, + double(fixed_group), double(move_group), double(fixed_grouping_method), double(move_grouping_method)}; + for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) { + values.insert(values.end(), {p_start[i][j], p_stop[i][j], p_period[i][j], + double(p_flag[i][j]), double(need_scale[i][j])}); + } + return values; +} + +double Spin_Lattice_MTTK::protocol_fraction(int step, int number_of_steps) const +{ + const int length = protocol_steps ? protocol_steps : number_of_steps; + return std::min(1.0, double(restart_offset + step) / length); +} + +std::string Spin_Lattice_MTTK::restart_state() const +{ + if (!initialized) return ""; + // Numeric CSV avoids whitespace/quote ambiguity in extended XYZ headers. + std::vector values = {1.0, double(completed_steps), double(protocol_steps)}; + const auto config = restart_configuration(); + values.insert(values.end(), config.begin(), config.end()); + values.insert(values.end(), {t_current, t_target, t_for_barostat, + double(t_current_from_thermo), factor_eta, vol_ref}); + for (auto matrix : {h_ref_inv, omega_dot, omega_mass, p_current, p_target, p_hydro, sigma}) { + for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) values.push_back(matrix[i][j]); + } + for (int n = 0; n < tchain; ++n) values.insert(values.end(), {Q[n], eta_dot[n], eta_dotdot[n]}); + values.push_back(eta_dot[tchain]); + for (int n = 0; n < pchain; ++n) values.insert(values.end(), {Q_p[n], eta_p_dot[n], eta_p_dotdot[n]}); + values.push_back(eta_p_dot[pchain]); + std::ostringstream stream; + stream << std::setprecision(17); + for (size_t i = 0; i < values.size(); ++i) { + if (!std::isfinite(values[i])) PRINT_INPUT_ERROR("Cannot write non-finite MTTK checkpoint."); + if (i) stream << ','; + stream << values[i]; + } + return stream.str(); +} + +void Spin_Lattice_MTTK::restore_restart(const std::string& state) +{ + std::vector values; + std::istringstream input(state); + std::string token; + if (state.empty() || state.back() == ',') PRINT_INPUT_ERROR("Invalid MTTK checkpoint."); + while (std::getline(input, token, ',')) { + try { + size_t end = 0; + double value = std::stod(token, &end); + if (end != token.size() || !std::isfinite(value)) throw std::invalid_argument("value"); + values.push_back(value); + } catch (...) { PRINT_INPUT_ERROR("Invalid number in MTTK checkpoint."); } + } + const auto config = restart_configuration(); + const size_t expected = 3 + config.size() + 6 + 7 * 9 + 3 * (tchain + pchain) + 2; + if (values.size() != expected || values[0] != 1.0) PRINT_INPUT_ERROR("Unsupported or truncated MTTK checkpoint."); + if (values[1] < 0 || values[1] > 9007197107257343.0 || std::floor(values[1]) != values[1] || + values[2] < 1 || values[2] > 2147483647.0 || std::floor(values[2]) != values[2]) { + PRINT_INPUT_ERROR("Invalid MTTK checkpoint step/protocol length."); + } + for (size_t i = 0; i < config.size(); ++i) { + if (values[3 + i] != config[i]) PRINT_INPUT_ERROR("MTTK restart parameters, atom count or timestep do not match."); + } + restart_offset = completed_steps = static_cast(values[1]); + protocol_steps = static_cast(values[2]); + size_t index = 3 + config.size(); + t_current = values[index++]; t_target = values[index++]; t_for_barostat = values[index++]; + if (values[index] != 0.0 && values[index] != 1.0) PRINT_INPUT_ERROR("Invalid MTTK temperature-cache flag."); + t_current_from_thermo = values[index++] != 0; + factor_eta = values[index++]; vol_ref = values[index++]; + for (auto matrix : {h_ref_inv, omega_dot, omega_mass, p_current, p_target, p_hydro, sigma}) { + for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) matrix[i][j] = values[index++]; + } + for (int n = 0; n < tchain; ++n) { Q[n] = values[index++]; eta_dot[n] = values[index++]; eta_dotdot[n] = values[index++]; } + eta_dot[tchain] = values[index++]; + for (int n = 0; n < pchain; ++n) { Q_p[n] = values[index++]; eta_p_dot[n] = values[index++]; eta_p_dotdot[n] = values[index++]; } + eta_p_dot[pchain] = values[index++]; +} diff --git a/src/integrate/spin/lattice.cuh b/src/integrate/spin/lattice.cuh new file mode 100644 index 000000000..42a21272c --- /dev/null +++ b/src/integrate/spin/lattice.cuh @@ -0,0 +1,64 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once +#include "integrate/ensemble_nhc.cuh" +#include "integrate/ensemble_mttk.cuh" +#include + +// Only Spin ensembles persist lattice baths and the original ramp protocol. +// The upstream base classes own and advance the mechanical state. +class Spin_Lattice_NHC final : public Ensemble_NHC +{ +public: + using Ensemble_NHC::Ensemble_NHC; + void initialize_run(double time_step, Atom& atom, Box& box, const std::vector& group) override; + void compute1(double time_step, int step, int number_of_steps, const std::vector& group, + Box& box, Atom& atom, GPU_Vector& thermo) override; + void compute2(double time_step, int step, int number_of_steps, const std::vector& group, + Box& box, Atom& atom, GPU_Vector& thermo, Force& force) override; + std::string restart_state() const; + double protocol_fraction(int step, int number_of_steps) const; + +private: + void restore_restart(const std::string& state); + std::vector restart_configuration_; + std::uint64_t restart_offset_ = 0, completed_steps_ = 0; + int protocol_steps_ = 0; +}; + +class Spin_Lattice_MTTK final : public Ensemble_MTTK +{ +public: + using Ensemble_MTTK::Ensemble_MTTK; + void initialize_before_first_step(double time_step, int number_of_steps, const std::vector& group, + Box& box, Atom& atom, GPU_Vector& thermo) override; + void compute2(double time_step, int step, int number_of_steps, const std::vector& group, + Box& box, Atom& atom, GPU_Vector& thermo, Force& force) override; + std::string restart_state() const; + double protocol_fraction(int step, int number_of_steps) const; + double get_temperature_period() const { return t_period; } + +private: + void get_target_temp(int step, int number_of_steps, const std::vector& group, + const Box& box, const Atom& atom, GPU_Vector& thermo) override; + void get_target_pressure(int step, int number_of_steps, const std::vector& group, + const Box& box, const Atom& atom, GPU_Vector& thermo) override; + std::vector restart_configuration() const; + void restore_restart(const std::string& state); + std::uint64_t restart_offset = 0, completed_steps = 0; + int protocol_steps = 0; + bool initialized = false; +}; diff --git a/src/integrate/spin/nhc.cu b/src/integrate/spin/nhc.cu new file mode 100644 index 000000000..53b25d737 --- /dev/null +++ b/src/integrate/spin/nhc.cu @@ -0,0 +1,100 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#include "nhc.cuh" +#include + +double nhc( + int chain_length, + double* position, + double* velocity, + double* mass, + double twice_kinetic_energy, + double thermal_energy, + double degrees_of_freedom, + double half_time_step) +{ + const int number_of_yoshida_suzuki_stages = 7; + const int number_of_respa_steps = 4; + const double weight[7] = { + 0.784513610477560, + 0.235573213359357, + -1.17767998417887, + 1.31518632068391, + -1.17767998417887, + 0.235573213359357, + 0.784513610477560}; + + double factor = 1.0; + for (int stage = 0; stage < number_of_yoshida_suzuki_stages; ++stage) { + const double dt2 = + half_time_step * weight[stage] / number_of_respa_steps; + const double dt4 = dt2 * 0.5; + const double dt8 = dt4 * 0.5; + for (int respa = 0; respa < number_of_respa_steps; ++respa) { + double acceleration = + velocity[chain_length - 2] * velocity[chain_length - 2] / + mass[chain_length - 2] - + thermal_energy; + velocity[chain_length - 1] += dt4 * acceleration; + + for (int index = chain_length - 2; index >= 0; --index) { + const double scale = + std::exp(-dt8 * velocity[index + 1] / mass[index + 1]); + if (index == 0) { + acceleration = + twice_kinetic_energy - degrees_of_freedom * thermal_energy; + } else { + acceleration = + velocity[index - 1] * velocity[index - 1] / mass[index - 1] - + thermal_energy; + } + velocity[index] = + scale * (scale * velocity[index] + dt4 * acceleration); + } + + for (int index = chain_length - 1; index >= 0; --index) { + position[index] += dt2 * velocity[index] / mass[index]; + } + + const double factor_local = + std::exp(-dt2 * velocity[0] / mass[0]); + twice_kinetic_energy *= factor_local * factor_local; + factor *= factor_local; + + for (int index = 0; index < chain_length - 1; ++index) { + const double scale = + std::exp(-dt8 * velocity[index + 1] / mass[index + 1]); + if (index == 0) { + acceleration = + twice_kinetic_energy - degrees_of_freedom * thermal_energy; + } else { + acceleration = + velocity[index - 1] * velocity[index - 1] / mass[index - 1] - + thermal_energy; + } + velocity[index] = + scale * (scale * velocity[index] + dt4 * acceleration); + } + + acceleration = + velocity[chain_length - 2] * velocity[chain_length - 2] / + mass[chain_length - 2] - + thermal_energy; + velocity[chain_length - 1] += dt4 * acceleration; + } + } + return factor; +} diff --git a/src/integrate/spin/nhc.cuh b/src/integrate/spin/nhc.cuh new file mode 100644 index 000000000..d00265d77 --- /dev/null +++ b/src/integrate/spin/nhc.cuh @@ -0,0 +1,26 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once + +double nhc( + int chain_length, + double* position, + double* velocity, + double* mass, + double twice_kinetic_energy, + double thermal_energy, + double degrees_of_freedom, + double half_time_step); diff --git a/src/integrate/spin/restart.cu b/src/integrate/spin/restart.cu new file mode 100644 index 000000000..f4b1c1f2d --- /dev/null +++ b/src/integrate/spin/restart.cu @@ -0,0 +1,73 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#include "restart.cuh" +#include "integrate/integrate.cuh" +#include "model/atom.cuh" +#include "utilities/read_file.cuh" +#include "utilities/error.cuh" +#include + +void read_spin_restart(const std::vector& tokens, Atom& atom) +{ + bool has_mttk_state = false, has_mttk_time = false; + for (const auto& token : tokens) { + if (token.find("mttk_state=") == 0) { + if (has_mttk_state || token.size() == 11) PRINT_INPUT_ERROR("Invalid or duplicate MTTK restart state."); + has_mttk_state = true; + atom.spin_lattice_restart.mttk = token.substr(11); + } else if (token.find("mttk_time=") == 0) { + if (has_mttk_time || !is_valid_real(token.substr(10), &atom.spin_lattice_restart.mttk_time) || + !std::isfinite(atom.spin_lattice_restart.mttk_time) || atom.spin_lattice_restart.mttk_time < 0.0) { + PRINT_INPUT_ERROR("Invalid or duplicate MTTK restart time."); + } + has_mttk_time = true; + } + } + if (has_mttk_state != has_mttk_time) PRINT_INPUT_ERROR("MTTK restart requires state and time together."); + + bool has_nhc_state = false, has_nhc_time = false; + for (const auto& token : tokens) { + if (token.find("nhc_state=") == 0) { + if (has_nhc_state || token.size() == 10) PRINT_INPUT_ERROR("Invalid or duplicate NHC restart state."); + has_nhc_state = true; + atom.spin_lattice_restart.nhc = token.substr(10); + } else if (token.find("nhc_time=") == 0) { + if (has_nhc_time || !is_valid_real(token.substr(9), &atom.spin_lattice_restart.nhc_time) || + !std::isfinite(atom.spin_lattice_restart.nhc_time) || atom.spin_lattice_restart.nhc_time < 0.0) { + PRINT_INPUT_ERROR("Invalid or duplicate NHC restart time."); + } + has_nhc_time = true; + } + } + if (has_nhc_state != has_nhc_time) PRINT_INPUT_ERROR("NHC restart requires state and time together."); + if (has_nhc_state && has_mttk_state) PRINT_INPUT_ERROR("Conflicting NHC and MTTK restart states."); + + +} + +bool write_spin_restart(FILE* fid, const Atom& atom, const Integrate& integrate, double global_time) +{ + const std::string mttk_state = integrate.spin_mttk_restart_state(); + const std::string nhc_state = integrate.spin_nhc_restart_state(); + if (!mttk_state.empty()) { + fprintf(fid, "mttk_state=%s mttk_time=%.17g ", mttk_state.c_str(), global_time); + } + if (!nhc_state.empty()) { + fprintf(fid, "nhc_state=%s nhc_time=%.17g ", nhc_state.c_str(), global_time); + } + + return !mttk_state.empty() || !nhc_state.empty(); +} diff --git a/src/integrate/spin/restart.cuh b/src/integrate/spin/restart.cuh new file mode 100644 index 000000000..d4fd8b2d5 --- /dev/null +++ b/src/integrate/spin/restart.cuh @@ -0,0 +1,32 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once +#include +#include +#include + +class Atom; +class Integrate; + +struct Spin_Lattice_Restart +{ + std::string mttk, nhc; // Pending endpoint, consumed once by the Spin lattice driver. + double mttk_time = -1.0, nhc_time = -1.0; // Internal time units. +}; + +void read_spin_restart(const std::vector& tokens, Atom& atom); +// Writes metadata and returns whether moments require checkpoint precision. +bool write_spin_restart(FILE* fid, const Atom& atom, const Integrate& integrate, double global_time); diff --git a/src/integrate/spin_integrator.cuh b/src/integrate/spin_integrator.cuh new file mode 100644 index 000000000..4c9bf1edd --- /dev/null +++ b/src/integrate/spin_integrator.cuh @@ -0,0 +1,29 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once + +class Atom; + +class Spin_Integrator +{ +public: + virtual ~Spin_Integrator(void) = default; + + virtual void compute1(const double time_step, Atom& atom) = 0; + virtual void compute2(const double time_step, Atom& atom) = 0; + + double temperature = 0.0; +}; diff --git a/src/integrate/spin_tspin.cu b/src/integrate/spin_tspin.cu new file mode 100644 index 000000000..98bac28bb --- /dev/null +++ b/src/integrate/spin_tspin.cu @@ -0,0 +1,374 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#include "spin_tspin.cuh" +#include "model/atom.cuh" +#include "spin/nhc.cuh" +#include "utilities/common.cuh" +#include "utilities/error.cuh" +#include "utilities/gpu_macro.cuh" +#include +#include +#include +#include + +namespace +{ +std::uint64_t splitmix64(std::uint64_t value) +{ + value += 0x9e3779b97f4a7c15ULL; + value = (value ^ (value >> 30)) * 0xbf58476d1ce4e5b9ULL; + value = (value ^ (value >> 27)) * 0x94d049bb133111ebULL; + return value ^ (value >> 31); +} + +double uniform_01(std::uint64_t& state) +{ + state = splitmix64(state); + return (state >> 11) * (1.0 / 9007199254740992.0); +} + +double gaussian(std::uint64_t seed, std::uint64_t atom_index, int component) +{ + std::uint64_t state = seed; + state ^= atom_index * 0xd1b54a32d192ed03ULL; + state ^= + static_cast(component) * 0x9e3779b97f4a7c15ULL; + double u1 = 0.0; + do { + u1 = uniform_01(state); + } while (u1 <= 0.0); + const double u2 = uniform_01(state); + return std::sqrt(-2.0 * std::log(u1)) * + std::cos(2.0 * PI * u2); +} +} // namespace + +static __global__ void gpu_scale_spin_velocity( + const int number_of_atoms, + const double factor, + double* spin_velocity) +{ + const int atom = blockIdx.x * blockDim.x + threadIdx.x; + if (atom < number_of_atoms) { + spin_velocity[atom] *= factor; + spin_velocity[number_of_atoms + atom] *= factor; + spin_velocity[2 * number_of_atoms + atom] *= factor; + } +} + +static __global__ void gpu_update_spin_velocity( + const int number_of_atoms, + const double half_time_step, + const double* mass_factor, + const double* mass, + const double* mforce, + double* spin_velocity) +{ + const int atom = blockIdx.x * blockDim.x + threadIdx.x; + if (atom < number_of_atoms && mass_factor[atom] > 0.0) { + const double coefficient = + half_time_step / (mass[atom] * mass_factor[atom]); + spin_velocity[atom] += coefficient * mforce[atom]; + spin_velocity[number_of_atoms + atom] += + coefficient * mforce[number_of_atoms + atom]; + spin_velocity[2 * number_of_atoms + atom] += + coefficient * mforce[2 * number_of_atoms + atom]; + } +} + +static __global__ void gpu_update_spin( + const int number_of_atoms, + const double time_step, + const double* spin_velocity, + const double* mass_factor, + double* spin) +{ + const int atom = blockIdx.x * blockDim.x + threadIdx.x; + if (atom < number_of_atoms && mass_factor[atom] > 0.0) { + spin[atom] += time_step * spin_velocity[atom]; + spin[number_of_atoms + atom] += + time_step * spin_velocity[number_of_atoms + atom]; + spin[2 * number_of_atoms + atom] += + time_step * spin_velocity[2 * number_of_atoms + atom]; + } +} + +static __global__ void gpu_find_spin_kinetic_energy( + const int number_of_atoms, + const int number_of_rounds, + const double* mass_factor, + const double* mass, + const double* spin_velocity, + double* twice_kinetic_energy) +{ + const int thread = threadIdx.x; + __shared__ double kinetic_energy[1024]; + kinetic_energy[thread] = 0.0; + for (int round = 0; round < number_of_rounds; ++round) { + const int atom = round * blockDim.x + thread; + if (atom < number_of_atoms && mass_factor[atom] > 0.0) { + const double vx = spin_velocity[atom]; + const double vy = spin_velocity[number_of_atoms + atom]; + const double vz = spin_velocity[2 * number_of_atoms + atom]; + kinetic_energy[thread] += + mass[atom] * mass_factor[atom] * (vx * vx + vy * vy + vz * vz); + } + } + __syncthreads(); + for (int offset = blockDim.x >> 1; offset > 0; offset >>= 1) { + if (thread < offset) { + kinetic_energy[thread] += kinetic_energy[thread + offset]; + } + __syncthreads(); + } + if (thread == 0) { + twice_kinetic_energy[0] = kinetic_energy[0]; + } +} + +Spin_TSPIN::Spin_TSPIN( + double initial_temperature, + double temperature_coupling, + double time_step, + const std::vector& mass_factor_by_type, + int seed, + Atom& atom) + : twice_kinetic_energy_(1) +{ + const int number_of_atoms = atom.number_of_atoms; + if (!atom.has_spin || + atom.spin_per_atom.size() != 3 * number_of_atoms || + atom.mforce_per_atom.size() != 3 * number_of_atoms || + atom.spin_velocity_per_atom.size() != 3 * number_of_atoms || + atom.cpu_mass.size() != number_of_atoms || + atom.cpu_type.size() != number_of_atoms) { + PRINT_INPUT_ERROR("TSPIN requires complete spin, mforce, mass, and type arrays."); + } + if (!(initial_temperature > 0.0) || !std::isfinite(initial_temperature) || + !(temperature_coupling >= 1.0) || !std::isfinite(temperature_coupling) || + !(time_step > 0.0) || !std::isfinite(time_step)) { + PRINT_INPUT_ERROR("TSPIN requires finite positive integration parameters."); + } + if (atom.spin_velocity_initialized && + atom.cpu_spin_velocity_per_atom.size() != 3 * number_of_atoms) { + PRINT_INPUT_ERROR("Initialized TSPIN velocities have an invalid size."); + } + if (mass_factor_by_type.size() != atom.cpu_type_size.size()) { + PRINT_INPUT_ERROR("TSPIN mass factors do not match the atom types."); + } + cpu_mass_factor_per_atom_.resize(number_of_atoms); + for (int atom_index = 0; atom_index < number_of_atoms; ++atom_index) { + const double factor = mass_factor_by_type[atom.cpu_type[atom_index]]; + if (factor < 0.0 || !std::isfinite(factor)) { + PRINT_INPUT_ERROR("TSPIN mass factors should be finite and >= 0."); + } + cpu_mass_factor_per_atom_[atom_index] = factor; + number_of_active_atoms_ += factor > 0.0; + } + if (number_of_active_atoms_ == 0) { + PRINT_INPUT_ERROR("TSPIN requires at least one positive mass factor."); + } + mass_factor_per_atom_.resize(number_of_atoms); + mass_factor_per_atom_.copy_from_host(cpu_mass_factor_per_atom_.data()); + pos_nhc_[0] = pos_nhc_[1] = pos_nhc_[2] = pos_nhc_[3] = 0.0; + vel_nhc_[0] = vel_nhc_[2] = 1.0; + vel_nhc_[1] = vel_nhc_[3] = -1.0; + + const double thermal_energy = K_B * initial_temperature; + const double tau = time_step * temperature_coupling; + for (int index = 0; index < 4; ++index) { + mas_nhc_[index] = thermal_energy * tau * tau; + } + mas_nhc_[0] *= 3.0 * number_of_active_atoms_; + + initialize_spin_velocity(initial_temperature, seed, atom); +} + +void Spin_TSPIN::initialize_spin_velocity( + double initial_temperature, + int seed, + Atom& atom) +{ + if (atom.spin_velocity_initialized) { + const int number_of_atoms = atom.number_of_atoms; + for (int component = 0; component < 3; ++component) { + for (int atom_index = 0; atom_index < number_of_atoms; ++atom_index) { + double& value = atom.cpu_spin_velocity_per_atom[ + component * number_of_atoms + atom_index]; + if (!std::isfinite(value)) { + PRINT_INPUT_ERROR("Initialized TSPIN velocities must be finite."); + } + if (cpu_mass_factor_per_atom_[atom_index] == 0.0) { + value = 0.0; + } + } + } + atom.spin_velocity_per_atom.copy_from_host( + atom.cpu_spin_velocity_per_atom.data()); + printf("Reuse initialized spin velocities; TSPIN seed is not used.\n"); + return; + } + + const int number_of_atoms = atom.number_of_atoms; + const int number_of_types = atom.cpu_type_size.size(); + atom.cpu_spin_velocity_per_atom.assign(3 * number_of_atoms, 0.0); + for (int atom_index = 0; atom_index < number_of_atoms; ++atom_index) { + if (cpu_mass_factor_per_atom_[atom_index] == 0.0) { + continue; + } + for (int component = 0; component < 3; ++component) { + atom.cpu_spin_velocity_per_atom[ + component * number_of_atoms + atom_index] = + 0.5 * gaussian( + static_cast(seed), + static_cast(atom_index + 1), + component); + } + } + + std::vector twice_kinetic_energy(number_of_types, 0.0); + std::vector type_count(number_of_types, 0); + for (int atom_index = 0; atom_index < number_of_atoms; ++atom_index) { + if (cpu_mass_factor_per_atom_[atom_index] == 0.0) { + continue; + } + const int type = atom.cpu_type[atom_index]; + const double mass = + atom.cpu_mass[atom_index] * cpu_mass_factor_per_atom_[atom_index]; + if (!(mass > 0.0) || !std::isfinite(mass)) { + PRINT_INPUT_ERROR("TSPIN requires finite positive spin masses."); + } + double velocity_squared = 0.0; + for (int component = 0; component < 3; ++component) { + const double velocity = atom.cpu_spin_velocity_per_atom[ + component * number_of_atoms + atom_index]; + velocity_squared += velocity * velocity; + } + twice_kinetic_energy[type] += mass * velocity_squared; + ++type_count[type]; + } + + for (int type = 0; type < number_of_types; ++type) { + if (type_count[type] == 0) { + continue; + } + if (!(twice_kinetic_energy[type] > 0.0) || + !std::isfinite(twice_kinetic_energy[type])) { + PRINT_INPUT_ERROR("Failed to initialize finite TSPIN velocities."); + } + const double target = + 3.0 * type_count[type] * K_B * initial_temperature; + const double factor = + std::sqrt(target / twice_kinetic_energy[type]); + for (int atom_index = 0; atom_index < number_of_atoms; ++atom_index) { + if (atom.cpu_type[atom_index] != type) { + continue; + } + for (int component = 0; component < 3; ++component) { + atom.cpu_spin_velocity_per_atom[ + component * number_of_atoms + atom_index] *= factor; + } + } + } + + atom.spin_velocity_per_atom.copy_from_host( + atom.cpu_spin_velocity_per_atom.data()); + atom.spin_velocity_initialized = true; + printf("Initialized TSPIN velocities with seed %d.\n", seed); +} + +double Spin_TSPIN::find_twice_kinetic_energy(const Atom& atom) +{ + const int number_of_atoms = atom.number_of_atoms; + gpu_find_spin_kinetic_energy<<<1, 1024>>>( + number_of_atoms, + (number_of_atoms - 1) / 1024 + 1, + mass_factor_per_atom_.data(), + atom.mass.data(), + atom.spin_velocity_per_atom.data(), + twice_kinetic_energy_.data()); + GPU_CHECK_KERNEL + double twice_kinetic_energy = 0.0; + twice_kinetic_energy_.copy_to_host(&twice_kinetic_energy); + return twice_kinetic_energy; +} + +double Spin_TSPIN::find_nhc_factor( + const double time_step, + const Atom& atom) +{ + const double twice_kinetic_energy = find_twice_kinetic_energy(atom); + const double thermal_energy = K_B * temperature; + const double degrees_of_freedom = 3.0 * number_of_active_atoms_; + const double factor = nhc( + 4, + pos_nhc_, + vel_nhc_, + mas_nhc_, + twice_kinetic_energy, + thermal_energy, + degrees_of_freedom, + time_step * 0.5); + if (!std::isfinite(factor)) { + PRINT_INPUT_ERROR("TSPIN thermostat produced a non-finite scale factor."); + } + return factor; +} + +void Spin_TSPIN::compute1(const double time_step, Atom& atom) +{ + const int number_of_atoms = atom.number_of_atoms; + const int number_of_blocks = (number_of_atoms - 1) / 128 + 1; + const double factor = find_nhc_factor(time_step, atom); + gpu_scale_spin_velocity<<>>( + number_of_atoms, + factor, + atom.spin_velocity_per_atom.data()); + gpu_update_spin_velocity<<>>( + number_of_atoms, + time_step * 0.5, + mass_factor_per_atom_.data(), + atom.mass.data(), + atom.mforce_per_atom.data(), + atom.spin_velocity_per_atom.data()); + gpu_update_spin<<>>( + number_of_atoms, + time_step, + atom.spin_velocity_per_atom.data(), + mass_factor_per_atom_.data(), + atom.spin_per_atom.data()); + GPU_CHECK_KERNEL +} + +void Spin_TSPIN::compute2(const double time_step, Atom& atom) +{ + const int number_of_atoms = atom.number_of_atoms; + const int number_of_blocks = (number_of_atoms - 1) / 128 + 1; + gpu_update_spin_velocity<<>>( + number_of_atoms, + time_step * 0.5, + mass_factor_per_atom_.data(), + atom.mass.data(), + atom.mforce_per_atom.data(), + atom.spin_velocity_per_atom.data()); + GPU_CHECK_KERNEL + const double factor = find_nhc_factor(time_step, atom); + gpu_scale_spin_velocity<<>>( + number_of_atoms, + factor, + atom.spin_velocity_per_atom.data()); + GPU_CHECK_KERNEL +} diff --git a/src/integrate/spin_tspin.cuh b/src/integrate/spin_tspin.cuh new file mode 100644 index 000000000..14eaa7ff0 --- /dev/null +++ b/src/integrate/spin_tspin.cuh @@ -0,0 +1,53 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once + +#include "spin_integrator.cuh" +#include "utilities/gpu_vector.cuh" +#include + +class Atom; + +class Spin_TSPIN : public Spin_Integrator +{ +public: + Spin_TSPIN( + double initial_temperature, + double temperature_coupling, + double time_step, + const std::vector& mass_factor_by_type, + int seed, + Atom& atom); + + void compute1(const double time_step, Atom& atom) override; + void compute2(const double time_step, Atom& atom) override; + +private: + double find_twice_kinetic_energy(const Atom& atom); + double find_nhc_factor(const double time_step, const Atom& atom); + void initialize_spin_velocity( + double initial_temperature, + int seed, + Atom& atom); + + double pos_nhc_[4]; + double vel_nhc_[4]; + double mas_nhc_[4]; + int number_of_active_atoms_ = 0; + std::vector cpu_mass_factor_per_atom_; + GPU_Vector mass_factor_per_atom_; + GPU_Vector twice_kinetic_energy_; +}; diff --git a/src/main_gpumd/replicate.cu b/src/main_gpumd/replicate.cu index d21c05f54..efac4b224 100644 --- a/src/main_gpumd/replicate.cu +++ b/src/main_gpumd/replicate.cu @@ -56,6 +56,12 @@ void Replicate( new_atoms.cpu_atom_symbol.resize(N); new_atoms.cpu_position_per_atom.resize(N * 3); new_atoms.cpu_velocity_per_atom.resize(N * 3); + new_atoms.has_spin = atoms.has_spin; + new_atoms.spin_velocity_initialized = atoms.spin_velocity_initialized; + if (atoms.has_spin) { + new_atoms.cpu_spin_per_atom.resize(N * 3); + new_atoms.cpu_spin_velocity_per_atom.resize(N * 3); + } int cur = 0; for (int i = 0; i < r[0]; i++) { for (int j = 0; j < r[1]; j++) { @@ -72,6 +78,11 @@ void Replicate( new_atoms.cpu_position_per_atom[cur + d * N] += i * box.cpu_h[d * 3] + j * box.cpu_h[d * 3 + 1] + k * box.cpu_h[d * 3 + 2]; new_atoms.cpu_velocity_per_atom[cur + d * N] = atoms.cpu_velocity_per_atom[nn + d * n]; + if (atoms.has_spin) { + new_atoms.cpu_spin_per_atom[cur + d * N] = atoms.cpu_spin_per_atom[nn + d * n]; + new_atoms.cpu_spin_velocity_per_atom[cur + d * N] = + atoms.cpu_spin_velocity_per_atom[nn + d * n]; + } } cur++; } @@ -101,6 +112,12 @@ void Replicate( new_atoms.cpu_position_per_atom.begin(), new_atoms.cpu_position_per_atom.end()); atoms.cpu_velocity_per_atom.assign( new_atoms.cpu_velocity_per_atom.begin(), new_atoms.cpu_velocity_per_atom.end()); + atoms.has_spin = new_atoms.has_spin; + atoms.spin_velocity_initialized = new_atoms.spin_velocity_initialized; + atoms.cpu_spin_per_atom.assign( + new_atoms.cpu_spin_per_atom.begin(), new_atoms.cpu_spin_per_atom.end()); + atoms.cpu_spin_velocity_per_atom.assign( + new_atoms.cpu_spin_velocity_per_atom.begin(), new_atoms.cpu_spin_velocity_per_atom.end()); for (int& i : atoms.cpu_type_size) i = i * r[0] * r[1] * r[2]; diff --git a/src/main_gpumd/run.cu b/src/main_gpumd/run.cu index 519f6dbb9..82193e07d 100644 --- a/src/main_gpumd/run.cu +++ b/src/main_gpumd/run.cu @@ -202,7 +202,7 @@ void Run::execute_run_in(const RunInput& run_input) void Run::compute_force() { - if (is_pimd(integrate.get_type())) { + if (is_pimd(integrate.get_type())) { // PIMD for (int k = 0; k < integrate.get_number_of_beads(); ++k) { force.compute( box, @@ -216,23 +216,49 @@ void Run::compute_force() atom.mass); } } else { - force.compute( - box, - atom.position_per_atom, - atom.type, - group, - atom.potential_per_atom, - atom.force_per_atom, - atom.virial_per_atom, - atom.velocity_per_atom, - atom.mass, - atom.position_image.size() > 0 ? atom.position_image.data() : nullptr); + if (force.has_spin_potential()) { + if (!atom.has_spin) { + PRINT_INPUT_ERROR("NEP_Spin requires spin:R:3 in model.xyz."); + } + force.compute_spin( + box, + atom.position_per_atom, + atom.type, + group, + atom.potential_per_atom, + atom.force_per_atom, + atom.virial_per_atom, + atom.spin_per_atom, + atom.mforce_per_atom, + atom.position_image.size() > 0 ? atom.position_image.data() : nullptr); + } else { + force.compute( + box, + atom.position_per_atom, + atom.type, + group, + atom.potential_per_atom, + atom.force_per_atom, + atom.virial_per_atom, + atom.velocity_per_atom, + atom.mass, + atom.position_image.size() > 0 ? atom.position_image.data() : nullptr); + } } } void Run::perform_a_run(const int number_of_steps) { + if (force.has_mfield() && (!force.has_spin_potential() || !atom.has_spin)) { + PRINT_INPUT_ERROR("add_mfield requires a Spin potential and spin:R:3."); + } + if ((integrate.use_spin_tspin) && + (!force.has_spin_potential() || !atom.has_spin)) { + PRINT_INPUT_ERROR("A spin ensemble requires a Spin potential and spin:R:3 in model.xyz."); + } + integrate.restore_spin_time(atom, global_time); integrate.initialize(time_step, atom, box, group); + measure.pre_run(number_of_steps, time_step, integrate, group, atom, box, force); // setup force for the first integrate step @@ -261,12 +287,15 @@ void Run::perform_a_run(const int number_of_steps) measure.pre_force(step, time_step, integrate, group, atom, box, force); compute_force(); + atom.update_unwrapped_position(box); measure.post_force(step, time_step, integrate, group, atom, box, force); integrate.compute2(time_step, step, number_of_steps, group, box, atom, thermo, force); atom.update_unwrapped_position(box); + + measure.end_of_step( number_of_steps, step, @@ -313,6 +342,10 @@ void Run::parse_one_keyword( PRINT_INPUT_ERROR("replicate must be the first effective command."); } + for (const char* unsupported : {"dump_observer", "compute_hac", "compute_hnemd", "compute_hnemdec", + "compute_shc", "compute_gkma", "compute_hnema", "deform", "compute_lsqt"}) { + if (tokens[0] == unsupported) mark_spin_unsupported(unsupported); + } const int num_param = tokens.size(); const int max_num_param = 32; if (num_param > max_num_param) @@ -324,7 +357,11 @@ void Run::parse_one_keyword( if (tokens[0] == "potential") { force.parse_potential(tokens, box, atom.type.size(), run_input); + if (force.has_spin_potential() && !spin_unsupported_command.empty()) { + mark_spin_unsupported(spin_unsupported_command.c_str()); + } } else if (tokens[0] == "minimize") { + mark_spin_unsupported(tokens[0].c_str()); Minimize minimize; minimize.parse_minimize( tokens, @@ -335,6 +372,7 @@ void Run::parse_one_keyword( atom, group); } else if (tokens[0] == "compute_phonon") { + mark_spin_unsupported(tokens[0].c_str()); Hessian hessian; hessian.parse(tokens); if (!has_replicate_) { @@ -342,10 +380,12 @@ void Run::parse_one_keyword( } hessian.compute(force, box, atom, group, replicate_size_); } else if (tokens[0] == "compute_cohesive") { + mark_spin_unsupported(tokens[0].c_str()); Cohesive cohesive; cohesive.parse(tokens, 0); cohesive.compute(box, atom, group, force); } else if (tokens[0] == "compute_elastic") { + mark_spin_unsupported(tokens[0].c_str()); Cohesive cohesive; cohesive.parse(tokens, 1); cohesive.compute(box, atom, group, force); @@ -354,7 +394,15 @@ void Run::parse_one_keyword( } else if (tokens[0] == "velocity") { parse_velocity(tokens); } else if (tokens[0] == "ensemble") { + if (tokens.size() < 2 || (tokens[1] != "nve" && tokens[1] != "nvt_nhc" && + tokens[1] != "nvt_tspin" && tokens[1] != "npt_tspin")) { + mark_spin_unsupported("ensemble"); + } integrate.parse_ensemble(tokens, atom, box, group); + } else if (tokens[0] == "add_mfield") { + std::vector fields; + for (const auto& token : tokens) fields.push_back(token.c_str()); + force.parse_mfield(fields.data(), fields.size(), group); } else if (tokens[0] == "time_step") { parse_time_step(tokens); } else if (tokens[0] == "correct_velocity") { @@ -364,11 +412,13 @@ void Run::parse_one_keyword( } else if (tokens[0] == "move") { integrate.parse_move(tokens, group); } else if (tokens[0] == "kspace") { + mark_spin_unsupported(tokens[0].c_str()); if (has_seen_kspace_command) { PRINT_INPUT_ERROR("kspace can only appear once."); } has_seen_kspace_command = true; } else if (tokens[0] == "dftd3") { + mark_spin_unsupported(tokens[0].c_str()); if (has_seen_dftd3_command) { PRINT_INPUT_ERROR("dftd3 can only appear once."); } @@ -388,6 +438,16 @@ void Run::parse_one_keyword( } } +void Run::mark_spin_unsupported(const char* command) +{ + if (force.has_spin_potential()) { + PRINT_INPUT_ERROR((std::string("NEP_Spin does not support command ") + command + ".").c_str()); + } + if (spin_unsupported_command.empty()) { + spin_unsupported_command = command; + } +} + void Run::parse_velocity(const std::vector& tokens) { const int num_param = tokens.size(); diff --git a/src/main_gpumd/run.cuh b/src/main_gpumd/run.cuh index 248e87969..7bbe03f6f 100644 --- a/src/main_gpumd/run.cuh +++ b/src/main_gpumd/run.cuh @@ -45,6 +45,8 @@ private: const std::vector& tokens, const RunInput& run_input); // keyword parsing functions + std::string spin_unsupported_command; + void mark_spin_unsupported(const char* command); void parse_velocity(const std::vector& tokens); void parse_change_box(const std::vector& tokens); void parse_correct_velocity( diff --git a/src/main_nep/nep/nep_evaluate.cu b/src/main_nep/common/nep_evaluate.cu similarity index 98% rename from src/main_nep/nep/nep_evaluate.cu rename to src/main_nep/common/nep_evaluate.cu index 9975bbf1b..bf0eaba8d 100644 --- a/src/main_nep/nep/nep_evaluate.cu +++ b/src/main_nep/common/nep_evaluate.cu @@ -713,3 +713,14 @@ void NEP_Compiled_Evaluation::launch_force_angular( sum_fxyz, 0, fx, fy, fz, virial), "force_angular_jit"); } + +NEP_Compiled_Evaluation::NEP_Compiled_Evaluation(const NEP_Compile_Config& config) + : library(config) +{ + if (!library.is_valid()) { + return; + } + valid = common.load(library); + valid &= library.load_symbol("nep_train_launch_ann_nep", ann_nep_); + valid &= library.load_symbol("nep_train_launch_ann_temperature", ann_temperature_); +} diff --git a/src/main_nep/nep/nep_evaluate.cuh b/src/main_nep/common/nep_evaluate.cuh similarity index 100% rename from src/main_nep/nep/nep_evaluate.cuh rename to src/main_nep/common/nep_evaluate.cuh diff --git a/src/main_nep/common/nep_io.cu b/src/main_nep/common/nep_io.cu index 4b0ee72a5..334c052c0 100644 --- a/src/main_nep/common/nep_io.cu +++ b/src/main_nep/common/nep_io.cu @@ -137,7 +137,7 @@ static float read_nep_restart_value(std::istream& input, const std::string& file static void read_nep_restart_file( const std::string& filename, const NEP_Parameters& para, int num_types, std::vector& reference, std::vector* mu = nullptr, - std::vector* sigma = nullptr) + std::vector* sigma = nullptr, int expected_count = 0) { std::ifstream input(filename); if (!input.is_open()) { @@ -163,7 +163,8 @@ static void read_nep_restart_file( (num_types * para.number_of_variables_ann_1 + para.global_parameters) * para.ann_count; const int num_radial_basis = (para.n_max_radial + 1) * (para.basis_size_radial + 1); const int num_angular_basis = (para.n_max_angular + 1) * (para.basis_size_angular + 1); - const int num_parameters = ann_size + (num_radial_basis + num_angular_basis) * num_types * num_types; + const int num_parameters = expected_count ? expected_count : + ann_size + (num_radial_basis + num_angular_basis) * num_types * num_types; if (!(input >> token >> count) || token != "parameters" || count != num_parameters) { PRINT_INPUT_ERROR((filename + ": invalid parameter count.").c_str()); } @@ -194,13 +195,19 @@ bool read_nep_restart( const char* filename, const NEP_Parameters& para, std::vector& mu, - std::vector& sigma) + std::vector& sigma, + std::vector* energy_reference) { if (!does_file_exist(filename)) { return false; } std::vector reference; +#ifdef USE_CJ read_nep_restart_file(filename, para, para.num_types, reference, &mu, &sigma); +#else + read_nep_restart_file(filename, para, para.num_types, reference, &mu, &sigma, para.number_of_variables); +#endif + if (energy_reference) *energy_reference = reference; return true; } @@ -247,7 +254,7 @@ void read_nep_prediction_zbl(NEP_Parameters& para) } } -static void write_nep_header( +void write_nep_header( FILE* file, const NEP_Parameters& para, int max_radial, int max_angular) { fprintf(file, "nep %d", para.num_types); @@ -354,6 +361,11 @@ void write_nep_model( CHECK(gpuSetDevice(0)); para.q_scaler_gpu[0].copy_to_host(para.q_scaler_cpu.data()); write_nep_header(file, para, max_radial, max_angular); + write_nep_model_parameters(file, para, parameters); +} + +void write_nep_model_parameters(FILE* file, const NEP_Parameters& para, const float* parameters) +{ const std::vector values = get_nep_file_parameters(para, parameters); write_nep_block(file, "parameters", values.data(), values.size()); write_nep_block(file, "q_scaler", para.q_scaler_cpu.data(), para.dim); diff --git a/src/main_nep/common/nep_io.cuh b/src/main_nep/common/nep_io.cuh index a6ec3a2ac..235566a92 100644 --- a/src/main_nep/common/nep_io.cuh +++ b/src/main_nep/common/nep_io.cuh @@ -27,7 +27,8 @@ bool read_nep_restart( const char* filename, const NEP_Parameters& para, std::vector& mu, - std::vector& sigma); + std::vector& sigma, + std::vector* energy_reference = nullptr); void read_nep_foundation_restart( const NEP_Parameters& para, std::vector& mu, std::vector& sigma); @@ -46,3 +47,6 @@ void write_nep_model( FILE* file, NEP_Parameters& para, const float* parameters, int max_radial, int max_angular); void check_existing_nep_model(NEP_Parameters& para); + +void write_nep_header(FILE*, const NEP_Parameters&, int, int); +void write_nep_model_parameters(FILE*, const NEP_Parameters&, const float*); diff --git a/src/main_nep/common/nep_parameters.cuh b/src/main_nep/common/nep_parameters.cuh index 29bb29d12..42a185454 100644 --- a/src/main_nep/common/nep_parameters.cuh +++ b/src/main_nep/common/nep_parameters.cuh @@ -113,13 +113,13 @@ public: GPU_Vector q_scaler_min[16]; // used to scale some descriptor components (GPU) protected: + void report_inputs(const ParameterInput& input, const char* model_name, + const char* model_description); virtual void report_model_inputs() const {} + virtual void read_zbl_in(); private: - void read_zbl_in(); void initialize_q_scaler(); - void report_inputs(const ParameterInput& input, const char* model_name, - const char* model_description); void parse_nep_compile(const char** param, int num_param); void parse_version(const char** param, int num_param); void parse_type(const char** param, int num_param); diff --git a/src/main_nep/nep/nep.cu b/src/main_nep/nep/nep.cu index 65f2d0c78..c947b234b 100644 --- a/src/main_nep/nep/nep.cu +++ b/src/main_nep/nep/nep.cu @@ -107,16 +107,6 @@ NEP_Compile_Config make_compile_config( } } // namespace -NEP_Compiled_Evaluation::NEP_Compiled_Evaluation(const NEP_Compile_Config& config) - : library(config) -{ - if (!library.is_valid()) { - return; - } - valid = common.load(library); - valid &= library.load_symbol("nep_train_launch_ann_nep", ann_nep_); - valid &= library.load_symbol("nep_train_launch_ann_temperature", ann_temperature_); -} void NEP::initialize_compiled_kernel(const NEP_Potential_Parameters& para) { diff --git a/src/main_nep/nep/nep.cuh b/src/main_nep/nep/nep.cuh index 16c958146..18954d1da 100644 --- a/src/main_nep/nep/nep.cuh +++ b/src/main_nep/nep/nep.cuh @@ -21,7 +21,7 @@ #include "main_nep/common/nep_batch_data.cuh" #include "main_nep/common/energy_difference.cuh" #include "main_nep/common/nep_compile.cuh" -#include "nep_evaluate.cuh" +#include "main_nep/common/nep_evaluate.cuh" #include "main_nep/common/nep_common.cuh" #include diff --git a/src/main_nep/nep_spin/nep_spin.cu b/src/main_nep/nep_spin/nep_spin.cu new file mode 100644 index 000000000..c6b08df7b --- /dev/null +++ b/src/main_nep/nep_spin/nep_spin.cu @@ -0,0 +1,507 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. +*/ + +#include "nep_spin.cuh" +#include "spin_init.cuh" +#include "spin_io.cuh" +#include "spin_policy.cuh" +#include "main_nep/common/nep_output.cuh" +#include "main_nep/common/nep_init.cuh" +#include "main_nep/common/nep_io.cuh" +#include "main_nep/common/nep_model.cuh" +#include "utilities/error.cuh" +#include "utilities/nep_utilities.cuh" +#include +void NEP_Spin_Model::initialize(Spin_Parameters& para, int N, int deviceCount) +{ + initialize_model(para); + for (int device_id = 0; device_id < deviceCount; ++device_id) { + CHECK(gpuSetDevice(device_id)); + initialize_device(para, N, device_id); + } + initialize_compiled_kernel(para); + initialize_spin(para, N, deviceCount); +} + +void NEP_Spin_Model::initialize_model(const Spin_Parameters& para) +{ + paramb.version = para.version; + paramb.num_types = para.num_types; + for (int t = 0; t < paramb.num_types; ++t) { + paramb.rc_radial[t] = para.rc_radial[t]; + paramb.rc_angular[t] = para.rc_angular[t]; + } + paramb.n_max_radial = para.n_max_radial; + paramb.n_max_angular = para.n_max_angular; + paramb.L_max = para.L_max; + paramb.has_q_222 = para.has_q_222; + paramb.has_q_1111 = para.has_q_1111; + paramb.has_q_112 = para.has_q_112; + paramb.has_q_123 = para.has_q_123; + paramb.has_q_233 = para.has_q_233; + paramb.has_q_134 = para.has_q_134; + paramb.num_L = para.dim_angular / (para.n_max_angular + 1); + paramb.dim_angular = para.dim_angular; + + paramb.basis_size_radial = para.basis_size_radial; + paramb.basis_size_angular = para.basis_size_angular; + paramb.num_types_sq = para.num_types * para.num_types; +#ifdef USE_CJ + paramb.num_c_radial = + paramb.num_types * (para.n_max_radial + 1) * (para.basis_size_radial + 1); +#else + paramb.num_c_radial = + paramb.num_types_sq * (para.n_max_radial + 1) * (para.basis_size_radial + 1); +#endif + + initialize_nep_zbl(para, zbl); +} + +void NEP_Spin_Model::initialize_device(const Spin_Parameters& para, int N, int device_id) +{ + NEP_ANN& ann = annmb[device_id]; + NEP_Data& data = nep_data[device_id]; + ann.dim = para.dim; + ann.num_neurons1 = para.num_neurons1; + ann.num_hidden_layers = para.num_hidden_layers; + ann.num_para = para.number_of_variables; + if (para.num_hidden_layers == 2) { + ann.num_neurons2 = para.num_neurons2; + } + ann.one_ann_no_bias = para.number_of_variables_ann_1; + + data.descriptors.resize(N * ann.dim); + data.Fp.resize(N * ann.dim); + data.sum_fxyz.resize( + N * (paramb.n_max_angular + 1) * ((paramb.L_max + 1) * (paramb.L_max + 1) - 1)); + data.parameters.resize(ann.num_para); +} + +void NEP_Spin_Model::initialize_compiled_kernel(const Spin_Parameters& para) { + if (para.nep_compile && para.prediction == 0) { + CHECK(gpuSetDevice(0)); + auto config = make_nep_compile_config(para); + config.model_name = "Spin3"; + config.source_file = "main_nep/nep/nep_specialized.cu"; + compiled_kernel_.reset(new NEP_Compiled_Evaluation(config)); + if (!compiled_kernel_->is_valid()) compiled_kernel_.reset(); + } +} +static void __global__ find_max_min( + const int N, + const float* g_q, + float* g_q_scaler, + float* g_q_scaler_max, + float* g_q_scaler_min, + float* g_q_square_sum, + unsigned long long* g_q_count) +{ + const int tid = threadIdx.x; + const int bid = blockIdx.x; + __shared__ float s_max[1024]; + __shared__ float s_min[1024]; + __shared__ float s_square_sum[1024]; + s_max[tid] = -1000000.0f; // a small number + s_min[tid] = +1000000.0f; // a large number + s_square_sum[tid] = 0.0f; + const int stride = 1024; + const int number_of_rounds = (N - 1) / stride + 1; + for (int round = 0; round < number_of_rounds; ++round) { + const int n = round * stride + tid; + if (n < N) { + const int m = n + N * bid; + float q = g_q[m]; + s_square_sum[tid] += q * q; + if (q > s_max[tid]) { + s_max[tid] = q; + } + if (q < s_min[tid]) { + s_min[tid] = q; + } + } + } + __syncthreads(); + for (int offset = blockDim.x >> 1; offset > 0; offset >>= 1) { + if (tid < offset) { + if (s_max[tid] < s_max[tid + offset]) { + s_max[tid] = s_max[tid + offset]; + } + if (s_min[tid] > s_min[tid + offset]) { + s_min[tid] = s_min[tid + offset]; + } + s_square_sum[tid] += s_square_sum[tid + offset]; + } + __syncthreads(); + } + if (tid == 0) { + g_q_scaler_max[bid] = max(g_q_scaler_max[bid], s_max[0]); + g_q_scaler_min[bid] = min(g_q_scaler_min[bid], s_min[0]); + g_q_square_sum[bid] += s_square_sum[0]; + g_q_count[bid] += static_cast(N); + g_q_scaler[bid] = 1.0f / (g_q_scaler_max[bid] - g_q_scaler_min[bid]); + } +} + +template +static __global__ void apply_ann_one_layer_warp( + const int N, + const NEP_ANN annmb, + const int* __restrict__ g_type, + const float* __restrict__ g_descriptors, + const float* __restrict__ g_q_scaler, + double* g_pe, + float* g_Fp) +{ + constexpr int warp_size = 32; + constexpr int values_per_lane = (max_dim + warp_size - 1) / warp_size; + const int lane = threadIdx.x & (warp_size - 1); + const int atom = (blockIdx.x * blockDim.x + threadIdx.x) / warp_size; + if (atom >= N) return; + + const int dim = annmb.dim; + const int num_neurons = annmb.num_neurons1; + const int type = g_type[atom]; + const float* w0 = annmb.wb[type]; + const float* b0 = w0 + num_neurons * dim; + const float* w1 = b0 + num_neurons; + float q[values_per_lane] = {}; + float Fp[values_per_lane] = {}; + for (int k = 0; k < values_per_lane; ++k) { + const int d = lane + k * warp_size; + if (d < dim) { + q[k] = g_descriptors[atom + d * N] * g_q_scaler[d]; + } + } + + float energy = 0.0f; + for (int n = 0; n < num_neurons; ++n) { + float w0_times_q = 0.0f; + for (int k = 0; k < values_per_lane; ++k) { + const int d = lane + k * warp_size; + if (d < dim) w0_times_q += w0[n * dim + d] * q[k]; + } + for (int offset = warp_size / 2; offset > 0; offset /= 2) { + w0_times_q += __shfl_down_sync(0xffffffff, w0_times_q, offset); + } + float derivative_scale = 0.0f; + if (lane == 0) { + const float x1 = tanh(w0_times_q - b0[n]); + derivative_scale = w1[n] * (1.0f - x1 * x1); + energy += w1[n] * x1; + } + derivative_scale = __shfl_sync(0xffffffff, derivative_scale, 0); + for (int k = 0; k < values_per_lane; ++k) { + const int d = lane + k * warp_size; + if (d < dim) Fp[k] += derivative_scale * w0[n * dim + d]; + } + } + + if (lane == 0) g_pe[atom] = energy - annmb.b[0]; + for (int k = 0; k < values_per_lane; ++k) { + const int d = lane + k * warp_size; + if (d < dim) g_Fp[atom + d * N] = Fp[k] * g_q_scaler[d]; + } +} + +Spin_Data& NEP_Spin_Model::magnetic(Dataset& dataset) { + if (!response_set.empty() && &dataset == &response_set[dataset.device_id]) + return *response_data[dataset.device_id]; + return magnetic_data.get(dataset); +} +void NEP_Spin_Model::find_force( + Spin_Parameters& para, + const float* parameters, + std::vector& dataset, + bool calculate_q_scaler, + int device_in_this_iter) +{ + for (int device_id = 0; device_id < device_in_this_iter; ++device_id) { + CHECK(gpuSetDevice(device_id)); + nep_data[device_id].parameters.copy_from_host( + parameters + device_id * para.number_of_variables); + bind_nep_parameters( + paramb.num_types, nep_data[device_id].parameters.data(), annmb[device_id]); + } + + for (int device_id = 0; device_id < device_in_this_iter; ++device_id) { + CHECK(gpuSetDevice(device_id)); + neighbor[device_id].prepare(para, dataset[device_id], device_id); + + compute_nep_descriptors( + paramb, annmb[device_id].c, dataset[device_id], neighbor[device_id], + nep_data[device_id], compiled_kernel_.get()); + + find_additional_descriptors(para, dataset[device_id], device_id); + if (para.prediction == 1 && para.output_descriptor >= 1) { + output_nep_descriptors( + dataset[device_id], annmb[device_id].dim, para.output_descriptor, + para.q_scaler_cpu, nep_data[device_id].descriptors); + } + + if (calculate_q_scaler) { + find_max_min<<>>( + dataset[device_id].N, nep_data[device_id].descriptors.data(), + para.q_scaler_gpu[device_id].data(), para.q_scaler_max[device_id].data(), + para.q_scaler_min[device_id].data(), para.q_scaler_square_sum[device_id].data(), + para.q_scaler_count[device_id].data()); + GPU_CHECK_KERNEL + } + + zero_nep_outputs(dataset[device_id]); + + initialize_additional_outputs(dataset[device_id], device_id); + auto& data = dataset[device_id]; + auto& work = nep_data[device_id]; + if (compiled_kernel_) { + compiled_kernel_->launch_ann(data.N, data.type.data(), work.descriptors.data(), + para.q_scaler_gpu[device_id].data(), work.parameters.data(), data.energy.data(), work.Fp.data()); + } else { + apply_ann_one_layer_warp<<<(data.N + 3) / 4, 128>>>(data.N, + annmb[device_id], data.type.data(), work.descriptors.data(), + para.q_scaler_gpu[device_id].data(), data.energy.data(), work.Fp.data()); + GPU_CHECK_KERNEL + } + compute_nep_forces( + paramb, annmb[device_id].c, dataset[device_id], neighbor[device_id], + nep_data[device_id], compiled_kernel_.get()); + + if (zbl.enabled) { + add_nep_zbl(zbl, dataset[device_id], neighbor[device_id]); + } + find_additional_force(para, dataset[device_id], device_id); + } +} + + +NEP_Spin_Model::NEP_Spin_Model(const ParameterInput& input) : model_parameters(new Spin_Parameters(input)) {} + +int NEP_Spin_Model::prepare_data() +{ + auto& para = *model_parameters; + Spin_Reader reader(para, energy_difference, magnetic_data); + training.reset(new NEP_Training(para, reader)); + int capacity = training->N; + if (para.lambda_spin_response > 0 && !para.prediction) { + std::vector frames; + std::vector labels; + reader.read_response(frames, labels); + if (frames.empty()) PRINT_INPUT_ERROR("response.xyz must not be empty."); + response_set.resize(training->device_count); + response_data.resize(training->device_count); + for (int device = 0; device < training->device_count; ++device) { + CHECK(gpuSetDevice(device)); + response_set[device].construct(para, frames, 0, frames.size(), device, -1); + response_data[device].reset(new Spin_Data); + response_data[device]->construct(para, response_set[device], labels); + capacity = std::max(capacity, response_set[device].N); + } + } + initialize(para, capacity, training->device_count); + if (!para.prediction) { + energy_loss.initialize(para); + const int size = (para.num_types + 1) * para.population_size; + fitness_mforce.assign(size, 0.0f); + fitness_tau.assign(size, 0.0f); + fitness_response.assign(size, 0.0f); + std::string columns = + " rmse_energy_train rmse_force_train rmse_virial_train rmse_mforce_train rmse_tau_train" + " rmse_energy_test rmse_force_test rmse_virial_test rmse_mforce_test rmse_tau_test"; + if (para.split_mforce_loss) { + columns += " rmse_m_parallel_train rmse_m_perp_train rmse_m_parallel_test rmse_m_perp_test"; + } + training->open_loss_file(para, columns.c_str(), para.has_ediff_combinations); + } + return training->num_batches; +} + +void NEP_Spin_Model::prepare_training() +{ + auto& para = *model_parameters; + if (para.prediction || para.spin_restart || para.import_q_scaler) return; + // A fixed reference descriptor model makes scaling independent of population and seed. + std::mt19937 reference_rng(12345678); + std::vector mu(para.number_of_variables), sigma(para.number_of_variables); + snes_spin::initialize_search(para, reference_rng, mu, sigma); + // Scale radial coefficients only: constant/scaled projection matrices would + // change the relative scaling of the different magnetic contraction orders. + const int radial_end = para.number_of_variables - para.number_of_variables_spin_projection; + for (int n = para.number_of_variables_ann; n < radial_end; ++n) + mu[n] *= para.initial_para; + printf("Spin scaler reference: initial_para = %g\n", para.initial_para); + std::vector parameters; + for (int device = 0; device < training->device_count; ++device) + parameters.insert(parameters.end(), mu.begin(), mu.end()); + for (int batch = 0; batch < training->num_batches; ++batch) + find_force(para, parameters.data(), training->train_set[batch], true, training->device_count); + fitness_spin::finalize_q_scaler(para, training->device_count); +} + +void NEP_Spin_Model::initialize_parameters(std::mt19937& rng, std::vector& mu, std::vector& sigma) +{ + auto& para = *model_parameters; + if (!read_spin_restart(para, mu, sigma)) + snes_spin::initialize_search(para, rng, mu, sigma); +} +void NEP_Spin_Model::parameter_groups(std::vector& groups) +{ + auto& para = *model_parameters; + find_nep_type_of_variable(para, groups, 1, 1); + const int offset = para.number_of_variables - para.number_of_variables_descriptor_spin - + para.number_of_variables_spin_projection; + snes_spin::assign_variable_types(para, offset, groups); +} +void NEP_Spin_Model::read_model(float* parameters) { read_spin_model(*model_parameters, parameters); } +void NEP_Spin_Model::write_restart(const char* filename, const std::vector& mu, const std::vector& sigma) +{ + write_nep_restart(filename, *model_parameters, mu, sigma); +} +float NEP_Spin_Model::response_loss(int device) +{ + if (response_set.empty()) return 0.0f; + fitness_spin::ResponseLoss response; + response.append(device, response_set[device], *response_data[device]); + return response.value(); +} +void NEP_Spin_Model::evaluate(int batch, const float* population) +{ + auto& para = *model_parameters; + const int devices = training->device_count; + for (int first = 0; first < para.population_size; first += devices) { + const int count = std::min(devices, para.population_size - first); + const float* parameters = population + first * para.number_of_variables; + find_force(para, parameters, training->train_set[batch], false, count); + for (int device = 0; device < count; ++device) { + Dataset& data = training->train_set[batch][device]; + energy_loss.evaluate(para, data, energy_difference, batch, first + device, device); + auto m = para.split_mforce_loss + ? magnetic(data).get_rmse_mforce_parallel(para, data, true, device) + : magnetic(data).get_rmse_mforce(para, data, true, device); + std::vector perpendicular; + if (para.split_mforce_loss) + perpendicular = magnetic(data).get_rmse_mforce_perp(para, data, true, device); + auto t = magnetic(data).get_rmse_tau(para, data, true, device); + for (int type = 0; type <= para.num_types; ++type) { + const int index = first + device + type * para.population_size; + fitness_mforce[index] = para.split_mforce_loss + ? para.lambda_m_parallel * m[type] + para.lambda_m_perp * perpendicular[type] + : para.lambda_m * m[type]; + fitness_tau[index] = para.lambda_tau * t[type]; + } + } + if (!response_set.empty()) { + find_force(para, parameters, response_set, false, count); + for (int device = 0; device < count; ++device) { + const float loss = para.lambda_spin_response * response_loss(device); + for (int type = 0; type <= para.num_types; ++type) + fitness_response[first + device + type * para.population_size] = loss; + } + } + } +} +void NEP_Spin_Model::accumulate_fitness(float* total) +{ + auto& para = *model_parameters; + energy_loss.accumulate_fitness(para, total); + for (int i = 0; i < fitness_mforce.size(); ++i) + total[i] = total[i] + fitness_mforce[i] + fitness_tau[i] + fitness_response[i]; + energy_loss.accumulate_energy_difference(para, total); +} +void NEP_Spin_Model::print_training_header() +{ + fitness_spin::print_loss_header(model_parameters->split_mforce_loss); +} +void NEP_Spin_Model::write_magnetic_predictions( + const char* prefix, const std::vector>& structures) +{ + const std::string filename = std::string("mforce_") + prefix + ".out"; + FILE* file = my_fopen(filename.c_str(), "w"); + for (const auto& entry : structures) { + Dataset& data = *entry.first; + auto& spin = magnetic(data); + const int nc = entry.second; + if (!model_parameters->prediction && !spin.labels[nc].has_mforce) continue; + for (int a = 0; a < data.Na_cpu[nc]; ++a) { + const int atom = data.Na_sum_cpu[nc] + a; + fprintf(file, "%g %g %g %g %g %g\n", + spin.mforce_cpu[atom], spin.mforce_cpu[data.N + atom], spin.mforce_cpu[2 * data.N + atom], + spin.mforce_ref_cpu[atom], spin.mforce_ref_cpu[data.N + atom], spin.mforce_ref_cpu[2 * data.N + atom]); + } + } + fclose(file); +} +void NEP_Spin_Model::report_error(const TrainingReport& report) +{ + auto& para = *model_parameters; + find_force(para, report.parameters, training->train_set[report.batch], false, 1); + Dataset& data = training->train_set[report.batch][0]; + auto train = energy_loss.get_error(para, data, energy_difference, true, report.batch); + const float mt = magnetic(data).get_rmse_mforce(para, data, false, 0).back(); + const float tt = magnetic(data).get_rmse_tau(para, data, false, 0).back(); + float mp_train = 0, mt_train = 0, mp_test = 0, mt_test = 0; + if (para.split_mforce_loss) { + mp_train = magnetic(data).get_rmse_mforce_parallel(para, data, false, 0).back(); + mt_train = magnetic(data).get_rmse_mforce_perp(para, data, false, 0).back(); + } + report.parameters[para.number_of_variables_ann - 1] += train.energy_shift; + NEP_Energy_Error test; + float mv = 0, tv = 0; + if (training->has_test_set) { + find_force(para, report.parameters, training->test_set, false, 1); + Dataset& data = training->test_set[0]; + test = energy_loss.get_error(para, data, energy_difference, false, 0); + mv = magnetic(data).get_rmse_mforce(para, data, false, 0).back(); + tv = magnetic(data).get_rmse_tau(para, data, false, 0).back(); + if (para.split_mforce_loss) { + mp_test = magnetic(data).get_rmse_mforce_parallel(para, data, false, 0).back(); + mt_test = magnetic(data).get_rmse_mforce_perp(para, data, false, 0).back(); + } + } + int max_radial = training->max_NN_radial; + for (auto& batch : training->train_set) max_radial = std::max(max_radial, magnetic(batch[0]).max_NN_spin); + if (training->has_test_set) max_radial = std::max(max_radial, magnetic(training->test_set[0]).max_NN_spin); + int max_angular = training->max_NN_angular; + if (!response_set.empty()) { + max_radial = std::max(max_radial, std::max(response_set[0].max_NN_radial, response_data[0]->max_NN_spin)); + max_angular = std::max(max_angular, response_set[0].max_NN_angular); + } + for (const auto& filename : {std::string("nep.txt"), report.checkpoint}) { + if (filename.empty()) continue; + FILE* file = my_fopen(filename.c_str(), "w"); + write_spin_model(file, para, report.parameters, max_radial, max_angular); + fclose(file); + } + for (FILE* file : {stdout, training->fid_loss_out}) { + fprintf(file, "%d %.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f", + report.generation + 1, report.total, report.l1, report.l2, train.energy, train.force, + train.virial, mt, tt, test.energy, test.force, test.virial, mv, tv); + if (para.split_mforce_loss) + fprintf(file, " %.8e %.8e %.8e %.8e", mp_train, mt_train, mp_test, mt_test); + if (para.has_ediff_combinations) fprintf(file, " %.5f %.5f", train.ediff, test.ediff); + fprintf(file, "\n"); fflush(file); + } + if (training->has_test_set) { + Dataset& data = training->test_set[0]; + copy_nep_energy_predictions(data, para.energy_reference); + magnetic(data).mforce.copy_to_host(magnetic(data).mforce_cpu.data()); + std::vector> structures; + for (int nc = 0; nc < data.Nc; ++nc) structures.emplace_back(&data, nc); + write_nep_energy_predictions("test", structures); + write_magnetic_predictions("test", structures); + } +} +void NEP_Spin_Model::predict(float* parameters) +{ + auto& para = *model_parameters; + for (int batch = 0; batch < training->num_batches; ++batch) { + find_force(para, parameters, training->train_set[batch], false, 1); + Dataset& data = training->train_set[batch][0]; + copy_nep_energy_predictions(data, para.energy_reference); + magnetic(data).mforce.copy_to_host(magnetic(data).mforce_cpu.data()); + } + std::vector> structures; + training->get_prediction_order(structures); + write_nep_energy_predictions("train", structures); + write_magnetic_predictions("train", structures); +} diff --git a/src/main_nep/nep_spin/nep_spin.cuh b/src/main_nep/nep_spin/nep_spin.cuh new file mode 100644 index 000000000..be9491ff2 --- /dev/null +++ b/src/main_nep/nep_spin/nep_spin.cuh @@ -0,0 +1,130 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once +#include "main_nep/dataset.cuh" +#include "main_nep/potential.cuh" +#include "main_nep/common/nep_parameters.cuh" +#include "main_nep/common/nep_training.cuh" +#include "main_nep/common/nep_batch_data.cuh" +#include "main_nep/common/energy_difference.cuh" +#include "main_nep/common/nep_compile.cuh" +#include "main_nep/common/nep_evaluate.cuh" +#include "main_nep/common/nep_common.cuh" +#include + +#include "spin_data.cuh" +class NEP_Spin_Model : public Potential { +public: + explicit NEP_Spin_Model(const ParameterInput&); + int prepare_data() override; + void prepare_training() override; + void evaluate(int, const float*) override; + void accumulate_fitness(float*) override; + void print_training_header() override; + void report_error(const TrainingReport&) override; + void predict(float*) override; + Parameters& get_parameters() override { return *model_parameters; } + void initialize_parameters(std::mt19937&, std::vector&, std::vector&) override; + void parameter_groups(std::vector&) override; + void read_model(float*) override; + void write_restart(const char*, const std::vector&, const std::vector&) override; + struct Spin_Polynomial_Layout { + int channels = 0; + int pair_count = 0; + int density_stride = 38; + int moment_count = 0; + int local_s2 = -1; + int edge_l0_dot = -1; + int edge_l0_neighbor_s2 = -1; + int edge_l2_pair = -1; + int center_l2_environment = -1; + int edge_l0_dot2 = -1; + int density_l0_self = -1; + int density_l1_longitudinal_self = -1; + int density_l1_axial_self = -1; + int density_l1_stf_self = -1; + int density_l1_product_self = -1; + int density_l2_product_self = -1; + int density_l0_dot_response = -1; + int correlation_same_edge = -1; + int correlation_distinct_neighbor = -1; + int correlation_distinct_l1 = -1; + int correlation_distinct_l2 = -1; + int angular_l1_moment_offset = -1; + int angular_l2_moment_offset = -1; + int coupling_l11_axial = -1; + int edge_l11_axial = -1; + int coupling_l22_axial = -1; + int edge_l22_axial = -1; + int edge_l0_moment_gate = -1; + int coupling_l11_dot_response = -1; + int coupling_l111_p_m_x = -1; + int coupling_l22_dot_response = -1; + int coupling_l111_p_qs_x = -1; + int coupling_l112_edge_response = -1; + int coupling_l111_bulk = -1; + int descriptor_dim = 0; + }; + +private: + std::unique_ptr model_parameters; + std::unique_ptr training; + NEP_Batch_Data magnetic_data; + std::vector response_set; + std::vector> response_data; + std::vector fitness_mforce, fitness_tau, fitness_response; + NEP_Energy_Loss energy_loss; + EnergyDifference energy_difference; + NEP_Neighbor neighbor[16]; + NEP_Descriptor_Parameters paramb; + NEP_ANN annmb[16]; + NEP_Data nep_data[16]; + NEP_ZBL zbl; + std::unique_ptr compiled_kernel_; + void initialize(Spin_Parameters&, int, int); + void initialize_model(const Spin_Parameters&); + void initialize_device(const Spin_Parameters&, int, int); + void initialize_compiled_kernel(const Spin_Parameters&); + void initialize_spin(Spin_Parameters&, int, int); + void find_force(Spin_Parameters&, const float*, std::vector&, bool, int); + Spin_Data& magnetic(Dataset& dataset); + void find_additional_descriptors(Spin_Parameters&, Dataset&, int); + void initialize_additional_outputs(Dataset&, int); + void find_additional_force(Spin_Parameters&, Dataset&, int); + float response_loss(int); + void write_magnetic_predictions(const char*, const std::vector>&); + struct Spin_Workspace { + GPU_Vector spin_dof_type_active; + GPU_Vector spin_env_type_active; + GPU_Vector spin_cutoff_pair; + GPU_Vector spin3_moments; + GPU_Vector force; + GPU_Vector mforce; + GPU_Vector virial; + }; + int spin_compress_ = 0; + int spin_basis_size_ = 0; + int spin_l_max_ = 0; + int spin_order_ = 0; + int spin_soc_ = 0; + int spin_projection_offset_ = 0; + int struct_dim_ = 0; + int spin_coefficient_offset_ = 0; + int num_types_ = 0; + float spin_cutoff_ = 0.0f; + Spin_Polynomial_Layout polynomial_layout_; + Spin_Workspace spin_data_[16]; +}; diff --git a/src/main_nep/nep_spin/rotation_response.cuh b/src/main_nep/nep_spin/rotation_response.cuh new file mode 100644 index 000000000..ea6814623 --- /dev/null +++ b/src/main_nep/nep_spin/rotation_response.cuh @@ -0,0 +1,52 @@ +/* + This file is part of GPUMD. + SPDX-License-Identifier: LGPL-3.0-or-later +*/ + +#pragma once + +#include +#include +#include + +namespace fitness_spin { + +// A local displacement for differentiating a sampled spin path. The sphere log +// keeps fixed-length rotations tangent, while the separate radial difference +// retains genuine changes in the converged moment magnitude. Neighbouring +// samples must resolve the path (angular separation strictly below pi). +inline bool rotation_displacement( + const std::array& center, + const std::array& neighbour, + std::array& displacement) +{ + double r2 = 0.0, q2 = 0.0; + for (int d = 0; d < 3; ++d) { + r2 += center[d] * center[d]; + q2 += neighbour[d] * neighbour[d]; + } + const double r = std::sqrt(r2), q = std::sqrt(q2); + // At zero moment there is no sphere tangent; retain the Cartesian limit. + if (r <= 1.0e-12 || q <= 1.0e-12) { + for (int d = 0; d < 3; ++d) displacement[d] = neighbour[d] - center[d]; + return true; + } + double cosine = 0.0; + for (int d = 0; d < 3; ++d) cosine += (center[d] / r) * (neighbour[d] / q); + cosine = std::max(-1.0, std::min(1.0, cosine)); + std::array tangent; + double sine2 = 0.0; + for (int d = 0; d < 3; ++d) { + tangent[d] = neighbour[d] / q - cosine * center[d] / r; + sine2 += tangent[d] * tangent[d]; + } + const double sine = std::sqrt(sine2); + if (cosine < 0.0 && sine < 1.0e-10) return false; + const double factor = sine > 1.0e-12 ? std::atan2(sine, cosine) / sine : 1.0; + for (int d = 0; d < 3; ++d) { + displacement[d] = r * factor * tangent[d] + (q - r) * center[d] / r; + } + return true; +} + +} // namespace fitness_spin diff --git a/src/main_nep/nep_spin/spin_data.cu b/src/main_nep/nep_spin/spin_data.cu new file mode 100644 index 000000000..a6ce125fa --- /dev/null +++ b/src/main_nep/nep_spin/spin_data.cu @@ -0,0 +1,291 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#include "spin_data.cuh" +#include "main_nep/mic.cuh" +#include "utilities/error.cuh" +#include +#include +#include +// Both passes traverse the same periodic geometry; structural neighbors belong to Dataset. +template +static __global__ void gpu_find_spin_neighbors( + const int N, const int* Na, const int* Na_sum, const float rc_spin, + const float* __restrict__ g_box, const float* __restrict__ g_box_original, + const int* __restrict__ g_num_cell, const float* x, const float* y, const float* z, + const int plane_size, int* NN_spin, int* NL_spin, double* r12_spin) +{ + const int N1 = Na_sum[blockIdx.x]; + const int N2 = N1 + Na[blockIdx.x]; + const float* box = g_box + 18 * blockIdx.x; + const float* box_original = g_box_original + 9 * blockIdx.x; + const int* num_cell = g_num_cell + 3 * blockIdx.x; + for (int n1 = N1 + threadIdx.x; n1 < N2; n1 += blockDim.x) { + const float x1 = x[n1], y1 = y[n1], z1 = z[n1]; + int count = 0; + for (int n2 = N1; n2 < N2; ++n2) { + for (int ia = 0; ia < num_cell[0]; ++ia) { + for (int ib = 0; ib < num_cell[1]; ++ib) { + for (int ic = 0; ic < num_cell[2]; ++ic) { + if (ia == 0 && ib == 0 && ic == 0 && n1 == n2) continue; + float dx = box_original[0] * ia + box_original[1] * ib + box_original[2] * ic; + float dy = box_original[3] * ia + box_original[4] * ib + box_original[5] * ic; + float dz = box_original[6] * ia + box_original[7] * ib + box_original[8] * ic; + float x12 = x[n2] + dx - x1; + float y12 = y[n2] + dy - y1; + float z12 = z[n2] + dz - z1; + dev_apply_mic(box, x12, y12, z12); + if (x12 * x12 + y12 * y12 + z12 * z12 < rc_spin * rc_spin) { + if (Store) { + const int index = n1 + N * count; + NL_spin[index] = n2; + r12_spin[index] = x12; + r12_spin[plane_size + index] = y12; + r12_spin[2 * plane_size + index] = z12; + } + ++count; + } + } + } + } + } + NN_spin[n1] = count; + } +} + +void Spin_Data::construct(Spin_Parameters& para, Dataset& dataset, const std::vector& input) { + const int N=dataset.N, Nc=dataset.Nc; + labels.reserve(Nc); + std::vector position(3*N), moments(3*N); + mforce_ref_cpu.resize(3*N); mforce_cpu.resize(3*N); has_mforce_cpu.resize(Nc); + for (int n=0;n<<>>(N,dataset.Na.data(),dataset.Na_sum.data(), + para.spin_cutoff,dataset.box.data(),dataset.box_original.data(),dataset.num_cell.data(), + dataset.r.data(),dataset.r.data()+N,dataset.r.data()+2*N,0,NN_spin.data(),nullptr,nullptr); + GPU_CHECK_KERNEL + std::vector counts(N); NN_spin.copy_to_host(counts.data()); + for (int count:counts) max_NN_spin=std::max(max_NN_spin,count); + const long long slots=static_cast(N)*max_NN_spin; + if (slots>std::numeric_limits::max()) PRINT_INPUT_ERROR("Spin neighbor slot count exceeds the supported int range."); + NL_spin.resize(slots); r12_spin.resize(3*slots); + gpu_find_spin_neighbors<<>>(N,dataset.Na.data(),dataset.Na_sum.data(), + para.spin_cutoff,dataset.box.data(),dataset.box_original.data(),dataset.num_cell.data(), + dataset.r.data(),dataset.r.data()+N,dataset.r.data()+2*N, + static_cast(slots),NN_spin.data(),NL_spin.data(),r12_spin.data()); + GPU_CHECK_KERNEL +} +enum class MagneticError { Cartesian, Torque, Parallel, Perpendicular }; + +template +static __global__ void gpu_sum_mforce_error( + const int N, + const int* Na, + const int* Na_sum, + const int* type, + const int* active_type, + const int* has_mforce, + const double* spin, + const float* mforce, + const float* mforce_ref, + float* error) +{ + const int configuration = blockIdx.x; + const int begin = Na_sum[configuration]; + const int end = begin + Na[configuration]; + extern __shared__ float partial[]; + float sum = 0.0f; + if (has_mforce[configuration]) { + for (int atom = begin + threadIdx.x; atom < end; atom += blockDim.x) { + if (!active_type[type[atom]]) { + continue; + } + float predicted[3] = { + mforce[atom], + mforce[N + atom], + mforce[2 * N + atom]}; + float reference[3] = { + mforce_ref[atom], + mforce_ref[N + atom], + mforce_ref[2 * N + atom]}; + const double sx = spin[atom]; + const double sy = spin[N + atom]; + const double sz = spin[2 * N + atom]; + const double spin2 = sx * sx + sy * sy + sz * sz; + if (Channel == MagneticError::Torque && spin2 <= 1.0e-20) { + continue; + } + if (Channel == MagneticError::Torque) { + const float predicted_tau[3] = { + static_cast(sy * predicted[2] - sz * predicted[1]), + static_cast(sz * predicted[0] - sx * predicted[2]), + static_cast(sx * predicted[1] - sy * predicted[0])}; + const float reference_tau[3] = { + static_cast(sy * reference[2] - sz * reference[1]), + static_cast(sz * reference[0] - sx * reference[2]), + static_cast(sx * reference[1] - sy * reference[0])}; + for (int component = 0; component < 3; ++component) { + const float difference = + predicted_tau[component] - reference_tau[component]; + sum += difference * difference; + } + } else if (Channel == MagneticError::Cartesian) { + for (int component = 0; component < 3; ++component) { + const float difference = predicted[component] - reference[component]; + sum += difference * difference; + } + } else { + const double dx = static_cast(predicted[0]) - reference[0]; + const double dy = static_cast(predicted[1]) - reference[1]; + const double dz = static_cast(predicted[2]) - reference[2]; + // Normalize after scaling: tiny nonzero spins still define an axis. + const double scale = fmax(fabs(sx), fmax(fabs(sy), fabs(sz))); + double parallel, perpendicular; + if (scale == 0.0) { + // No preferred axis at zero spin: isotropic directional average. + const double norm2 = dx * dx + dy * dy + dz * dz; + parallel = norm2 / 3.0; + perpendicular = 2.0 * norm2 / 3.0; + } else { + double ux = sx / scale, uy = sy / scale, uz = sz / scale; + const double norm = sqrt(ux * ux + uy * uy + uz * uz); + ux /= norm; uy /= norm; uz /= norm; + const double projection = dx * ux + dy * uy + dz * uz; + parallel = projection * projection; + const double tx = dx - projection * ux; + const double ty = dy - projection * uy; + const double tz = dz - projection * uz; + perpendicular = tx * tx + ty * ty + tz * tz; + } + sum += static_cast(Channel == MagneticError::Parallel ? parallel : perpendicular); + } + } + } + partial[threadIdx.x] = sum; + __syncthreads(); + for (int offset = blockDim.x / 2; offset > 0; offset /= 2) { + if (threadIdx.x < offset) { + partial[threadIdx.x] += partial[threadIdx.x + offset]; + } + __syncthreads(); + } + if (threadIdx.x == 0) { + error[configuration] = partial[0]; + } +} + +template +static std::vector get_rmse_spin_impl( + Spin_Data& spin_data, Dataset& dataset, + Spin_Parameters& para, + const bool use_weight, + int device_id) +{ + CHECK(gpuSetDevice(device_id)); + const int block_size = 256; + gpu_sum_mforce_error + <<>>( + dataset.N, + dataset.Na.data(), + dataset.Na_sum.data(), + dataset.type.data(), + spin_data.spin_dof_type_active_gpu.data(), + spin_data.has_mforce_gpu.data(), + spin_data.spin.data(), + spin_data.mforce.data(), + spin_data.mforce_ref_gpu.data(), + dataset.error_gpu.data()); + GPU_CHECK_KERNEL + dataset.error_gpu.copy_to_host(dataset.error_cpu.data()); + + std::vector rmse_array(para.num_types + 1, 0.0f); + std::vector count_array(para.num_types + 1, 0); + for (int configuration = 0; configuration < dataset.Nc; ++configuration) { + if (!spin_data.has_mforce_cpu[configuration]) { + continue; + } + int active_count = 0; + const auto& structure = dataset.structures[configuration]; + const auto& label = spin_data.labels[configuration]; + for (int atom = 0; atom < structure.num_atom; ++atom) { + if (!para.spin_dof_type_active[structure.type[atom]]) { + continue; + } + const double spin2 = + label.sx[atom] * label.sx[atom] + + label.sy[atom] * label.sy[atom] + + label.sz[atom] * label.sz[atom]; + if (Channel != MagneticError::Torque || spin2 > 1.0e-20) { + ++active_count; + } + } + const float weighted_error = + use_weight + ? dataset.weight_cpu[configuration] * dataset.weight_cpu[configuration] * + dataset.error_cpu[configuration] + : dataset.error_cpu[configuration]; + for (int type = 0; type <= para.num_types; ++type) { + if (dataset.has_type[type * dataset.Nc + configuration]) { + rmse_array[type] += weighted_error; + count_array[type] += active_count; + } + } + } + for (int type = 0; type <= para.num_types; ++type) { + if (count_array[type] > 0) { + const int degrees_of_freedom = + Channel == MagneticError::Cartesian ? 3 : + (Channel == MagneticError::Parallel ? 1 : 2); + rmse_array[type] = sqrt( + rmse_array[type] / (degrees_of_freedom * count_array[type])); + } + } + return rmse_array; +} + +std::vector +Spin_Data::get_rmse_mforce(Spin_Parameters& para, Dataset& dataset, const bool use_weight, int device_id) +{ + return get_rmse_spin_impl(*this, dataset, para, use_weight, device_id); +} + +std::vector +Spin_Data::get_rmse_tau(Spin_Parameters& para, Dataset& dataset, const bool use_weight, int device_id) +{ + return get_rmse_spin_impl(*this, dataset, para, use_weight, device_id); +} + +std::vector +Spin_Data::get_rmse_mforce_parallel(Spin_Parameters& para, Dataset& dataset, const bool use_weight, int device_id) +{ + return get_rmse_spin_impl(*this, dataset, para, use_weight, device_id); +} + +std::vector +Spin_Data::get_rmse_mforce_perp(Spin_Parameters& para, Dataset& dataset, const bool use_weight, int device_id) +{ + return get_rmse_spin_impl(*this, dataset, para, use_weight, device_id); +} diff --git a/src/main_nep/nep_spin/spin_data.cuh b/src/main_nep/nep_spin/spin_data.cuh new file mode 100644 index 000000000..83921803b --- /dev/null +++ b/src/main_nep/nep_spin/spin_data.cuh @@ -0,0 +1,59 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#pragma once +#include "spin_parameters.cuh" +#include "main_nep/dataset.cuh" +#include "main_nep/common/nep_energy_reader.cuh" +#include "main_nep/common/nep_batch_data.cuh" +#include +struct Spin_Labels { + int has_mforce = 0, has_spin_response_metadata = 0, has_spin_response = 0; + double spin_response_coordinate = 0.0; + std::string spin_response_probe, spin_response_group; + std::vector sx, sy, sz, mfx, mfy, mfz; + std::vector spin_tangent_x, spin_tangent_y, spin_tangent_z; +}; + +struct Spin_Frame { + const Structure& geometry; + Spin_Labels& label; +}; +struct Spin_Data { + int max_NN_spin = 0; + std::vector labels; + GPU_Vector r_spin, spin, r12_spin; + GPU_Vector NN_spin, NL_spin, has_mforce_gpu, spin_dof_type_active_gpu; + GPU_Vector mforce, mforce_ref_gpu; + std::vector mforce_cpu, mforce_ref_cpu; + std::vector has_mforce_cpu; + void construct(Spin_Parameters&, Dataset&, const std::vector&); + std::vector get_rmse_mforce(Spin_Parameters&, Dataset&, bool, int); + std::vector get_rmse_mforce_parallel(Spin_Parameters&, Dataset&, bool, int); + std::vector get_rmse_mforce_perp(Spin_Parameters&, Dataset&, bool, int); + std::vector get_rmse_tau(Spin_Parameters&, Dataset&, bool, int); +}; +class Spin_Reader : public NEP_Energy_Reader { +public: + Spin_Reader(Spin_Parameters& p, EnergyDifference& e, NEP_Batch_Data& d) + : NEP_Energy_Reader(p,e), parameters(p), data(d) {} + void prepare_train(std::vector&, int, int&, std::vector&) override; + void prepare_test(const std::vector&, bool) override; + void prepare_dataset(Dataset&) override; + const char* energy_difference_conflict(const Structure&, const Structure&) const override; + void read_response(std::vector&, std::vector&); +protected: + void begin_reading() override { labels.clear(); } + void read_structure(const XYZ_Record&, Structure&) override; + float geometry_cutoff() const override; +private: + Spin_Parameters& parameters; + NEP_Batch_Data& data; + std::vector labels; + std::set train_groups, test_groups, test_frames; +}; diff --git a/src/main_nep/nep_spin/spin_evaluate.cu b/src/main_nep/nep_spin/spin_evaluate.cu new file mode 100644 index 000000000..56bd29e35 --- /dev/null +++ b/src/main_nep/nep_spin/spin_evaluate.cu @@ -0,0 +1,518 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#include "nep_spin.cuh" +#include "main_nep/dataset.cuh" +#include "spin_parameters.cuh" +#include "model/box.cuh" +#include "utilities/gpu_macro.cuh" +#include + +namespace { + +using SimulationBox = Box; + +#include "force/nep_spin/nep_spin3_common.cuh" + +enum class SpinVirialMode : int { + disabled, + center_owned, + neighbor_owned, + center_and_neighbor_float_sink, +}; + +__device__ __forceinline__ void atomic_add_per_atom_virial_double( + const int atom_stride, + const int atom, + const float x12, + const float y12, + const float z12, + const float fx, + const float fy, + const float fz, + double* virial) +{ + atomicAdd(&virial[atom], -static_cast(x12 * fx)); + atomicAdd(&virial[atom_stride + atom], -static_cast(y12 * fy)); + atomicAdd(&virial[2 * atom_stride + atom], -static_cast(z12 * fz)); + atomicAdd(&virial[3 * atom_stride + atom], -static_cast(x12 * fy)); + atomicAdd(&virial[4 * atom_stride + atom], -static_cast(x12 * fz)); + atomicAdd(&virial[5 * atom_stride + atom], -static_cast(y12 * fz)); + atomicAdd(&virial[6 * atom_stride + atom], -static_cast(y12 * fx)); + atomicAdd(&virial[7 * atom_stride + atom], -static_cast(z12 * fx)); + atomicAdd(&virial[8 * atom_stride + atom], -static_cast(z12 * fy)); +} + +__device__ __forceinline__ void atomic_add_per_atom_virial_float( + const int atom_stride, + const int atom, + const float x12, + const float y12, + const float z12, + const float fx, + const float fy, + const float fz, + float* virial) +{ + atomicAdd(&virial[atom], -x12 * fx); + atomicAdd(&virial[atom_stride + atom], -y12 * fy); + atomicAdd(&virial[2 * atom_stride + atom], -z12 * fz); + atomicAdd(&virial[3 * atom_stride + atom], -x12 * fy); + atomicAdd(&virial[4 * atom_stride + atom], -x12 * fz); + atomicAdd(&virial[5 * atom_stride + atom], -y12 * fz); + atomicAdd(&virial[6 * atom_stride + atom], -y12 * fx); + atomicAdd(&virial[7 * atom_stride + atom], -z12 * fx); + atomicAdd(&virial[8 * atom_stride + atom], -z12 * fy); +} + +__device__ __forceinline__ void atomic_add_spin_transfer_float( + int, int, float, float, float, const float*, float*) +{ +} + +__global__ void mask_inactive_spin_mforce_training( + const int atom_count, + const int atom_stride, + const int* __restrict__ types, + const int* __restrict__ spin_dof_type_active, + double* __restrict__ mforce) +{ + const int atom = blockIdx.x * blockDim.x + threadIdx.x; + if (atom < atom_count && spin_dof_type_active[types[atom]] == 0) { + mforce[atom] = 0.0; + mforce[atom_stride + atom] = 0.0; + mforce[2 * atom_stride + atom] = 0.0; + } +} + +using SpinPolynomialLayout = NEP_Spin_Model::Spin_Polynomial_Layout; + +template +__device__ __forceinline__ void evaluate_spin3_edge_weights_b9_f32( + const float spin_cutoff, + const float dist, + const int num_types, + const int type_pair, + const float* descriptor_coefficients, + const int spin_coefficient_offset, + float* weights, + float* weight_derivatives) +{ + constexpr int basis_count = 9; + constexpr float pi = 3.14159265358979323846f; + const int pair_count = num_types * num_types; + const float inverse_cutoff = 1.0f / spin_cutoff; + const float scaled_distance = dist * inverse_cutoff; + const float phase = pi * scaled_distance; + const float cutoff = 0.5f * cosf(phase) + 0.5f; + const float shifted = scaled_distance - 1.0f; + const float x = 2.0f * shifted * shifted - 1.0f; + const float dxdr = 2.0f * shifted * inverse_cutoff; + const float cutoff_derivative = + NeedDerivatives ? -0.5f * pi * sinf(phase) * inverse_cutoff : 0.0f; + float basis[basis_count] = {}; + float basis_derivative[basis_count] = {}; + basis[0] = cutoff; + basis_derivative[0] = cutoff_derivative; + const float raw1 = 0.5f * (x + 1.0f); + basis[1] = raw1 * cutoff; + basis_derivative[1] = dxdr * cutoff + raw1 * cutoff_derivative; + float t0 = 1.0f; + float t1 = x; + float u0 = 1.0f; + float u1 = 2.0f * x; + for (int n = 2; n < basis_count; ++n) { + const float t2 = 2.0f * x * t1 - t0; + const float raw = 0.5f * (t2 + 1.0f); + basis[n] = raw * cutoff; + basis_derivative[n] = + static_cast(n) * u1 * dxdr * cutoff + raw * cutoff_derivative; + const float u2 = 2.0f * x * u1 - u0; + t0 = t1; + t1 = t2; + u0 = u1; + u1 = u2; + } + for (int channel = 0; channel < C; ++channel) { + float weight = 0.0f; + float derivative = 0.0f; + for (int basis_index = 0; basis_index < basis_count; ++basis_index) { + const int index = spin_coefficient_offset + + (channel * basis_count + basis_index) * pair_count + type_pair; + weight += basis[basis_index] * descriptor_coefficients[index]; + if (NeedDerivatives) { + derivative += basis_derivative[basis_index] * descriptor_coefficients[index]; + } + } + weights[channel] = weight; + if (NeedDerivatives) { + weight_derivatives[channel] = derivative; + } + } +} + +template +__device__ __forceinline__ bool load_spin3_edge_f32( + const int atom, + const int neighbor, + const int atom_stride, + const int num_types, + const int spin_basis_size, + const float spin_cutoff, + const float* __restrict__ spin_cutoff_pair, + const SimulationBox box, + const int* types, + const double* positions, + const double* slot_r12, + const int r12_plane_size, + const int slot_index, + const double* spins, + const float* descriptor_coefficients, + const int spin_coefficient_offset, + float* rhat, + float& dist, + float* si, + float* sj, + float* weights, + float* weight_derivatives) +{ + if (slot_r12) { + const float dx = static_cast(slot_r12[slot_index]); + const float dy = static_cast(slot_r12[r12_plane_size + slot_index]); + const float dz = static_cast(slot_r12[2 * r12_plane_size + slot_index]); + dist = sqrtf(dx * dx + dy * dy + dz * dz); + if (dist > 1.0e-12f) { + const float inverse_distance = 1.0f / dist; + rhat[0] = dx * inverse_distance; + rhat[1] = dy * inverse_distance; + rhat[2] = dz * inverse_distance; + } + } else { + compute_spin_edge_geometry_f32( + atom, neighbor, atom_stride, box, positions, rhat, dist); + } + for (int component = 0; component < 3; ++component) { + si[component] = static_cast(spins[component * atom_stride + atom]); + sj[component] = static_cast(spins[component * atom_stride + neighbor]); + } + if (!(dist > 1.0e-12f && dist < spin_cutoff) || spin_basis_size != 8) { + return false; + } + const int type_pair = types[atom] * num_types + types[neighbor]; + const float resolved_spin_cutoff = + spin_cutoff_pair == nullptr ? spin_cutoff : spin_cutoff_pair[type_pair]; + if (!(dist > 1.0e-12f && dist < resolved_spin_cutoff)) { + return false; + } + evaluate_spin3_edge_weights_b9_f32( + resolved_spin_cutoff, + dist, + num_types, + type_pair, + descriptor_coefficients, + spin_coefficient_offset, + weights, + weight_derivatives); + return true; +} + +#include "force/nep_spin/nep_spin3_layout.cuh" +#include "force/nep_spin/nep_spin3_descriptor.cuh" +#include "force/nep_spin/nep_spin3_force.cuh" + +template +void launch_spin3_descriptor( + Layout layout, + int atom_count, + int struct_dim, + int num_types, + int spin_basis_size, + float spin_cutoff, + const float* spin_cutoff_pair, + const int* type, + const int* spin_dof_type_active, + const int* spin_env_type_active, + const double* position, + const double* spin, + const int* NN_spin, + const int* NL_spin, + const double* r12_spin, + int r12_plane_size, + const float* descriptor_coefficients, + int spin_coefficient_offset, + const float* projection, + float* moments, + float* descriptors) +{ + constexpr int block_size = 128; + Box box{}; + const int density_work = C * atom_count; + build_spin3_oc_density_bank + <<<(density_work + block_size - 1) / block_size, block_size>>>( + layout, + atom_count, + atom_count, + struct_dim, + num_types, + spin_basis_size, + spin_cutoff, + spin_cutoff_pair, + spin_coefficient_offset, + box, + type, + spin_dof_type_active, + spin_env_type_active, + position, + r12_spin, + r12_plane_size, + spin, + NN_spin, + NL_spin, + descriptor_coefficients, + descriptors, + moments); + contract_spin3_oc_descriptors + <<<(atom_count + block_size - 1) / block_size, block_size>>>( + layout, + atom_count, + atom_count, + struct_dim, + type, + spin_dof_type_active, + spin, + projection, + moments, + descriptors); + GPU_CHECK_KERNEL +} + +template +void launch_spin3_force( + Layout layout, + int atom_count, + int struct_dim, + int num_types, + int spin_basis_size, + float spin_cutoff, + const float* spin_cutoff_pair, + const int* type, + const int* spin_dof_type_active, + const int* spin_env_type_active, + const double* position, + const double* spin, + const int* NN_spin, + const int* NL_spin, + const double* r12_spin, + int r12_plane_size, + const float* Fp, + const float* descriptor_coefficients, + int spin_coefficient_offset, + const float* projection, + const float* moments, + double* force, + double* mforce, + double* virial) +{ + using Tile = Spin3ForceTile; + const int grid_size = + (atom_count + Tile::centers_per_block - 1) / Tile::centers_per_block; + const std::size_t shared_size = + static_cast(Tile::centers_per_block) * layout.moment_count * sizeof(float); + Box box{}; + accumulate_spin3_oc_native_forces< + C, SpinVirialMode::neighbor_owned, false, Tile::atoms_per_warp><<< + grid_size, Tile::block_size, shared_size>>>( + layout, + atom_count, + atom_count, + struct_dim, + num_types, + spin_basis_size, + spin_cutoff, + spin_cutoff_pair, + box, + type, + spin_dof_type_active, + spin_env_type_active, + position, + r12_spin, + r12_plane_size, + spin, + NN_spin, + NL_spin, + Fp, + descriptor_coefficients, + projection, + moments, + spin_coefficient_offset, + force, + mforce, + virial, + nullptr, + nullptr); + GPU_CHECK_KERNEL +} + +__global__ void add_spin_training_outputs( + int atom_count, + const double* spin_force, + const double* spin_mforce, + const double* spin_virial, + float* force, + float* mforce, + float* virial) +{ + const int atom = blockIdx.x * blockDim.x + threadIdx.x; + if (atom >= atom_count) { + return; + } + for (int component = 0; component < 3; ++component) { + const int index = component * atom_count + atom; + force[index] += static_cast(spin_force[index]); + mforce[index] = static_cast(spin_mforce[index]); + } + constexpr int source_component[6] = {0, 1, 2, 3, 5, 7}; + for (int component = 0; component < 6; ++component) { + virial[component * atom_count + atom] += static_cast( + spin_virial[source_component[component] * atom_count + atom]); + } +} + +} // namespace + +void NEP_Spin_Model::initialize_spin(Spin_Parameters& para, int N, int device_count) +{ + spin_compress_ = para.spin_compress; + spin_basis_size_ = para.spin_basis_size[0]; + spin_l_max_ = para.spin_l_max[0]; + spin_order_ = para.spin_order; + spin_soc_ = para.spin_soc; + struct_dim_ = para.dim_struct; + spin_coefficient_offset_ = + para.number_of_variables_descriptor - para.number_of_variables_descriptor_spin; + spin_coefficient_offset_ -= para.number_of_variables_spin_projection; + spin_projection_offset_ = + spin_coefficient_offset_ + para.number_of_variables_descriptor_spin; + num_types_ = para.num_types; + spin_cutoff_ = para.spin_cutoff; + + polynomial_layout_ = make_spin_polynomial_layout( + spin_compress_, spin_l_max_, spin_order_, spin_soc_); + + for (int device_id = 0; device_id < device_count; ++device_id) { + CHECK(gpuSetDevice(device_id)); + auto& data = spin_data_[device_id]; + data.spin_dof_type_active.resize(num_types_); + data.spin_env_type_active.resize(num_types_); + data.spin_dof_type_active.copy_from_host(para.spin_dof_type_active.data()); + data.spin_env_type_active.copy_from_host(para.spin_env_type_active.data()); + std::vector spin_cutoff_pair( + static_cast(num_types_) * num_types_); + for (int type_i = 0; type_i < num_types_; ++type_i) { + for (int type_j = 0; type_j < num_types_; ++type_j) { + spin_cutoff_pair[type_i * num_types_ + type_j] = + 0.5f * (para.spin_cutoff_by_type[type_i] + para.spin_cutoff_by_type[type_j]); + } + } + data.spin_cutoff_pair.resize(spin_cutoff_pair.size()); + data.spin_cutoff_pair.copy_from_host(spin_cutoff_pair.data(), spin_cutoff_pair.size()); + data.spin3_moments.resize(N * polynomial_layout_.moment_count); + data.force.resize(3 * N); + data.mforce.resize(3 * N); + data.virial.resize(9 * N); + } +} + +void NEP_Spin_Model::find_additional_descriptors( + Spin_Parameters&, Dataset& dataset, int device_id) +{ + auto& data = spin_data_[device_id]; + auto& magnetic_data = magnetic(dataset); + const int plane_size = dataset.N * magnetic_data.max_NN_spin; + const float* projection = annmb[device_id].c + spin_projection_offset_; +#define LAUNCH_SPIN3_DESCRIPTOR(C) \ + launch_spin3_descriptor( \ + polynomial_layout_, dataset.N, struct_dim_, num_types_, spin_basis_size_, \ + spin_cutoff_, data.spin_cutoff_pair.data(), dataset.type.data(), data.spin_dof_type_active.data(), \ + data.spin_env_type_active.data(), magnetic_data.r_spin.data(), magnetic_data.spin.data(), \ + magnetic_data.NN_spin.data(), magnetic_data.NL_spin.data(), magnetic_data.r12_spin.data(), \ + plane_size, annmb[device_id].c, spin_coefficient_offset_, projection, \ + data.spin3_moments.data(), nep_data[device_id].descriptors.data()) + switch (spin_compress_) { + case 1: LAUNCH_SPIN3_DESCRIPTOR(1); break; + case 2: LAUNCH_SPIN3_DESCRIPTOR(2); break; + case 3: LAUNCH_SPIN3_DESCRIPTOR(3); break; + case 4: LAUNCH_SPIN3_DESCRIPTOR(4); break; + case 5: LAUNCH_SPIN3_DESCRIPTOR(5); break; + case 6: LAUNCH_SPIN3_DESCRIPTOR(6); break; + case 7: LAUNCH_SPIN3_DESCRIPTOR(7); break; + case 8: LAUNCH_SPIN3_DESCRIPTOR(8); break; + case 9: LAUNCH_SPIN3_DESCRIPTOR(9); break; + } +#undef LAUNCH_SPIN3_DESCRIPTOR +} + +void NEP_Spin_Model::initialize_additional_outputs( + Dataset& dataset, int device_id) +{ + auto& data = spin_data_[device_id]; + auto& magnetic_data = magnetic(dataset); + data.force.fill(0.0); + data.mforce.fill(0.0); + data.virial.fill(0.0); + magnetic_data.mforce.fill(0.0f); +} + +void NEP_Spin_Model::find_additional_force( + Spin_Parameters&, Dataset& dataset, int device_id) +{ + auto& data = spin_data_[device_id]; + auto& magnetic_data = magnetic(dataset); + const int block_size = 128; + const int grid_size = (dataset.N + block_size - 1) / block_size; + const int plane_size = dataset.N * magnetic_data.max_NN_spin; + const float* projection = annmb[device_id].c + spin_projection_offset_; +#define LAUNCH_SPIN3_FORCE(C) \ + launch_spin3_force( \ + polynomial_layout_, dataset.N, struct_dim_, num_types_, spin_basis_size_, \ + spin_cutoff_, data.spin_cutoff_pair.data(), dataset.type.data(), data.spin_dof_type_active.data(), \ + data.spin_env_type_active.data(), magnetic_data.r_spin.data(), magnetic_data.spin.data(), \ + magnetic_data.NN_spin.data(), magnetic_data.NL_spin.data(), magnetic_data.r12_spin.data(), \ + plane_size, nep_data[device_id].Fp.data(), annmb[device_id].c, \ + spin_coefficient_offset_, projection, data.spin3_moments.data(), \ + data.force.data(), data.mforce.data(), \ + data.virial.data()) + switch (spin_compress_) { + case 1: LAUNCH_SPIN3_FORCE(1); break; + case 2: LAUNCH_SPIN3_FORCE(2); break; + case 3: LAUNCH_SPIN3_FORCE(3); break; + case 4: LAUNCH_SPIN3_FORCE(4); break; + case 5: LAUNCH_SPIN3_FORCE(5); break; + case 6: LAUNCH_SPIN3_FORCE(6); break; + case 7: LAUNCH_SPIN3_FORCE(7); break; + case 8: LAUNCH_SPIN3_FORCE(8); break; + case 9: LAUNCH_SPIN3_FORCE(9); break; + } +#undef LAUNCH_SPIN3_FORCE + + mask_inactive_spin_mforce_training<<>>( + dataset.N, + dataset.N, + dataset.type.data(), + data.spin_dof_type_active.data(), + data.mforce.data()); + add_spin_training_outputs<<>>( + dataset.N, + data.force.data(), + data.mforce.data(), + data.virial.data(), + dataset.force.data(), + magnetic_data.mforce.data(), + dataset.virial.data()); + GPU_CHECK_KERNEL +} diff --git a/src/main_nep/nep_spin/spin_init.cu b/src/main_nep/nep_spin/spin_init.cu new file mode 100644 index 000000000..db911ca8c --- /dev/null +++ b/src/main_nep/nep_spin/spin_init.cu @@ -0,0 +1,145 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#include "spin_init.cuh" +#include +#include +namespace snes_spin { +void initialize_search(const Spin_Parameters& para, std::mt19937& rng, + std::vector& mu, std::vector& sigma) +{ + std::normal_distribution normal(0.0f, 1.0f); + const float input_scale = + 1.0f / std::sqrt(float(para.dim + para.num_neurons1)); + const float output_scale = + 1.0f / std::sqrt(float(para.num_neurons1 + 1)); + const float descriptor_scale = 0.1f; + const float spin_noise = 0.01f; + + std::fill(mu.begin(), mu.end(), 0.0f); + std::fill(sigma.begin(), sigma.end(), para.sigma0 * descriptor_scale); + for (int type = 0; type < para.num_types; ++type) { + const int ann_offset = type * para.number_of_variables_ann_1; + for (int neuron = 0; neuron < para.num_neurons1; ++neuron) { + for (int descriptor = 0; descriptor < para.dim; ++descriptor) { + const int index = + ann_offset + neuron * para.dim + descriptor; + mu[index] = normal(rng) * input_scale; + sigma[index] = para.sigma0 * input_scale; + } + } + const int bias_offset = + ann_offset + para.num_neurons1 * para.dim; + const int output_offset = bias_offset + para.num_neurons1; + for (int neuron = 0; neuron < para.num_neurons1; ++neuron) { + mu[bias_offset + neuron] = 0.0f; + sigma[bias_offset + neuron] = para.sigma0 * input_scale; + mu[output_offset + neuron] = normal(rng) * output_scale; + sigma[output_offset + neuron] = para.sigma0 * output_scale; + } + } + const int descriptor_offset = para.number_of_variables_ann; + const int type_pairs = para.num_types * para.num_types; + const int radial_basis_count = para.basis_size_radial + 1; + const int radial_channel_count = para.n_max_radial + 1; + const int radial_count = + type_pairs * radial_channel_count * radial_basis_count; + for (int channel = 0; channel < radial_channel_count; ++channel) { + for (int basis = 0; basis < radial_basis_count; ++basis) { + for (int pair = 0; pair < type_pairs; ++pair) { + const int index = descriptor_offset + + pair * radial_channel_count * radial_basis_count + + channel * radial_basis_count + basis; + mu[index] = normal(rng) * spin_noise; + if (basis == channel % radial_basis_count) { + mu[index] += 1.0f; + } + } + } + } + const int angular_basis_count = para.basis_size_angular + 1; + const int angular_channel_count = para.n_max_angular + 1; + const int angular_offset = descriptor_offset + radial_count; + for (int channel = 0; channel < angular_channel_count; ++channel) { + for (int basis = 0; basis < angular_basis_count; ++basis) { + for (int pair = 0; pair < type_pairs; ++pair) { + const int index = angular_offset + + pair * angular_channel_count * angular_basis_count + + channel * angular_basis_count + basis; + mu[index] = normal(rng) * spin_noise; + if (basis == channel % angular_basis_count) { + mu[index] += 1.0f; + } + } + } + } + + const int structural_count = radial_count + + type_pairs * angular_channel_count * angular_basis_count; + + const int spin_offset = descriptor_offset + structural_count; + const int basis_count = para.spin_basis_size[0] + 1; + // Least-squares coefficients of x^c f_c(x) in the fixed B8 magnetic + // Chebyshev basis, sampled exactly as the Spin3 TorchNEP initializer. + static constexpr float spin3_radial_frame[9][9] = { + {1.0000000000e+00f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, + {7.2002207902e-01f, -8.3611353484e-01f, 1.5734662283e-01f, -6.0533065445e-02f, 2.8744838362e-02f, -1.4475653098e-02f, 7.3741983730e-03f, -3.2703655593e-03f, 1.3101771678e-03f}, + {4.4004415805e-01f, -6.7222706969e-01f, 3.1469324567e-01f, -1.2106613089e-01f, 5.7489676724e-02f, -2.8951306196e-02f, 1.4748396746e-02f, -6.5407311186e-03f, 2.6203543356e-03f}, + {3.1140768621e-01f, -5.2723264595e-01f, 3.2681622705e-01f, -1.6571616135e-01f, 8.2091070549e-02f, -4.1985522505e-02f, 2.1558021488e-02f, -9.6011245317e-03f, 3.8591478579e-03f}, + {2.3545411266e-01f, -4.2002230503e-01f, 2.9849192552e-01f, -1.7860012185e-01f, 9.8405575301e-02f, -5.2136865236e-02f, 2.7238498970e-02f, -1.2241573652e-02f, 4.9551740892e-03f}, + {1.8445053632e-01f, -3.3955276527e-01f, 2.6111274825e-01f, -1.7321025355e-01f, 1.0453147344e-01f, -5.8397411709e-02f, 3.1342038309e-02f, -1.4286182365e-02f, 5.8465512142e-03f}, + {1.4751535571e-01f, -2.7741009878e-01f, 2.2430319966e-01f, -1.5928934988e-01f, 1.0305050145e-01f, -6.0626267462e-02f, 3.3654414123e-02f, -1.5627206618e-02f, 6.4904010783e-03f}, + {1.1949382843e-01f, -2.2829289243e-01f, 1.9098724002e-01f, -1.4218308534e-01f, 9.6941146019e-02f, -5.9613663992e-02f, 3.4255504783e-02f, -1.6247499316e-02f, 6.8698231435e-03f}, + {9.7608450047e-02f, -1.8883237673e-01f, 1.6185826384e-01f, -1.2464644955e-01f, 8.8460078738e-02f, -5.6406223768e-02f, 3.3467341677e-02f, -1.6219692953e-02f, 6.9958126950e-03f}, + }; + for (int channel = 0; channel < para.spin_compress; ++channel) { + for (int basis = 0; basis < basis_count; ++basis) { + for (int pair = 0; pair < type_pairs; ++pair) { + const int index = spin_offset + + (channel * basis_count + basis) * type_pairs + pair; + mu[index] = spin3_radial_frame[channel][basis]; + sigma[index] = para.sigma0 * descriptor_scale; + } + } + } + + const int projection_offset = + spin_offset + para.number_of_variables_descriptor_spin; + const int channels = para.spin_compress; + for (int leg = 0; leg < 4; ++leg) { + for (int row = 0; row < channels; ++row) { + for (int source = 0; source < channels; ++source) { + const int index = projection_offset + + (leg * channels + row) * channels + source; + mu[index] = normal(rng) * spin_noise; + if (source == (row + leg) % channels) { + mu[index] += 1.0f; + } + sigma[index] = para.sigma0 * descriptor_scale; + } + } + } +} +void assign_variable_types(const Spin_Parameters& para, int offset, std::vector& type_of_variable) +{ + for (int channel = 0; channel < para.spin_compress; ++channel) { + for (int basis = 0; basis <= para.spin_basis_size[0]; ++basis) { + for (int t1 = 0; t1 < para.num_types; ++t1) { + for (int t2 = 0; t2 < para.num_types; ++t2) { + const int pair = t1 * para.num_types + t2; + const int coefficient = + (channel * (para.spin_basis_size[0] + 1) + basis) * + para.num_types * para.num_types + + pair; + type_of_variable[offset + coefficient] = t1; + } + } + } + } +} +} diff --git a/src/main_nep/nep_spin/spin_init.cuh b/src/main_nep/nep_spin/spin_init.cuh new file mode 100644 index 000000000..dbf9e77bb --- /dev/null +++ b/src/main_nep/nep_spin/spin_init.cuh @@ -0,0 +1,15 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#pragma once +#include "spin_parameters.cuh" +#include +namespace snes_spin { +void initialize_search(const Spin_Parameters&, std::mt19937&, std::vector&, std::vector&); +void assign_variable_types(const Spin_Parameters&, int, std::vector&); +} diff --git a/src/main_nep/nep_spin/spin_io.cu b/src/main_nep/nep_spin/spin_io.cu new file mode 100644 index 000000000..f5e14c565 --- /dev/null +++ b/src/main_nep/nep_spin/spin_io.cu @@ -0,0 +1,572 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#include "spin_io.cuh" +#include "utilities/nep_spin_model_file.cuh" +#include +#include "main_nep/common/nep_io.cuh" +#include "utilities/error.cuh" +#include "utilities/read_file.cuh" +#include "utilities/nep_spin_legacy_parameters.cuh" +#include +#include +#include +#include +namespace { +// Shared structural codec; model-specific metadata precedes this section. +struct NepTxtHeader { + std::string model_token; + int version; + bool enable_zbl; + bool use_typewise_cutoff_zbl; + float zbl_rc_inner; + float zbl_rc_outer; + float typewise_cutoff_zbl_factor; + int num_types; + std::vector elements; + bool has_multiple_cutoffs; + std::vector rc_radial; + std::vector rc_angular; + int n_max_radial; + int n_max_angular; + int basis_size_radial; + int basis_size_angular; + int L_max; + int has_q_222; // as written to nep.txt, that is 2 or 0 + int has_q_1111; + int has_q_112; + int has_q_123; + int has_q_233; + int has_q_134; + int num_neurons1; + int num_neurons2; + int number_of_header_lines; // 6 without a zbl line, 7 with one +}; + +static bool check_header_line( + const std::vector& tokens, + const char* keyword, + const size_t min_size, + const size_t max_size, + const std::string& filename, + std::string& error) +{ + if (tokens.size() < min_size || tokens.size() > max_size || tokens[0] != keyword) { + error = "The " + std::string(keyword) + " line of " + filename + " is malformed."; + return false; + } + return true; +} + +bool read_nep_structural_header( + std::istream& input, const std::string& filename, NepTxtHeader& header, std::string& error) +{ + std::vector tokens; + // second line: zbl, written only for a model with ZBL + header.use_typewise_cutoff_zbl = false; + header.zbl_rc_inner = 0.0f; + header.zbl_rc_outer = 0.0f; + header.typewise_cutoff_zbl_factor = -1.0f; + if (header.enable_zbl) { + tokens = get_tokens(input); + ++header.number_of_header_lines; + if (!check_header_line(tokens, "zbl", 3, 4, filename, error)) { + return false; + } + header.zbl_rc_inner = get_double_from_token(tokens[1], __FILE__, __LINE__); + header.zbl_rc_outer = get_double_from_token(tokens[2], __FILE__, __LINE__); + if (header.zbl_rc_inner == 0.0f && header.zbl_rc_outer == 0.0f) { + error = "NEP-spin does not support flexible ZBL (zbl 0 0)."; + return false; + } + if (tokens.size() == 4) { + header.use_typewise_cutoff_zbl = true; + header.typewise_cutoff_zbl_factor = get_double_from_token(tokens[3], __FILE__, __LINE__); + } + } + + // cutoff line: the two neighbor counts at the end depend on the training set and are ignored + tokens = get_tokens(input); + ++header.number_of_header_lines; + if (!check_header_line(tokens, "cutoff", 5, size_t(header.num_types) * 2 + 3, filename, error)) { + return false; + } + header.has_multiple_cutoffs = + (tokens.size() == size_t(header.num_types) * 2 + 3 && tokens.size() > 5); + const int num_cutoffs = header.has_multiple_cutoffs ? header.num_types : 1; + if (tokens.size() != size_t(num_cutoffs) * 2 + 3) { + error = "The cutoff line of " + filename + " is malformed."; + return false; + } + header.rc_radial.resize(num_cutoffs); + header.rc_angular.resize(num_cutoffs); + for (int n = 0; n < num_cutoffs; ++n) { + header.rc_radial[n] = get_double_from_token(tokens[1 + n * 2], __FILE__, __LINE__); + header.rc_angular[n] = get_double_from_token(tokens[2 + n * 2], __FILE__, __LINE__); + } + + tokens = get_tokens(input); + ++header.number_of_header_lines; + if (!check_header_line(tokens, "n_max", 3, 3, filename, error)) { + return false; + } + header.n_max_radial = get_int_from_token(tokens[1], __FILE__, __LINE__); + header.n_max_angular = get_int_from_token(tokens[2], __FILE__, __LINE__); + + tokens = get_tokens(input); + ++header.number_of_header_lines; + if (!check_header_line(tokens, "basis_size", 3, 3, filename, error)) { + return false; + } + header.basis_size_radial = get_int_from_token(tokens[1], __FILE__, __LINE__); + header.basis_size_angular = get_int_from_token(tokens[2], __FILE__, __LINE__); + + // l_max line: between 3 and 7 values, the trailing ones defaulting to zero when absent + tokens = get_tokens(input); + ++header.number_of_header_lines; + if (!check_header_line(tokens, "l_max", 4, 8, filename, error)) { + return false; + } + header.L_max = get_int_from_token(tokens[1], __FILE__, __LINE__); + header.has_q_222 = get_int_from_token(tokens[2], __FILE__, __LINE__); + header.has_q_1111 = get_int_from_token(tokens[3], __FILE__, __LINE__); + header.has_q_112 = (tokens.size() > 4) ? get_int_from_token(tokens[4], __FILE__, __LINE__) : 0; + header.has_q_123 = (tokens.size() > 5) ? get_int_from_token(tokens[5], __FILE__, __LINE__) : 0; + header.has_q_233 = (tokens.size() > 6) ? get_int_from_token(tokens[6], __FILE__, __LINE__) : 0; + header.has_q_134 = (tokens.size() > 7) ? get_int_from_token(tokens[7], __FILE__, __LINE__) : 0; + + tokens = get_tokens(input); + ++header.number_of_header_lines; + if (!check_header_line(tokens, "ANN", 3, 3, filename, error)) { + return false; + } + header.num_neurons1 = get_int_from_token(tokens[1], __FILE__, __LINE__); + header.num_neurons2 = get_int_from_token(tokens[2], __FILE__, __LINE__); + + return true; +} + + +// parse the header of a nep.txt file; returns false and sets error if it cannot be parsed +static bool parse_model_token(const std::string& token, NepTxtHeader& header) { + if (token != "nep4_spin3" && token != "nep4_spin3_zbl") return false; + header.version = 4; + header.enable_zbl = token == "nep4_spin3_zbl"; + return true; +} +bool read_nep_txt_header(const std::string& filename, NepTxtHeader& header, std::string& error) +{ + std::istringstream input(read_nep_spin_model_input(filename)); + if (!input.good()) { + error = "Failed to open " + filename + "."; + return false; + } + + // first line: the model token, the number of types, and the elements + std::vector tokens = get_tokens(input); + if (tokens.size() < 3) { + error = "The first line of " + filename + " should have at least 3 items."; + return false; + } + header.model_token = tokens[0]; + if (!parse_model_token(header.model_token, header)) { + error = "'" + header.model_token + "' in " + filename + " is not a known NEP model type."; + return false; + } + header.num_types = get_int_from_token(tokens[1], __FILE__, __LINE__); + if (header.num_types < 1 || tokens.size() != size_t(header.num_types) + 2) { + error = "The first line of " + filename + " does not list " + std::to_string(header.num_types) + + " elements."; + return false; + } + header.elements.assign(tokens.begin() + 2, tokens.end()); + header.number_of_header_lines = 1; + { + tokens = get_tokens(input); + if (tokens.size() != 3 || tokens[0] != "spin_mode" || + get_int_from_token(tokens[1], __FILE__, __LINE__) != 3) { + error = "Invalid counted Spin3 header in " + filename + "."; + return false; + } + const int count = get_int_from_token(tokens[2], __FILE__, __LINE__); + if (count < 9 || count > 11) { + error = "Invalid counted Spin3 header length in " + filename + "."; + return false; + } + for (int n = 0; n < count; ++n) { + if (get_tokens(input).empty()) { + error = "Truncated Spin3 header in " + filename + "."; + return false; + } + } + header.number_of_header_lines += count + 1; + } + + return read_nep_structural_header(input, filename, header, error); +} + +void load_spin_checkpoint_metadata(Spin_Parameters& para) +{ + std::istringstream input(read_nep_spin_model_input("nep.txt")); + if (!input.good()) { + PRINT_INPUT_ERROR("Failed to open nep.txt for Spin NEP prediction."); + } + auto tokens = get_tokens(input); + const std::string expected_tag = para.enable_zbl + ? "nep4_spin3_zbl" + : "nep4_spin3"; + if (tokens.size() != static_cast(para.num_types + 2) || + tokens[0] != expected_tag || + get_int_from_token(tokens[1], __FILE__, __LINE__) != para.num_types) { + PRINT_INPUT_ERROR("Spin NEP checkpoint header does not match nep.in."); + } + for (int type = 0; type < para.num_types; ++type) { + if (tokens[type + 2] != para.elements[type]) { + PRINT_INPUT_ERROR("Spin NEP checkpoint atom types do not match nep.in."); + } + } + tokens = get_tokens(input); + if (tokens.size() != 3 || tokens[0] != "spin_mode" || + get_int_from_token(tokens[1], __FILE__, __LINE__) != para.spin_mode) { + PRINT_INPUT_ERROR("Spin NEP checkpoint has an invalid counted spin header."); + } + const int line_count = get_int_from_token(tokens[2], __FILE__, __LINE__); + constexpr int minimum_lines = 9; + if (line_count < minimum_lines || line_count > minimum_lines + 2) { + PRINT_INPUT_ERROR("Spin NEP checkpoint has an invalid counted header length."); + } + + bool seen_baseline = false; + bool seen_basis_size = false; + bool seen_l_max = false; + bool seen_compress = false; + bool seen_cutoff = false; + bool seen_scaler = false; + bool seen_order = false; + bool seen_soc = false; + bool seen_projection_size = false; + bool seen_dof = false; + bool seen_env = false; + std::vector dof(para.num_types, 1); + std::vector env; + auto parse_active = [&](const std::vector& line_tokens) { + std::vector active(para.num_types, 0); + if (line_tokens.size() < 2) { + PRINT_INPUT_ERROR("Spin type-selection line must enable at least one type."); + } + for (std::size_t index = 1; index < line_tokens.size(); ++index) { + auto found = + std::find(para.elements.begin(), para.elements.end(), line_tokens[index]); + if (found == para.elements.end()) { + PRINT_INPUT_ERROR("Spin checkpoint contains an unknown atom type."); + } + const int type = static_cast(found - para.elements.begin()); + if (active[type]) { + PRINT_INPUT_ERROR("Spin checkpoint contains a duplicate atom type."); + } + active[type] = 1; + } + return active; + }; + for (int line = 0; line < line_count; ++line) { + tokens = get_tokens(input); + if (tokens.empty()) { + PRINT_INPUT_ERROR("Spin NEP checkpoint has a truncated spin header."); + } + const std::string& keyword = tokens[0]; + if (keyword == "spin_baseline") { + if (seen_baseline || + tokens.size() != static_cast(para.num_types + 1)) { + PRINT_INPUT_ERROR("Invalid spin_baseline in Spin NEP checkpoint."); + } + seen_baseline = true; + para.energy_reference.resize(para.num_types); + for (int type = 0; type < para.num_types; ++type) { + para.energy_reference[type] = + get_double_from_token(tokens[type + 1], __FILE__, __LINE__); + } + } else if (keyword == "spin_basis_size") { + if (seen_basis_size || tokens.size() != 2 || + get_int_from_token(tokens[1], __FILE__, __LINE__) != + para.spin_basis_size[0]) { + PRINT_INPUT_ERROR("spin_basis_size in nep.txt does not match nep.in."); + } + seen_basis_size = true; + } else if (keyword == "spin_l_max") { + if (seen_l_max || tokens.size() != 2) { + PRINT_INPUT_ERROR("Invalid spin_l_max in Spin NEP checkpoint."); + } + if (get_int_from_token(tokens[1], __FILE__, __LINE__) != + para.spin_l_max[0]) { + PRINT_INPUT_ERROR("spin_l_max in nep.txt does not match nep.in."); + } + seen_l_max = true; + } else if (keyword == "spin_compress") { + if (seen_compress || tokens.size() != 2 || + get_int_from_token(tokens[1], __FILE__, __LINE__) != para.spin_compress) { + PRINT_INPUT_ERROR("spin_compress in nep.txt does not match nep.in."); + } + seen_compress = true; + } else if (keyword == "spin_cutoff") { + if (seen_cutoff || + (tokens.size() != 2 && + tokens.size() != static_cast(para.num_types + 1))) { + PRINT_INPUT_ERROR("Invalid spin_cutoff in Spin NEP checkpoint."); + } + for (int type = 0; type < para.num_types; ++type) { + const std::size_t value_index = tokens.size() == 2 ? 1 : type + 1; + const double value = + get_double_from_token(tokens[value_index], __FILE__, __LINE__); + if (std::abs(value - para.spin_cutoff_by_type[type]) > + 1.0e-6 * std::max(1.0, std::abs(value))) { + PRINT_INPUT_ERROR("spin_cutoff in nep.txt does not match nep.in."); + } + } + seen_cutoff = true; + } else if (keyword == "spin_order") { + if (seen_order || tokens.size() != 2 || + get_int_from_token(tokens[1], __FILE__, __LINE__) != para.spin_order) { + PRINT_INPUT_ERROR("spin_order in nep.txt does not match nep.in."); + } + seen_order = true; + } else if (keyword == "spin_soc") { + if (seen_soc || tokens.size() != 2 || + get_int_from_token(tokens[1], __FILE__, __LINE__) != para.spin_soc) { + PRINT_INPUT_ERROR("spin_soc in nep.txt does not match nep.in."); + } + seen_soc = true; + } else if (keyword == "spin_projection_size") { + if (seen_projection_size || tokens.size() != 2 || + get_int_from_token(tokens[1], __FILE__, __LINE__) != + para.number_of_variables_spin_projection) { + PRINT_INPUT_ERROR("spin_projection_size in nep.txt does not match nep.in."); + } + seen_projection_size = true; + } else if (keyword == "spin_scaler") { + if (seen_scaler || tokens.size() != 2 || + get_int_from_token(tokens[1], __FILE__, __LINE__) != 1) { + PRINT_INPUT_ERROR("spin_scaler in nep.txt must occur once and equal 1."); + } + seen_scaler = true; + } else if (keyword == "spin_dof_type") { + if (seen_dof) { + PRINT_INPUT_ERROR("Duplicate spin_dof_type in Spin NEP checkpoint."); + } + dof = parse_active(tokens); + seen_dof = true; + } else if (keyword == "spin_env_type") { + if (seen_env) { + PRINT_INPUT_ERROR("Duplicate spin_env_type in Spin NEP checkpoint."); + } + env = parse_active(tokens); + seen_env = true; + } else { + PRINT_INPUT_ERROR("Unknown line in counted Spin NEP checkpoint header."); + } + } + if (!seen_baseline || !seen_basis_size || !seen_l_max || + !seen_compress || !seen_cutoff || !seen_scaler || !seen_order || + !seen_soc || !seen_projection_size) { + PRINT_INPUT_ERROR("Spin NEP checkpoint is missing required metadata."); + } + if (!seen_env) { + env = dof; + } + for (int type = 0; type < para.num_types; ++type) { + if (dof[type] && !env[type]) { + PRINT_INPUT_ERROR("spin_dof_type must be a subset of spin_env_type."); + } + } + if (para.is_spin_dof_type_set && para.spin_dof_type_active != dof) { + PRINT_INPUT_ERROR("spin_dof_type in nep.in conflicts with the Spin3 checkpoint."); + } + if (para.is_spin_env_type_set && para.spin_env_type_active != env) { + PRINT_INPUT_ERROR("spin_env_type in nep.in conflicts with the Spin3 checkpoint."); + } + para.spin_dof_type_active = dof; + para.spin_env_type_active = env; + if (para.enable_zbl) { + tokens = get_tokens(input); + const std::size_t expected_size = para.use_typewise_cutoff_zbl ? 4 : 3; + if (tokens.size() != expected_size || tokens[0] != "zbl") { + PRINT_INPUT_ERROR("Spin3 ZBL checkpoint has an invalid zbl line."); + } + const double inner = get_double_from_token(tokens[1], __FILE__, __LINE__); + const double outer = get_double_from_token(tokens[2], __FILE__, __LINE__); + if (std::abs(inner - para.zbl_rc_inner) > 1.0e-6 || + std::abs(outer - para.zbl_rc_outer) > 1.0e-6 || + (para.use_typewise_cutoff_zbl && + std::abs(get_double_from_token(tokens[3], __FILE__, __LINE__) - + para.typewise_cutoff_zbl_factor) > 1.0e-6)) { + PRINT_INPUT_ERROR("Spin3 ZBL checkpoint does not match nep.in."); + } + } +} +void write_checkpoint_metadata(FILE* fid_nep, const Spin_Parameters& para) +{ + // Serialize effective model state, including masks inherited from a checkpoint. + const bool write_dof = std::any_of( + para.spin_dof_type_active.begin(), para.spin_dof_type_active.end(), + [](int active) { return active != 1; }); + const bool write_env = para.spin_env_type_active != para.spin_dof_type_active; + fprintf(fid_nep, "spin_version 1\n"); + fprintf(fid_nep, "spin_basis_size %d\n", para.spin_basis_size[0]); + fprintf(fid_nep, "spin_l_max %d\n", para.spin_l_max[0]); + fprintf(fid_nep, "spin_compress %d\n", para.spin_compress); + fprintf(fid_nep, "spin_cutoff"); + const bool uniform_spin_cutoff = std::all_of( + para.spin_cutoff_by_type.begin() + 1, + para.spin_cutoff_by_type.end(), + [&](float value) { + return std::abs(value - para.spin_cutoff_by_type.front()) <= 1.0e-7f; + }); + const int cutoff_count = uniform_spin_cutoff ? 1 : para.num_types; + for (int type = 0; type < cutoff_count; ++type) { + fprintf(fid_nep, " %.9g", para.spin_cutoff_by_type[type]); + } + fprintf(fid_nep, "\n"); + fprintf(fid_nep, "spin_order %d\n", para.spin_order); + fprintf(fid_nep, "spin_soc %d\n", para.spin_soc); + fprintf( + fid_nep, + "spin_projection_size %d\n", + para.number_of_variables_spin_projection); + fprintf(fid_nep, "spin_scaler 1\n"); + if (write_dof) { + fprintf(fid_nep, "spin_dof_type"); + for (int type = 0; type < para.num_types; ++type) { + if (para.spin_dof_type_active[type]) { + fprintf(fid_nep, " %s", para.elements[type].c_str()); + } + } + fprintf(fid_nep, "\n"); + } + if (write_env) { + fprintf(fid_nep, "spin_env_type"); + for (int type = 0; type < para.num_types; ++type) { + if (para.spin_env_type_active[type]) { + fprintf(fid_nep, " %s", para.elements[type].c_str()); + } + } + fprintf(fid_nep, "\n"); + } +} +} + +static void validate_model_header(Spin_Parameters& para) { + NepTxtHeader h; + std::string error; + if (!read_nep_txt_header("nep.txt", h, error)) PRINT_INPUT_ERROR(error.c_str()); + para.number_of_nep_txt_header_lines = h.number_of_header_lines; + if (h.model_token != para.file_tag || h.num_types != para.num_types || h.elements != para.elements || + h.n_max_radial != para.n_max_radial || h.n_max_angular != para.n_max_angular || + h.basis_size_radial != para.basis_size_radial || h.basis_size_angular != para.basis_size_angular || + h.L_max != para.L_max || h.has_q_222 != (para.has_q_222 ? 2 : 0) || + h.has_q_1111 != para.has_q_1111 || h.has_q_112 != para.has_q_112 || + h.has_q_123 != para.has_q_123 || h.has_q_233 != para.has_q_233 || h.has_q_134 != para.has_q_134 || + h.num_neurons1 != para.num_neurons1 || h.num_neurons2 != 0 || h.has_multiple_cutoffs) { + PRINT_INPUT_ERROR("nep.in is inconsistent with the Spin3 model in nep.txt."); + } + const auto same = [](float a, float b) { return std::abs(a-b) <= 1.0e-5f*(std::abs(a)+std::abs(b)+1.0e-10f); }; + if (!same(h.rc_radial[0], para.rc_radial[0]) || !same(h.rc_angular[0], para.rc_angular[0])) { + PRINT_INPUT_ERROR("Structural cutoffs in nep.txt do not match nep.in."); + } + load_spin_checkpoint_metadata(para); +} + +void read_spin_model(Spin_Parameters& para, float* parameters) { + validate_model_header(para); + std::istringstream input(read_nep_spin_model_input("nep.txt")); + for (int i=0; i 16) PRINT_INPUT_ERROR("At most 16 training devices are supported."); + for (int d=0; d parameters(para.number_of_variables); + read_spin_model(para, parameters.data()); + } + if (para.spin_restart) { + std::vector mu, sigma; + read_spin_restart(para, mu, sigma); + } else if (!para.prediction) { + // import_q_scaler imports only the scaler; new training fits its own reference. + para.energy_reference.clear(); + } +} + +void write_spin_model(FILE* fid_nep, Spin_Parameters& para, const float* elite, int max_NN_radial, int max_NN_angular) { + CHECK(gpuSetDevice(0)); + para.q_scaler_gpu[0].copy_to_host(para.q_scaler_cpu.data()); + write_nep_header(fid_nep, para, max_NN_radial, max_NN_angular); + write_checkpoint_metadata(fid_nep, para); + write_nep_model_parameters(fid_nep, para, elite); +} + +bool read_spin_restart(Spin_Parameters& para, std::vector& mu, std::vector& sigma) +{ + std::ifstream input("nep.restart"); + if (!input.good()) return false; + std::string first; + input >> first; + if (first == "nep_restart") return read_nep_restart("nep.restart", para, mu, sigma, ¶.energy_reference); + // Legacy restart stores basis-major mu/sigma, with references in nep.txt. + input.clear(); input.seekg(0); + mu.clear(); sigma.clear(); + std::string line; + while (std::getline(input, line)) { + const auto tokens = get_tokens(line); + if (tokens.size() != 2) PRINT_INPUT_ERROR("Legacy Spin3 restart requires mu sigma pairs."); + const double m = get_double_from_token(tokens[0], __FILE__, __LINE__); + const double s = get_double_from_token(tokens[1], __FILE__, __LINE__); + if (!std::isfinite(m) || !std::isfinite(s) || std::abs(m) > std::numeric_limits::max() || + s < 0 || s > std::numeric_limits::max()) PRINT_INPUT_ERROR("Invalid Spin3 restart value."); + mu.push_back(m); sigma.push_back(s); + } + if (mu.size() != size_t(para.number_of_variables)) PRINT_INPUT_ERROR("Spin3 restart parameter count mismatch."); + for (auto* values : {&mu, &sigma}) + descriptor_parameters_to_channel_major(values->data(), para.number_of_variables_ann, + para.num_types * para.num_types, para.n_max_radial, para.n_max_angular, + para.basis_size_radial, para.basis_size_angular); + return true; +} diff --git a/src/main_nep/nep_spin/spin_io.cuh b/src/main_nep/nep_spin/spin_io.cuh new file mode 100644 index 000000000..135ec52e8 --- /dev/null +++ b/src/main_nep/nep_spin/spin_io.cuh @@ -0,0 +1,15 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#pragma once +#include "spin_parameters.cuh" +void initialize_spin_checkpoint(Spin_Parameters&); +void read_spin_model(Spin_Parameters&, float*); +void write_spin_model(FILE*, Spin_Parameters&, const float*, int max_radial, int max_angular); + +bool read_spin_restart(Spin_Parameters&, std::vector&, std::vector&); diff --git a/src/main_nep/nep_spin/spin_parameters.cu b/src/main_nep/nep_spin/spin_parameters.cu new file mode 100644 index 000000000..f1b3ff5e8 --- /dev/null +++ b/src/main_nep/nep_spin/spin_parameters.cu @@ -0,0 +1,422 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#include "spin_parameters.cuh" +#include "spin_io.cuh" +#include "main_nep/common/nep_model.cuh" +#include "utilities/common.cuh" +#include "utilities/nep_utilities.cuh" +#include "utilities/error.cuh" +#include "utilities/read_file.cuh" +#include +#include +#include +#include +Spin_Parameters::Spin_Parameters(const ParameterInput& input) { + read(input); + if (!is_spin_cutoff_set) { + spin_cutoff = rc_radial_max; + spin_cutoff_by_type.assign(num_types, spin_cutoff); + } + validate_spin_parameters(); + calculate_nep_model_parameters(*this, 0, 0, 1, 1); + dim_struct = dim; + calculate_spin_dimensions(); + calculate_nep_model_parameters(*this, dim_spin, 0, 1, 1); + number_of_variables_descriptor_spin = num_types * num_types * spin_compress * (spin_basis_size[0] + 1); + number_of_variables_spin_projection = 4 * spin_compress * spin_compress; + number_of_variables_descriptor += number_of_variables_descriptor_spin + number_of_variables_spin_projection; + number_of_variables = number_of_variables_ann + number_of_variables_descriptor; + model_name = "nep_spin"; + file_tag = enable_zbl ? "nep4_spin3_zbl" : "nep4_spin3"; + set_regularization_defaults(); + initialize_spin_checkpoint(*this); + // Check the effective masks after any omitted input fields were restored. + for (int type = 0; type < num_types; ++type) { + if (spin_dof_type_active[type] && !spin_env_type_active[type]) { + PRINT_INPUT_ERROR("spin_dof_type must be a subset of spin_env_type."); + } + } + report_inputs(input, "Spin3 potential", nullptr); + printf("Spin3 O%d/C%d: %d structural + %d magnetic descriptors, %d parameters.\n", + spin_order, spin_compress, dim_struct, dim_spin, number_of_variables); + printf("Finished reading nep.in.\n"); +} +void Spin_Parameters::report_model_inputs() const +{ + NEP_Energy_Parameters::report_model_inputs(); + printf(" spin_version = 1.\n"); + printf(" spin_order = %d, spin_compress = %d, spin_soc = %d.\n", spin_order, spin_compress, spin_soc); + printf(" spin_basis_size = %d, spin_l_max = %d.\n", spin_basis_size[0], spin_l_max[0]); + if (split_mforce_loss) { + printf(" lambda_m_parallel = %g, lambda_m_perp = %g (independent RMSE terms).\n", + lambda_m_parallel, lambda_m_perp); + } else { + printf(" lambda_m = %g (Cartesian RMSE).\n", lambda_m); + } + printf(" lambda_tau = %g, lambda_spin_response = %g.\n", lambda_tau, lambda_spin_response); + printf(" sigma0 = %g.\n", sigma0); + printf(" spin_cutoff:"); + for (int t = 0; t < num_types; ++t) printf(" %s=%g", elements[t].c_str(), spin_cutoff_by_type[t]); + printf("\n spin_dof_type:"); + for (int t = 0; t < num_types; ++t) if (spin_dof_type_active[t]) printf(" %s", elements[t].c_str()); + printf("\n spin_env_type:"); + for (int t = 0; t < num_types; ++t) if (spin_env_type_active[t]) printf(" %s", elements[t].c_str()); + printf("\n Spin q_scaler = %s; restart = %s.\n", + (prediction || spin_restart || import_q_scaler) ? "loaded from nep.txt" : "fixed reference initialization", + spin_restart ? "yes" : "no"); +} + +bool Spin_Parameters::parse_keyword(const char** param, int num_param) +{ + if (strcmp(param[0], "lambda_m") == 0 || + strcmp(param[0], "lambda_mforce") == 0) { + parse_lambda_m(param, num_param); + } else if (strcmp(param[0], "lambda_m_parallel") == 0) { + parse_lambda_m_component(param, num_param, lambda_m_parallel, is_lambda_m_parallel_set); + } else if (strcmp(param[0], "lambda_m_perp") == 0) { + parse_lambda_m_component(param, num_param, lambda_m_perp, is_lambda_m_perp_set); + } else if (strcmp(param[0], "lambda_tau") == 0) { + parse_lambda_tau(param, num_param); + } else if (strcmp(param[0], "lambda_spin_response") == 0) { + parse_lambda_spin_response(param, num_param); + } else if (strcmp(param[0], "spin_compress") == 0) { + parse_spin_compress(param, num_param); + } else if (strcmp(param[0], "spin_order") == 0) { + parse_spin_order(param, num_param); + } else if (strcmp(param[0], "spin_soc") == 0) { + parse_spin_soc(param, num_param); + + } else if (strcmp(param[0], "spin_basis_size") == 0) { + parse_spin_basis_size(param, num_param); + } else if (strcmp(param[0], "spin_l_max") == 0) { + parse_spin_l_max(param, num_param); + } else if (strcmp(param[0], "spin_cutoff") == 0) { + parse_spin_cutoff(param, num_param); + } else if (strcmp(param[0], "spin_dof_type") == 0) { + parse_spin_active_types( + param, + num_param, + "spin_dof_type", + spin_dof_type_names, + is_spin_dof_type_set); + } else if (strcmp(param[0], "spin_env_type") == 0) { + parse_spin_active_types( + param, + num_param, + "spin_env_type", + spin_env_type_names, + is_spin_env_type_set); + } else { + return NEP_Energy_Parameters::parse_keyword(param, num_param); + } + return true; +} + +void Spin_Parameters::validate_spin_parameters() +{ + split_mforce_loss = is_lambda_m_parallel_set || is_lambda_m_perp_set; + if (split_mforce_loss && is_lambda_m_set) { + PRINT_INPUT_ERROR("Do not combine lambda_m/lambda_mforce with lambda_m_parallel or lambda_m_perp.\n"); + } + if (split_mforce_loss && !(is_lambda_m_parallel_set && is_lambda_m_perp_set)) { + PRINT_INPUT_ERROR("Specify both lambda_m_parallel and lambda_m_perp; use 0 to disable a component.\n"); + } + if (version != 4) { + PRINT_INPUT_ERROR("Spin NEP only supports a NEP4 potential model.\n"); + } + if (has_multiple_cutoffs) { + PRINT_INPUT_ERROR( + "Spin3 does not support charge/vdW or type-dependent structural cutoffs.\n"); + } + if (num_hidden_layers == 2) { + PRINT_INPUT_ERROR("Spin NEP only supports one hidden layer.\n"); + } + if (fine_tune) { + PRINT_INPUT_ERROR( + "Spin NEP fine_tune is not supported until the " + "species-transfer checkpoint reader is implemented.\n"); + } + if ( + spin_compress < 1 || spin_compress > 9 || + spin_basis_size[0] != 8 || spin_basis_size[1] != 0 || + spin_l_max[0] < 0 || spin_l_max[0] > 2 || + spin_l_max[1] != 0 || spin_l_max[2] != 0 || + spin_order < 1 || spin_order > 3 || + (spin_soc != 0 && spin_soc != 1) || + spin_cutoff <= 0.0f) { + PRINT_INPUT_ERROR("Unsupported unified Spin NEP O/C shape in nep.in.\n"); + } +#ifdef USE_CJ + PRINT_INPUT_ERROR("Spin3 requires pair-dependent descriptor coefficients (no USE_CJ).\n"); +#endif + + auto resolve_active_types = [&](const std::vector& names, + bool is_set, + std::vector& active) { + active.assign(num_types, is_set ? 0 : 1); + if (!is_set) { + return; + } + for (const auto& name : names) { + auto found = std::find(elements.begin(), elements.end(), name); + if (found == elements.end()) { + PRINT_INPUT_ERROR("spin_dof_type or spin_env_type contains an unknown atom type.\n"); + } + active[found - elements.begin()] = 1; + } + }; + resolve_active_types( + spin_dof_type_names, + is_spin_dof_type_set, + spin_dof_type_active); + if (is_spin_env_type_set) { + resolve_active_types( + spin_env_type_names, + true, + spin_env_type_active); + } else { + spin_env_type_active = spin_dof_type_active; + } +} + +void Spin_Parameters::calculate_spin_dimensions() +{ + const int C = spin_compress; + const int L = spin_l_max[0]; + const int pairs = C * (C + 1) / 2; + dim_spin = 1 + 2 * C; + if (spin_soc && L >= 2) dim_spin += 2 * C; + if (spin_order >= 2) { + dim_spin += 2 * C; + if (L >= 1) dim_spin += (spin_soc ? 3 : 1) * C; + if (L >= 2) dim_spin += C; + dim_spin += C + 2 * pairs; + if (L >= 1) dim_spin += pairs; + if (L >= 2) dim_spin += pairs; + if (spin_soc && L >= 1) { + dim_spin += (C >= 2 ? 2 : 1) * C; + } + if (spin_soc && L >= 2) { + dim_spin += (C >= 2 ? 2 : 1) * C; + } + } + if (spin_order >= 3) { + dim_spin += C; + if (spin_soc && L >= 1) { + dim_spin += (C >= 2 ? 2 : 1) * C; + } + if (spin_soc && L >= 2) { + dim_spin += (C >= 2 ? 3 : 1) * C; + } + if (spin_soc && L >= 1 && C >= 3) dim_spin += C; + } + if (dim_spin > 96) { + PRINT_INPUT_ERROR("Number of spin descriptors should not exceed 96.\n"); + } + dim = dim_struct + dim_spin; + if (dim > MAX_DIM_SPIN) { + PRINT_INPUT_ERROR( + "Combined structural and spin descriptor dimension exceeds GPUMD MAX_DIM_SPIN.\n"); + } +} + +void Spin_Parameters::parse_lambda_m(const char** param, int num_param) +{ + if (is_lambda_m_set) { + PRINT_INPUT_ERROR("Duplicate lambda_m/lambda_mforce keyword.\n"); + } + is_lambda_m_set = true; + if (num_param != 2) { + PRINT_INPUT_ERROR("lambda_m should have 1 parameter.\n"); + } + double value = 0.0; + if (!is_valid_real(param[1], &value) || !std::isfinite(value) || value < 0.0 || + value > std::numeric_limits::max()) { + PRINT_INPUT_ERROR("Magnetic-force loss weight should be a non-negative number.\n"); + } + lambda_m = value; +} + +void Spin_Parameters::parse_lambda_m_component( + const char** param, int num_param, float& weight, bool& is_set) +{ + if (is_set) { + PRINT_INPUT_ERROR("Duplicate magnetic-force component lambda keyword.\n"); + } + is_set = true; + if (num_param != 2) { + PRINT_INPUT_ERROR("Each magnetic-force component lambda should have 1 parameter.\n"); + } + double value = 0.0; + if (!is_valid_real(param[1], &value) || !std::isfinite(value) || value < 0.0 || + value > std::numeric_limits::max()) { + PRINT_INPUT_ERROR("Magnetic-force component lambda should be finite and non-negative.\n"); + } + weight = value; +} + +void Spin_Parameters::parse_lambda_tau(const char** param, int num_param) +{ + if (is_lambda_tau_set) { + PRINT_INPUT_ERROR("Duplicate lambda_tau keyword.\n"); + } + is_lambda_tau_set = true; + if (num_param != 2) { + PRINT_INPUT_ERROR("lambda_tau should have 1 parameter.\n"); + } + double value = 0.0; + if (!is_valid_real(param[1], &value) || !std::isfinite(value) || value < 0.0 || + value > std::numeric_limits::max()) { + PRINT_INPUT_ERROR("Spin-torque loss weight should be finite and non-negative.\n"); + } + lambda_tau = value; +} + +void Spin_Parameters::parse_lambda_spin_response(const char** param, int num_param) +{ + if (is_lambda_spin_response_set) { + PRINT_INPUT_ERROR("Duplicate lambda_spin_response keyword.\n"); + } + is_lambda_spin_response_set = true; + if (num_param != 2) { + PRINT_INPUT_ERROR("lambda_spin_response should have 1 parameter.\n"); + } + double value = 0.0; + if (!is_valid_real(param[1], &value) || !std::isfinite(value) || value < 0.0 || + value > std::numeric_limits::max()) { + PRINT_INPUT_ERROR("lambda_spin_response should be finite and non-negative.\n"); + } + lambda_spin_response = value; +} + + +void Spin_Parameters::parse_spin_compress(const char** param, int num_param) +{ + if (is_spin_compress_set) { + PRINT_INPUT_ERROR("Duplicate spin_compress keyword.\n"); + } + is_spin_compress_set = true; + if (num_param != 2 || !is_valid_int(param[1], &spin_compress) || + spin_compress < 1 || spin_compress > 9) { + PRINT_INPUT_ERROR("spin_compress should be an integer from 1 to 9.\n"); + } +} + +void Spin_Parameters::parse_spin_order(const char** param, int num_param) +{ + if (is_spin_order_set) { + PRINT_INPUT_ERROR("Duplicate spin_order keyword.\n"); + } + is_spin_order_set = true; + if (num_param != 2 || !is_valid_int(param[1], &spin_order) || + spin_order < 1 || spin_order > 3) { + PRINT_INPUT_ERROR("spin_order should be an integer from 1 to 3.\n"); + } +} + +void Spin_Parameters::parse_spin_soc(const char** param, int num_param) +{ + if (is_spin_soc_set) { + PRINT_INPUT_ERROR("Duplicate spin_soc keyword.\n"); + } + is_spin_soc_set = true; + if (num_param != 2 || !is_valid_int(param[1], &spin_soc) || + (spin_soc != 0 && spin_soc != 1)) { + PRINT_INPUT_ERROR("spin_soc should be 0 or 1.\n"); + } +} + + +void Spin_Parameters::parse_spin_basis_size(const char** param, int num_param) +{ + if (is_spin_basis_size_set) { + PRINT_INPUT_ERROR("Duplicate spin_basis_size keyword.\n"); + } + is_spin_basis_size_set = true; + if (num_param != 3 || + !is_valid_int(param[1], &spin_basis_size[0]) || + !is_valid_int(param[2], &spin_basis_size[1]) || + spin_basis_size[0] < 0 || spin_basis_size[1] < 0) { + PRINT_INPUT_ERROR("spin_basis_size should have two non-negative integers.\n"); + } +} + +void Spin_Parameters::parse_spin_l_max(const char** param, int num_param) +{ + if (is_spin_l_max_set) { + PRINT_INPUT_ERROR("Duplicate spin_l_max keyword.\n"); + } + is_spin_l_max_set = true; + if (num_param != 4 || + !is_valid_int(param[1], &spin_l_max[0]) || + !is_valid_int(param[2], &spin_l_max[1]) || + !is_valid_int(param[3], &spin_l_max[2])) { + PRINT_INPUT_ERROR("spin_l_max should have three integers.\n"); + } +} + +void Spin_Parameters::parse_spin_cutoff(const char** param, int num_param) +{ + if (is_spin_cutoff_set) { + PRINT_INPUT_ERROR("Duplicate spin_cutoff keyword.\n"); + } + is_spin_cutoff_set = true; + if (num_types <= 0 || (num_param != 2 && num_param != num_types + 1)) { + PRINT_INPUT_ERROR( + "spin_cutoff should have one positive number or one per atom type.\n"); + } + spin_cutoff_by_type.resize(num_types); + for (int type = 0; type < num_types; ++type) { + double cutoff = 0.0; + const int value_index = num_param == 2 ? 1 : type + 1; + if (!is_valid_real(param[value_index], &cutoff) || !std::isfinite(cutoff) || cutoff <= 0.0 || + cutoff > std::numeric_limits::max()) { + PRINT_INPUT_ERROR("spin_cutoff values must be finite positive numbers within float range.\n"); + } + spin_cutoff_by_type[type] = static_cast(cutoff); + } + spin_cutoff = *std::max_element( + spin_cutoff_by_type.begin(), spin_cutoff_by_type.end()); +} + +void Spin_Parameters::parse_spin_active_types( + const char** param, + int num_param, + const char* keyword, + std::vector& names, + bool& is_set) +{ + if (is_set) { + PRINT_INPUT_ERROR("Duplicate spin_dof_type or spin_env_type keyword.\n"); + } + is_set = true; + if (num_param < 2) { + PRINT_INPUT_ERROR("spin_dof_type and spin_env_type must enable at least one type.\n"); + } + names.clear(); + for (int n = 1; n < num_param; ++n) { + if (std::find(names.begin(), names.end(), param[n]) != names.end()) { + PRINT_INPUT_ERROR("Duplicate atom type in spin_dof_type or spin_env_type.\n"); + } + names.emplace_back(param[n]); + } + (void)keyword; +} + +void Spin_Parameters::read_zbl_in() +{ + // Prediction ZBL metadata is read from the model, not from zbl.in. + if (!prediction) { + FILE* input = fopen("zbl.in", "r"); + if (input != nullptr) { + fclose(input); + PRINT_INPUT_ERROR("NEP-spin does not support flexible ZBL: remove zbl.in to use universal ZBL."); + } + } +} diff --git a/src/main_nep/nep_spin/spin_parameters.cuh b/src/main_nep/nep_spin/spin_parameters.cuh new file mode 100644 index 000000000..5bc852524 --- /dev/null +++ b/src/main_nep/nep_spin/spin_parameters.cuh @@ -0,0 +1,66 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#pragma once +#include "main_nep/common/nep_parameters.cuh" +class Spin_Parameters : public NEP_Energy_Parameters { +public: + explicit Spin_Parameters(const ParameterInput& input); + bool parse_keyword(const char**, int) override; + static constexpr int spin_mode = 3; + int spin_compress = 2, spin_order = 3, spin_soc = 1; + int spin_basis_size[2] = {8, 0}; + int spin_l_max[3] = {2, 0, 0}; + float spin_cutoff = 8.0f; + float lambda_m = 1.0f, lambda_tau = 0.0f, lambda_spin_response = 0.0f; + float lambda_m_parallel = 0.0f, lambda_m_perp = 0.0f; + bool split_mforce_loss = false; + bool is_spin_dof_type_set = false, is_spin_env_type_set = false; + bool spin_restart = false; + std::string file_tag; + int number_of_nep_txt_header_lines = 0; + int dim_struct = 0, dim_spin = 0; + int number_of_variables_descriptor_spin = 0, number_of_variables_spin_projection = 0; + std::vector spin_dof_type_names, spin_env_type_names; + std::vector spin_dof_type_active, spin_env_type_active; + std::vector spin_cutoff_by_type; + GPU_Vector q_scaler_square_sum[16]; + GPU_Vector q_scaler_count[16]; +protected: + void report_model_inputs() const override; + void read_zbl_in() override; +private: + void validate_spin_parameters(); + void calculate_spin_dimensions(); + bool is_lambda_m_set = false; + bool is_lambda_m_parallel_set = false, is_lambda_m_perp_set = false; + bool is_lambda_spin_response_set = false; + bool is_lambda_tau_set = false; + bool is_spin_basis_size_set = false; + bool is_spin_compress_set = false; + bool is_spin_cutoff_set = false; + bool is_spin_l_max_set = false; + bool is_spin_order_set = false; + bool is_spin_soc_set = false; + void parse_lambda_m(const char** param, int num_param); + void parse_lambda_m_component(const char** param, int num_param, float&, bool&); + void parse_lambda_tau(const char** param, int num_param); + void parse_lambda_spin_response(const char** param, int num_param); + void parse_spin_compress(const char** param, int num_param); + void parse_spin_order(const char** param, int num_param); + void parse_spin_soc(const char** param, int num_param); + void parse_spin_basis_size(const char** param, int num_param); + void parse_spin_l_max(const char** param, int num_param); + void parse_spin_cutoff(const char** param, int num_param); + void parse_spin_active_types( + const char** param, + int num_param, + const char* keyword, + std::vector& names, + bool& is_set); +}; diff --git a/src/main_nep/nep_spin/spin_policy.cu b/src/main_nep/nep_spin/spin_policy.cu new file mode 100644 index 000000000..8935b9fce --- /dev/null +++ b/src/main_nep/nep_spin/spin_policy.cu @@ -0,0 +1,318 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#include "spin_policy.cuh" +#include "rotation_response.cuh" +#include "utilities/error.cuh" +#include +#include +#include +#include +namespace fitness_spin { +void finalize_q_scaler(Spin_Parameters& para, int deviceCount) +{ + std::vector global_max(para.dim, -1.0e10f); + std::vector global_min(para.dim, 1.0e10f); + std::vector device_max(para.dim); + std::vector device_min(para.dim); + std::vector global_square_sum(para.dim, 0.0); + std::vector global_count(para.dim, 0); + std::vector device_square_sum(para.dim); + std::vector device_count(para.dim); + for (int device_id = 0; device_id < deviceCount; ++device_id) { + CHECK(gpuSetDevice(device_id)); + para.q_scaler_max[device_id].copy_to_host(device_max.data()); + para.q_scaler_min[device_id].copy_to_host(device_min.data()); + para.q_scaler_square_sum[device_id].copy_to_host(device_square_sum.data()); + para.q_scaler_count[device_id].copy_to_host(device_count.data()); + for (int d = 0; d < para.dim; ++d) { + global_max[d] = std::max(global_max[d], device_max[d]); + global_min[d] = std::min(global_min[d], device_min[d]); + global_square_sum[d] += device_square_sum[d]; + global_count[d] += device_count[d]; + } + } + + int unresolved_channels = 0; + for (int d = 0; d < para.dim; ++d) { + const float range = global_max[d] - global_min[d]; + const float magnitude = std::max( + 1.0f, std::max(std::abs(global_max[d]), std::abs(global_min[d]))); + const float resolution = + 64.0f * std::numeric_limits::epsilon() * magnitude; + if (!std::isfinite(range)) { + PRINT_INPUT_ERROR( + "Cannot initialize Spin NEP q_scaler from a non-finite " + "descriptor channel.\n"); + } + if (d >= para.dim_struct) { + const float rms = global_count[d] == 0 + ? 0.0f + : static_cast(std::sqrt( + global_square_sum[d] / static_cast(global_count[d]))); + if (!std::isfinite(rms)) { + PRINT_INPUT_ERROR("Cannot initialize Spin3 q_scaler from non-finite RMS.\n"); + } + para.q_scaler_cpu[d] = 1.0f / std::max(1.0f, std::max(range, rms)); + if (range <= resolution && rms <= resolution) { + ++unresolved_channels; + } + } else { + if (range <= 1.0e-10f) { + PRINT_INPUT_ERROR( + "Cannot initialize Spin NEP q_scaler from a constant " + "descriptor channel.\n"); + } + para.q_scaler_cpu[d] = 1.0f / range; + } + } + if (unresolved_channels > 0) { + printf( + "Spin3 q_scaler kept at 1 for %d numerically unresolved " + "descriptor channel(s).\n", + unresolved_channels); + } + for (int device_id = 0; device_id < deviceCount; ++device_id) { + CHECK(gpuSetDevice(device_id)); + para.q_scaler_gpu[device_id].copy_from_host(para.q_scaler_cpu.data()); + } + CHECK(gpuSetDevice(0)); +} +void print_loss_header(bool split_mforce) +{ + printf( + "%-8s%-11s%-11s%-11s%-11s%-11s%-11s%-11s%-11s%-11s%-11s%-11s%-11s%-11s", + "Step", + "Total", + "L1Reg", + "L2Reg", + "E-Train", + "F-Train", + "V-Train", + "M-Train", + "T-Train", + "E-Test", + "F-Test", + "V-Test", + "M-Test", + "T-Test"); + if (split_mforce) printf(" M-parallel-Train M-perp-Train M-parallel-Test M-perp-Test"); + printf("\n"); +} +void derive_spin_response_tangents( + const Spin_Parameters& para, + std::vector& structures) +{ + std::map> groups; + for (auto& structure : structures) { + structure.label.has_spin_response = 0; + structure.label.spin_tangent_x.clear(); + structure.label.spin_tangent_y.clear(); + structure.label.spin_tangent_z.clear(); + if (structure.label.has_spin_response_metadata && + structure.label.spin_response_probe == "rotation") { + if (!std::isfinite(structure.label.spin_response_coordinate)) { + PRINT_INPUT_ERROR("response_coordinate must be finite."); + } + groups[structure.label.spin_response_group].push_back(&structure); + } + } + if (groups.empty()) { + PRINT_INPUT_ERROR( + "lambda_spin_response requires rotation response frames in response.xyz.\n"); + } + + const auto differs = [](const float left, const float right) { + return !std::isfinite(left) || !std::isfinite(right) || + std::abs(static_cast(left) - static_cast(right)) > 1.0e-6; + }; + for (auto& item : groups) { + auto& members = item.second; + std::sort(members.begin(), members.end(), [](const Spin_Frame* left, const Spin_Frame* right) { + return left->label.spin_response_coordinate < right->label.spin_response_coordinate; + }); + if (members.size() < 3) { + PRINT_INPUT_ERROR( + "Each rotation response_group needs at least three distinct " + "response_coordinate values.\n"); + } + const Spin_Frame& reference = *members.front(); + for (std::size_t k = 0; k < members.size(); ++k) { + Spin_Frame& structure = *members[k]; + if (!std::isfinite(structure.label.spin_response_coordinate)) { + PRINT_INPUT_ERROR("response_coordinate must be finite.\n"); + } + if (k > 0 && + structure.label.spin_response_coordinate == members[k - 1]->label.spin_response_coordinate) { + PRINT_INPUT_ERROR( + "Each rotation response_group needs distinct response_coordinate values.\n"); + } + if (!structure.label.has_mforce) { + PRINT_INPUT_ERROR( + "Each rotation response frame requires mforce:R:3.\n"); + } + if (structure.geometry.num_atom != reference.geometry.num_atom || + structure.geometry.type != reference.geometry.type) { + PRINT_INPUT_ERROR( + "A rotation response_group cannot change atom count, type, or order.\n"); + } + for (int d = 0; d < 9; ++d) { + if (differs(structure.geometry.box_original[d], reference.geometry.box_original[d])) { + PRINT_INPUT_ERROR( + "A rotation response_group cannot change its cell.\n"); + } + } + for (int atom = 0; atom < structure.geometry.num_atom; ++atom) { + if (differs(structure.geometry.x[atom], reference.geometry.x[atom]) || + differs(structure.geometry.y[atom], reference.geometry.y[atom]) || + differs(structure.geometry.z[atom], reference.geometry.z[atom])) { + PRINT_INPUT_ERROR( + "A rotation response_group cannot change atomic positions.\n"); + } + if (!std::isfinite(structure.label.mfx[atom]) || !std::isfinite(structure.label.mfy[atom]) || + !std::isfinite(structure.label.mfz[atom])) { + PRINT_INPUT_ERROR("Magnetic forces in response.xyz must be finite."); + } + if (!std::isfinite(structure.label.sx[atom]) || + !std::isfinite(structure.label.sy[atom]) || + !std::isfinite(structure.label.sz[atom])) { + PRINT_INPUT_ERROR( + "Converged DFT spins in a rotation response_group must be finite.\n"); + } + } + structure.label.spin_tangent_x.resize(structure.geometry.num_atom); + structure.label.spin_tangent_y.resize(structure.geometry.num_atom); + structure.label.spin_tangent_z.resize(structure.geometry.num_atom); + } + + double tangent_power = 0.0; + for (std::size_t k = 0; k < members.size(); ++k) { + const std::size_t first = k == 0 ? 0 : (k + 1 == members.size() ? k - 2 : k - 1); + const std::size_t second = first + 1; + const std::size_t third = first + 2; + const double x0 = members[first]->label.spin_response_coordinate; + const double x1 = members[second]->label.spin_response_coordinate; + const double x2 = members[third]->label.spin_response_coordinate; + const double x = members[k]->label.spin_response_coordinate; + const double w0 = (2.0 * x - x1 - x2) / ((x0 - x1) * (x0 - x2)); + const double w1 = (2.0 * x - x0 - x2) / ((x1 - x0) * (x1 - x2)); + const double w2 = (2.0 * x - x0 - x1) / ((x2 - x0) * (x2 - x1)); + Spin_Frame& output = *members[k]; + for (int atom = 0; atom < output.geometry.num_atom; ++atom) { + const bool active = para.spin_dof_type_active[output.geometry.type[atom]] != 0; + std::array tangent = {{0.0, 0.0, 0.0}}; + if (active) { + const std::array center = {{ + output.label.sx[atom], output.label.sy[atom], output.label.sz[atom]}}; + const std::size_t nodes[] = {first, second, third}; + const double weights[] = {w0, w1, w2}; + for (int j = 0; j < 3; ++j) { + const auto& node = *members[nodes[j]]; + std::array delta; + if (!rotation_displacement(center, {{node.label.sx[atom], node.label.sy[atom], node.label.sz[atom]}}, delta)) { + PRINT_INPUT_ERROR( + "Antipodal spins in response rotation stencil; add intermediate rotation frames.\n"); + } + for (int d = 0; d < 3; ++d) tangent[d] += weights[j] * delta[d]; + } + } + output.label.spin_tangent_x[atom] = static_cast(tangent[0]); + output.label.spin_tangent_y[atom] = static_cast(tangent[1]); + output.label.spin_tangent_z[atom] = static_cast(tangent[2]); + if (active) { + for (double value : tangent) tangent_power += value * value; + } + } + output.label.has_spin_response = 1; + } + if (tangent_power == 0.0) { + PRINT_INPUT_ERROR( + "A rotation response_group must contain a changing converged DFT spin path.\n"); + } + } +} +void ResponseLoss::append( + const int device_id, + Dataset& dataset, Spin_Data& spin_data) +{ + CHECK(gpuSetDevice(device_id)); + spin_data.mforce.copy_to_host(spin_data.mforce_cpu.data()); + for (int nc = 0; nc < dataset.Nc; ++nc) { + const auto& structure = spin_data.labels[nc]; + if (!structure.has_spin_response) { + continue; + } + double prediction = 0.0; + double target = 0.0; + const int atom_offset = dataset.Na_sum_cpu[nc]; + for (int na = 0; na < dataset.structures[nc].num_atom; ++na) { + const int atom = atom_offset + na; + prediction += + spin_data.mforce_cpu[atom] * structure.spin_tangent_x[na] + + spin_data.mforce_cpu[dataset.N + atom] * structure.spin_tangent_y[na] + + spin_data.mforce_cpu[2 * dataset.N + atom] * structure.spin_tangent_z[na]; + target += + structure.mfx[na] * structure.spin_tangent_x[na] + + structure.mfy[na] * structure.spin_tangent_y[na] + + structure.mfz[na] * structure.spin_tangent_z[na]; + } + points_.push_back({ + structure.spin_response_group, + structure.spin_response_coordinate, + prediction, + target}); + } +} +static double huber_loss(const double residual) +{ + const double absolute = std::abs(residual); + return absolute <= 1.0 ? 0.5 * residual * residual : absolute - 0.5; +} +float ResponseLoss::value() const +{ + std::map> groups; + for (const auto& point : points_) { + groups[point.group].push_back(&point); + } + if (groups.empty()) { + return 0.0f; + } + + double shape_loss = 0.0; + double mean_loss = 0.0; + for (const auto& item : groups) { + const auto& members = item.second; + // Equal group weighting also requires a group-local target scale: a strong + // exchange scan must not suppress a weak anisotropy scan. Retain the + // absolute floor for zero/near-zero reference responses. + double target_power = 0.0; + for (const auto* point : members) target_power += point->target * point->target; + const double scale = std::max(std::sqrt(target_power / members.size()), 1.0e-6); + double mean_prediction = 0.0; + double mean_target = 0.0; + for (const auto* point : members) { + mean_prediction += point->prediction; + mean_target += point->target; + } + mean_prediction /= members.size(); + mean_target /= members.size(); + double group_shape_loss = 0.0; + for (const auto* point : members) { + const double residual = + ((point->prediction - mean_prediction) - + (point->target - mean_target)) / scale; + group_shape_loss += huber_loss(residual); + } + shape_loss += group_shape_loss / members.size(); + mean_loss += huber_loss((mean_prediction - mean_target) / scale); + } + shape_loss /= groups.size(); + mean_loss /= groups.size(); + return static_cast(shape_loss + 0.25 * mean_loss); +} +} diff --git a/src/main_nep/nep_spin/spin_policy.cuh b/src/main_nep/nep_spin/spin_policy.cuh new file mode 100644 index 000000000..6d6e8c77c --- /dev/null +++ b/src/main_nep/nep_spin/spin_policy.cuh @@ -0,0 +1,30 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#pragma once +#include "spin_data.cuh" +namespace fitness_spin { +void derive_spin_response_tangents(const Spin_Parameters&, std::vector&); +void finalize_q_scaler(Spin_Parameters&, int); +void print_loss_header(bool split_mforce); +class ResponseLoss { +public: + void append(int device_id, Dataset& dataset, Spin_Data& spin_data); + float value() const; + +private: + struct Point { + std::string group; + double coordinate; + double prediction; + double target; + }; + std::vector points_; +}; + +} diff --git a/src/main_nep/nep_spin/spin_reader.cu b/src/main_nep/nep_spin/spin_reader.cu new file mode 100644 index 000000000..17ae7b2c2 --- /dev/null +++ b/src/main_nep/nep_spin/spin_reader.cu @@ -0,0 +1,146 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD and is distributed under LGPLv3 or later. + + Spin3 training shares its descriptor and derivative implementation with + the production NEP_Spin runtime. +*/ + +#include "spin_data.cuh" +#include "spin_policy.cuh" +#include "main_nep/xyz_reader.cuh" +#include "utilities/read_file.cuh" +#include "utilities/error.cuh" +#include +#include +#include +#include + +static std::string frame_key(const Structure& geometry, const Spin_Labels& label) { + std::ostringstream key; key << std::hexfloat; + for (int t:geometry.type) key << t << ','; + key << ';'; for (float x:geometry.box_original) key << x << ','; + for (const auto* values:{&geometry.x,&geometry.y,&geometry.z,&label.sx,&label.sy,&label.sz}) { + key << ';'; for (float x:*values) key << x << ','; + } + return key.str(); +} +float Spin_Reader::geometry_cutoff() const { return std::max(parameters.rc_radial_max,parameters.spin_cutoff); } + +void Spin_Reader::read_structure(const XYZ_Record& record, Structure& structure) { + NEP_Energy_Reader::read_structure(record,structure); + labels.emplace_back(); + auto& label=labels.back(); + int spin_offset=-1, mforce_offset=-1, offset=0; + for (int k=0; k=0) PRINT_INPUT_ERROR("Only one spin or magnetic-force property alias is allowed."); + slot=offset; + } + offset+=count; + } + if (spin_offset<0) PRINT_INPUT_ERROR("spin_version 1 requires spin/spins/moment/moments with property type R:3."); + label.has_mforce=mforce_offset>=0; + for (auto* values:{&label.sx,&label.sy,&label.sz,&label.mfx,&label.mfy,&label.mfz}) values->resize(structure.num_atom,0.0f); + for (int a=0;a& structures, int batch_size, int& batches, std::vector& sizes) { + for (const auto& structure:structures) { + const auto& label=labels.at(structure.index_in_file); + if (label.has_spin_response_metadata) train_groups.insert(label.spin_response_group); + } + NEP_Energy_Reader::prepare_train(structures,batch_size,batches,sizes); +} +void Spin_Reader::prepare_test(const std::vector& structures, bool has_test_set) { + for (const auto& structure:structures) { + const auto& label=labels.at(structure.index_in_file); + if (label.has_spin_response_metadata) { + test_groups.insert(label.spin_response_group); + if (parameters.lambda_spin_response>0 && train_groups.count(label.spin_response_group)) + PRINT_INPUT_ERROR("response_group leakage between train.xyz and test.xyz."); + } + test_frames.insert(frame_key(structure,label)); + } + NEP_Energy_Reader::prepare_test(structures,has_test_set); +} +void Spin_Reader::prepare_dataset(Dataset& dataset) { + NEP_Energy_Reader::prepare_dataset(dataset); + data.create(dataset).construct(parameters,dataset,labels); +} +const char* Spin_Reader::energy_difference_conflict(const Structure& a, const Structure& b) const { + const char* conflict=NEP_Energy_Reader::energy_difference_conflict(a,b); + if (!conflict) return nullptr; + const auto& x=labels.at(a.index_in_file);const auto& y=labels.at(b.index_in_file); + for (int i=0;i1e-5f || std::abs(x.sy[i]-y.sy[i])>1e-5f || std::abs(x.sz[i]-y.sz[i])>1e-5f) return nullptr; + } + return "have the same geometry and spins, for which the model predicts the same energy."; +} +void Spin_Reader::read_response(std::vector& structures, std::vector& response_labels) { + std::ifstream input("response.xyz"); + if (!input.is_open()) PRINT_INPUT_ERROR("lambda_spin_response > 0 requires response.xyz."); + XYZ_Reader reader(input,"response.xyz"); XYZ_Record record; + begin_reading(); + while(reader.read(record)) { + structures.emplace_back(); read_structure(record,structures.back()); + const auto& label=labels.back(); + if (!label.has_spin_response_metadata || label.spin_response_probe!="rotation") + PRINT_INPUT_ERROR("Every response.xyz frame must have complete rotation response metadata."); + if (test_groups.count(label.spin_response_group)) PRINT_INPUT_ERROR("response_group leakage between response.xyz and test.xyz."); + if (test_frames.count(frame_key(structures.back(),label))) PRINT_INPUT_ERROR("Response frame leakage between response.xyz and test.xyz."); + } + std::vector frames; + for (int i=0;i tokens = get_tokens_without_comments(input); if (tokens.empty()) { @@ -38,7 +39,25 @@ ParameterInput::ParameterInput() for (int n = 0; n < tokens.size(); ++n) { param[n] = tokens[n].c_str(); } - if (tokens[0] == "model_type") { + if (tokens[0] == "spin_version" || tokens[0] == "spin_mode") { + if (has_spin_selector) { + PRINT_INPUT_ERROR("Specify spin_version only once; do not combine it with spin_mode."); + } + has_spin_selector = true; + if (tokens[0] == "spin_version") { + if (tokens.size() != 2 || tokens[1] != "1") { + PRINT_INPUT_ERROR("Unsupported spin_version (expected 1)."); + } + spin_version = 1; + } else { + // Read compatibility for inputs predating the versioned Spin model. + int mode = 0; + if (param.size() != 2 || !is_valid_int(param[1], &mode) || (mode != 0 && mode != 3)) { + PRINT_INPUT_ERROR("spin_mode should be 0 or 3."); + } + spin_version = mode == 3 ? 1 : 0; + } + } else if (tokens[0] == "model_type") { parse_model_type(param.data(), param.size()); } else if (tokens[0] == "charge_mode") { parse_charge_mode(param.data(), param.size()); @@ -50,6 +69,9 @@ ParameterInput::ParameterInput() keywords.push_back(tokens); } } + if (spin_version && (model_type != 0 || charge_mode || vdw || charge_vdw)) { + PRINT_INPUT_ERROR("Spin NEP only supports a NEP4 potential model without charge/vdW."); + } if ((charge_mode > 0) + vdw + charge_vdw > 1) { PRINT_INPUT_ERROR("charge_mode, vdw, and charge_vdw cannot be enabled simultaneously."); } diff --git a/src/main_nep/parameter_input.cuh b/src/main_nep/parameter_input.cuh index 2dc697651..77eabc939 100644 --- a/src/main_nep/parameter_input.cuh +++ b/src/main_nep/parameter_input.cuh @@ -23,6 +23,7 @@ class ParameterInput public: ParameterInput(); int model_type = 0; + int spin_version = 0; // zero means the Spin model was not selected int charge_mode = 0; int vdw = 0; int charge_vdw = 0; diff --git a/src/main_nep/parameters.cu b/src/main_nep/parameters.cu index 399ddaf76..d8636e4c1 100644 --- a/src/main_nep/parameters.cu +++ b/src/main_nep/parameters.cu @@ -280,7 +280,7 @@ void Parameters::parse_initial_para(const char** param, int num_param) } initial_para = initial_para_tmp; - if (initial_para < 0.1f || initial_para > 1.0f) { + if (!std::isfinite(initial_para_tmp) || initial_para < 0.1f || initial_para > 1.0f) { PRINT_INPUT_ERROR("initial_para should be within [0.1, 1]."); } } diff --git a/src/main_nep/potential.cu b/src/main_nep/potential.cu index 89321555f..39d7bd275 100644 --- a/src/main_nep/potential.cu +++ b/src/main_nep/potential.cu @@ -14,6 +14,7 @@ */ #include "potential.cuh" +#include "nep_spin/nep_spin.cuh" #include "main_nep/nep/nep.cuh" #include "main_nep/nep_vdw/nep_vdw.cuh" #include "main_nep/nep_charge/nep_charge.cuh" @@ -25,7 +26,9 @@ std::unique_ptr create_potential() { ParameterInput input; std::unique_ptr potential; - if (input.model_type == 1 || input.model_type == 2) { + if (input.spin_version) { + potential.reset(new NEP_Spin_Model(input)); + } else if (input.model_type == 1 || input.model_type == 2) { potential.reset(new TNEP(input)); } else { if (input.charge_vdw) { diff --git a/src/main_nep/structure.cu b/src/main_nep/structure.cu index 2a75cc157..4569fb912 100644 --- a/src/main_nep/structure.cu +++ b/src/main_nep/structure.cu @@ -36,7 +36,7 @@ static float get_det(const float* box) box[2] * (box[3] * box[7] - box[4] * box[6]); } -static void change_box(const NEP_Parameters& para, Structure& structure) +static void change_box(float cutoff, Structure& structure) { float a[3] = {structure.box_original[0], structure.box_original[3], structure.box_original[6]}; float b[3] = {structure.box_original[1], structure.box_original[4], structure.box_original[7]}; @@ -45,11 +45,11 @@ static void change_box(const NEP_Parameters& para, Structure& structure) structure.volume = abs(det); if (structure.pbc) { structure.num_cell[0] = - int(ceil(2.0f * para.rc_radial_max / (structure.volume / get_area(b, c)))); + int(ceil(2.0f * cutoff / (structure.volume / get_area(b, c)))); structure.num_cell[1] = - int(ceil(2.0f * para.rc_radial_max / (structure.volume / get_area(c, a)))); + int(ceil(2.0f * cutoff / (structure.volume / get_area(c, a)))); structure.num_cell[2] = - int(ceil(2.0f * para.rc_radial_max / (structure.volume / get_area(a, b)))); + int(ceil(2.0f * cutoff / (structure.volume / get_area(a, b)))); } else { structure.num_cell[0] = 1; structure.num_cell[1] = 1; @@ -115,7 +115,7 @@ void NEP_Data_Reader::read_geometry(const XYZ_Record& record, Structure& structu xyz_filename.c_str(), line_number); } - change_box(para, structure); + change_box(geometry_cutoff(), structure); } } if (!has_lattice_in_exyz) { @@ -344,3 +344,5 @@ bool NEP_Data_Reader::read_structures(bool is_train, std::vector& str return has_test_set; } + +float NEP_Data_Reader::geometry_cutoff() const { return para.rc_radial_max; } diff --git a/src/main_nep/structure.cuh b/src/main_nep/structure.cuh index 92b6e3011..e9fb3062c 100644 --- a/src/main_nep/structure.cuh +++ b/src/main_nep/structure.cuh @@ -65,6 +65,7 @@ public: protected: NEP_Parameters& para; virtual void begin_reading() {} + virtual float geometry_cutoff() const; virtual void read_structure(const XYZ_Record& record, Structure& structure); virtual void print_summary(const std::vector& structures) const {} void read_geometry(const XYZ_Record& record, Structure& structure) const; diff --git a/src/makefile b/src/makefile index 8c2bdecfc..2522ff3b3 100644 --- a/src/makefile +++ b/src/makefile @@ -40,6 +40,7 @@ LIBS = -lcublas -lcusolver -lcufft NEP_LIBS = GNEP_LIBS = ifndef OS +LIBS += -lpthread NEP_LIBS += -ldl GNEP_LIBS += -lpthread endif @@ -52,7 +53,7 @@ SOURCES_GPUMD = \ $(wildcard main_gpumd/*.cu) \ $(wildcard minimize/*.cu) \ $(wildcard phonon/*.cu) \ - $(wildcard integrate/*.cu) \ + $(wildcard integrate/*.cu) $(wildcard integrate/spin/*.cu) \ $(wildcard mc/*.cu) \ $(wildcard force/*.cu) \ $(wildcard force/*/*.cu) \ @@ -88,7 +89,7 @@ endif HEADERS = \ $(wildcard utilities/*.cuh) \ $(wildcard main_gpumd/*.cuh) \ - $(wildcard integrate/*.cuh) \ + $(wildcard integrate/*.cuh) $(wildcard integrate/spin/*.cuh) \ $(wildcard mc/*.cuh) \ $(wildcard minimize/*.cuh) \ $(wildcard force/*.cuh) \ diff --git a/src/makefile.hip b/src/makefile.hip index cc8b912f2..531599b00 100644 --- a/src/makefile.hip +++ b/src/makefile.hip @@ -30,7 +30,7 @@ SOURCES_GPUMD = \ $(wildcard main_gpumd/*.cu) \ $(wildcard minimize/*.cu) \ $(wildcard phonon/*.cu) \ - $(wildcard integrate/*.cu) \ + $(wildcard integrate/*.cu) $(wildcard integrate/spin/*.cu) \ $(wildcard mc/*.cu) \ $(wildcard force/*.cu) \ $(wildcard force/*/*.cu) \ @@ -56,7 +56,7 @@ OBJ_NEP = $(SOURCES_NEP:.cu=.o) HEADERS = \ $(wildcard utilities/*.cuh) \ $(wildcard main_gpumd/*.cuh) \ - $(wildcard integrate/*.cuh) \ + $(wildcard integrate/*.cuh) $(wildcard integrate/spin/*.cuh) \ $(wildcard mc/*.cuh) \ $(wildcard minimize/*.cuh) \ $(wildcard force/*.cuh) \ diff --git a/src/makefile_wpe b/src/makefile_wpe index defa64d6c..0492644a6 100644 --- a/src/makefile_wpe +++ b/src/makefile_wpe @@ -121,7 +121,7 @@ SOURCES_GPUMD = \ $(wildcard main_gpumd/*.cu) \ $(wildcard minimize/*.cu) \ $(wildcard phonon/*.cu) \ - $(wildcard integrate/*.cu) \ + $(wildcard integrate/*.cu) $(wildcard integrate/spin/*.cu) \ $(wildcard mc/*.cu) \ $(wildcard force/*.cu) \ $(wildcard force/*/*.cu) \ @@ -151,7 +151,7 @@ OBJECTS = $(OBJ_GPUMD) $(WPE_ADAPTER_OBJ) $(WPE_STAGE_OBJ) HEADERS = \ $(wildcard utilities/*.cuh) \ $(wildcard main_gpumd/*.cuh) \ - $(wildcard integrate/*.cuh) \ + $(wildcard integrate/*.cuh) $(wildcard integrate/spin/*.cuh) \ $(wildcard mc/*.cuh) \ $(wildcard minimize/*.cuh) \ $(wildcard force/*.cuh) \ diff --git a/src/measure/dump_restart.cu b/src/measure/dump_restart.cu index d7b83ad66..9e0ec1fe0 100644 --- a/src/measure/dump_restart.cu +++ b/src/measure/dump_restart.cu @@ -17,7 +17,9 @@ Dump a restart file --------------------------------------------------------------------------------------------------*/ +#include "integrate/spin/restart.cuh" #include "dump_restart.cuh" +#include "integrate/integrate.cuh" #include "model/box.cuh" #include "model/group.cuh" #include "utilities/common.cuh" @@ -89,6 +91,12 @@ void Dump_Restart::end_of_step( atom.position_per_atom.copy_to_host(atom.cpu_position_per_atom.data()); atom.velocity_per_atom.copy_to_host(atom.cpu_velocity_per_atom.data()); + if (atom.has_spin) { + atom.spin_per_atom.copy_to_host(atom.cpu_spin_per_atom.data()); + if (atom.spin_velocity_initialized) { + atom.spin_velocity_per_atom.copy_to_host(atom.cpu_spin_velocity_per_atom.data()); + } + } fprintf(fid, "%d\n", number_of_atoms); @@ -108,11 +116,18 @@ void Dump_Restart::end_of_step( box.cpu_h[5], box.cpu_h[8]); - if (group.size() == 0) { - fprintf(fid, "Properties=species:S:1:pos:R:3:mass:R:1:vel:R:3\n"); - } else { - fprintf(fid, "Properties=species:S:1:pos:R:3:mass:R:1:vel:R:3:group:I:%d\n", int(group.size())); + const bool spin_checkpoint = write_spin_restart(fid, atom, integrate, global_time); + fprintf(fid, "Properties=species:S:1:pos:R:3:mass:R:1:vel:R:3"); + if (atom.has_spin) { + fprintf(fid, ":spin:R:3"); + if (atom.spin_velocity_initialized) { + fprintf(fid, ":spin_vel:R:3"); + } } + if (!group.empty()) { + fprintf(fid, ":group:I:%d", int(group.size())); + } + fprintf(fid, "\n"); for (int n = 0; n < number_of_atoms; n++) { const double natural_to_A_per_fs = 1.0 / TIME_UNIT_CONVERSION; @@ -128,6 +143,23 @@ void Dump_Restart::end_of_step( atom.cpu_velocity_per_atom[n + number_of_atoms] * natural_to_A_per_fs, atom.cpu_velocity_per_atom[n + 2 * number_of_atoms] * natural_to_A_per_fs); + if (atom.has_spin) { + fprintf( + fid, + spin_checkpoint ? "%.17g %.17g %.17g " : "%g %g %g ", + atom.cpu_spin_per_atom[n], + atom.cpu_spin_per_atom[n + number_of_atoms], + atom.cpu_spin_per_atom[n + 2 * number_of_atoms]); + if (atom.spin_velocity_initialized) { + fprintf( + fid, + "%g %g %g ", + atom.cpu_spin_velocity_per_atom[n] * natural_to_A_per_fs, + atom.cpu_spin_velocity_per_atom[n + number_of_atoms] * natural_to_A_per_fs, + atom.cpu_spin_velocity_per_atom[n + 2 * number_of_atoms] * natural_to_A_per_fs); + } + } + for (int m = 0; m < group.size(); ++m) { fprintf(fid, "%d ", group[m].cpu_label[n]); } diff --git a/src/measure/dump_xyz.cu b/src/measure/dump_xyz.cu index 2ae27f6f8..7c30d813c 100644 --- a/src/measure/dump_xyz.cu +++ b/src/measure/dump_xyz.cu @@ -116,6 +116,18 @@ void Dump_XYZ::parse( bool precision_seen = false; for (int m = 3; m < num_param; ++m) { + if (tokens[m] == "spin") { + has_spin_ = true; + continue; + } + if (tokens[m] == "mforce") { + has_mforce_ = true; + continue; + } + if (tokens[m] == "spin_velocity") { + has_spin_velocity_ = true; + continue; + } if (tokens[m] == "group") { if (group_seen) { PRINT_INPUT_ERROR("Option 'group' is specified more than once in dump_xyz.\n"); @@ -174,6 +186,22 @@ void Dump_XYZ::pre_run( if (quantities.has_force_) { cpu_force_per_atom_.resize(atom.number_of_atoms * 3); } + if ((has_spin_ || has_mforce_ || has_spin_velocity_) && + !atom.has_spin) { + PRINT_INPUT_ERROR("dump_xyz spin quantities require spin:R:3 in model.xyz."); + } + if (has_spin_velocity_ && !atom.spin_velocity_initialized) { + PRINT_INPUT_ERROR("dump_xyz spin_velocity requires initialized spin_vel:R:3."); + } + if (has_spin_) { + cpu_spin_per_atom_.resize(atom.number_of_atoms * 3); + } + if (has_mforce_) { + cpu_mforce_per_atom_.resize(atom.number_of_atoms * 3); + } + if (has_spin_velocity_) { + cpu_spin_velocity_per_atom_.resize(atom.number_of_atoms * 3); + } if (quantities.has_potential_) { cpu_potential_per_atom_.resize(atom.number_of_atoms); } @@ -280,6 +308,15 @@ void Dump_XYZ::output_line2( if (quantities.has_force_) { fprintf(fid_, ":forces:R:3"); } + if (has_spin_) { + fprintf(fid_, ":spin:R:3"); + } + if (has_mforce_) { + fprintf(fid_, ":mforce:R:3"); + } + if (has_spin_velocity_) { + fprintf(fid_, ":spin_vel:R:3"); + } if (quantities.has_potential_) { fprintf(fid_, ":energy_atom:R:1"); } @@ -342,6 +379,15 @@ void Dump_XYZ::end_of_step( if (quantities.has_force_) { atom.force_per_atom.copy_to_host(cpu_force_per_atom_.data()); } + if (has_spin_) { + atom.spin_per_atom.copy_to_host(cpu_spin_per_atom_.data()); + } + if (has_mforce_) { + atom.mforce_per_atom.copy_to_host(cpu_mforce_per_atom_.data()); + } + if (has_spin_velocity_) { + atom.spin_velocity_per_atom.copy_to_host(cpu_spin_velocity_per_atom_.data()); + } if (quantities.has_potential_) { atom.potential_per_atom.copy_to_host(cpu_potential_per_atom_.data()); } @@ -401,6 +447,25 @@ void Dump_XYZ::end_of_step( fprintf(fid_, fmt_.c_str(), cpu_force_per_atom_[m + atom.number_of_atoms * d]); } } + if (has_spin_) { + for (int d = 0; d < 3; ++d) { + fprintf(fid_, fmt_.c_str(), cpu_spin_per_atom_[m + atom.number_of_atoms * d]); + } + } + if (has_mforce_) { + for (int d = 0; d < 3; ++d) { + fprintf(fid_, fmt_.c_str(), cpu_mforce_per_atom_[m + atom.number_of_atoms * d]); + } + } + if (has_spin_velocity_) { + const double natural_to_per_fs = 1.0 / TIME_UNIT_CONVERSION; + for (int d = 0; d < 3; ++d) { + fprintf( + fid_, + fmt_.c_str(), + cpu_spin_velocity_per_atom_[m + atom.number_of_atoms * d] * natural_to_per_fs); + } + } if (quantities.has_potential_) { fprintf(fid_, fmt_.c_str(), cpu_potential_per_atom_[m]); } diff --git a/src/measure/dump_xyz.cuh b/src/measure/dump_xyz.cuh index 6b9708e09..9a838ed31 100644 --- a/src/measure/dump_xyz.cuh +++ b/src/measure/dump_xyz.cuh @@ -70,6 +70,9 @@ private: int dump_interval_ = 1; int precision_ = 1; // 1 = single precision, 2 = double DumpQuantities quantities; + bool has_spin_ = false; + bool has_mforce_ = false; + bool has_spin_velocity_ = false; int separated_ = 0; std::string filename_; std::string fmt_; @@ -77,6 +80,9 @@ private: std::vector cpu_unwrapped_position_; std::vector cpu_force_per_atom_; + std::vector cpu_spin_per_atom_; + std::vector cpu_mforce_per_atom_; + std::vector cpu_spin_velocity_per_atom_; std::vector cpu_potential_per_atom_; std::vector cpu_virial_per_atom_; GPU_Vector gpu_total_virial_; diff --git a/src/model/atom.cuh b/src/model/atom.cuh index b9551bda8..e5940dac2 100644 --- a/src/model/atom.cuh +++ b/src/model/atom.cuh @@ -14,8 +14,10 @@ */ #pragma once +#include "integrate/spin/restart.cuh" #include "utilities/gpu_vector.cuh" #include +#include #include class Box; @@ -30,6 +32,8 @@ public: std::vector cpu_charge; // float is sufficient for charge std::vector cpu_position_per_atom; std::vector cpu_velocity_per_atom; + std::vector cpu_spin_per_atom; + std::vector cpu_spin_velocity_per_atom; std::vector cpu_atom_symbol; GPU_Vector type; // per-atom type (1 component) GPU_Vector mass; // per-atom mass (1 component) @@ -38,10 +42,16 @@ public: GPU_Vector position_image; // per-atom periodic image (3 components) GPU_Vector unwrapped_position; // unwrapped per-atom position (3 components) GPU_Vector velocity_per_atom; // per-atom velocity (3 components) + GPU_Vector spin_per_atom; // Cartesian magnetic moment (3 components) + GPU_Vector spin_velocity_per_atom; // spin velocity (3 components) + GPU_Vector mforce_per_atom; // -dE/dS (3 components) GPU_Vector force_per_atom; // per-atom force (3 components) GPU_Vector heat_per_atom; // per-atom heat current (5 components) GPU_Vector virial_per_atom; // per-atom virial (9 components) GPU_Vector potential_per_atom; // per-atom potential energy (1 component) + Spin_Lattice_Restart spin_lattice_restart; + bool has_spin = false; + bool spin_velocity_initialized = false; // for beads in PIMD int number_of_beads = 0; std::vector> position_beads; diff --git a/src/model/read_xyz.cu b/src/model/read_xyz.cu index 6f9aa911f..15122deda 100644 --- a/src/model/read_xyz.cu +++ b/src/model/read_xyz.cu @@ -17,6 +17,7 @@ The class defining the simulation model. ------------------------------------------------------------------------------*/ +#include "integrate/spin/restart.cuh" #include "atom.cuh" #include "box.cuh" #include "group.cuh" @@ -24,10 +25,12 @@ The class defining the simulation model. #include "utilities/common.cuh" #include "utilities/compact_nep.cuh" #include "utilities/error.cuh" +#include "utilities/read_file.cuh" #include "utilities/run_input.cuh" #include "utilities/gpu_macro.cuh" #include #include +#include #include #include #include @@ -160,9 +163,12 @@ static void read_xyz_line_2( int& has_velocity_in_xyz, bool& has_mass, bool& has_charge, + bool& has_spin, + bool& has_spin_velocity, int& num_columns, int* property_offset, - std::vector& group) + std::vector& group, + Atom& atom) { std::vector tokens = get_tokens_without_unwanted_spaces(input); for (auto& token : tokens) { @@ -170,6 +176,8 @@ static void read_xyz_line_2( token.begin(), token.end(), token.begin(), [](unsigned char c) { return std::tolower(c); }); } + read_spin_restart(tokens, atom); + box.pbc_x = box.pbc_y = box.pbc_z = 1; // default is periodic for (int n = 0; n < tokens.size(); ++n) { const std::string tmp_string = "pbc="; @@ -241,13 +249,19 @@ static void read_xyz_line_2( } // properties - const int num_properties = 6; - std::string property_name[num_properties] = {"species", "pos", "mass", "charge", "vel", "group"}; + const int num_properties = 8; + std::string property_name[num_properties] = { + "species", "pos", "mass", "charge", "vel", "group", "spin", "spin_vel"}; int property_position[num_properties] = { - -1, -1, -1, -1, -1, -1}; // species,pos,mass,charge,vel,group + -1, -1, -1, -1, -1, -1, -1, -1}; + bool found_properties = false; for (int n = 0; n < tokens.size(); ++n) { const std::string properties_string = "properties="; if (tokens[n].substr(0, properties_string.length()) == properties_string) { + if (found_properties) { + PRINT_INPUT_ERROR("Properties may be specified only once."); + } + found_properties = true; std::string line = tokens[n].substr(properties_string.length(), tokens[n].length()); for (auto& letter : line) { if (letter == ':') { @@ -258,11 +272,31 @@ static void read_xyz_line_2( for (int k = 0; k < sub_tokens.size() / 3; ++k) { for (int prop = 0; prop < num_properties; ++prop) { if (sub_tokens[k * 3] == property_name[prop]) { + if (property_position[prop] >= 0) { + PRINT_INPUT_ERROR("Duplicate property names are not allowed."); + } property_position[prop] = k; } } } + if (sub_tokens.size() % 3 != 0) { + PRINT_INPUT_ERROR("Properties must contain name:type:column-count triplets."); + } + for (int prop : {0, 1, 4, 6, 7}) { + if (property_position[prop] >= 0) { + const int base = property_position[prop] * 3; + const std::string expected_type = (prop == 0) ? "s" : "r"; + const int expected_columns = (prop == 0) ? 1 : 3; + if ( + sub_tokens[base + 1] != expected_type || + get_int_from_token(sub_tokens[base + 2], __FILE__, __LINE__) != expected_columns) { + PRINT_INPUT_ERROR( + "species must be S:1 and pos, vel, spin and spin_vel must be R:3."); + } + } + } + if (property_position[4] < 0) { has_velocity_in_xyz = 0; printf("Do not specify initial velocities here.\n"); @@ -309,6 +343,11 @@ static void read_xyz_line_2( } else { has_charge = true; } + has_spin = property_position[6] >= 0; + has_spin_velocity = property_position[7] >= 0; + if (has_spin_velocity && !has_spin) { + PRINT_INPUT_ERROR("spin_vel:R:3 requires spin:R:3."); + } } void read_xyz_in_line_3( @@ -317,6 +356,8 @@ void read_xyz_in_line_3( const int has_velocity_in_xyz, const bool has_mass, const bool has_charge, + const bool has_spin, + const bool has_spin_velocity, const int num_columns, const int* property_offset, int& number_of_types, @@ -327,6 +368,8 @@ void read_xyz_in_line_3( std::vector& cpu_charge, std::vector& cpu_position_per_atom, std::vector& cpu_velocity_per_atom, + std::vector& cpu_spin_per_atom, + std::vector& cpu_spin_velocity_per_atom, std::vector& group) { cpu_atom_symbol.resize(N); @@ -335,6 +378,8 @@ void read_xyz_in_line_3( cpu_charge.resize(N, 0.0); cpu_position_per_atom.resize(N * 3); cpu_velocity_per_atom.resize(N * 3); + cpu_spin_per_atom.resize(has_spin ? N * 3 : 0); + cpu_spin_velocity_per_atom.resize(has_spin ? N * 3 : 0, 0.0); number_of_types = atom_symbols.size(); for (int m = 0; m < group.size(); ++m) { @@ -388,6 +433,21 @@ void read_xyz_in_line_3( } } + if (has_spin) { + for (int d = 0; d < 3; ++d) { + cpu_spin_per_atom[n + N * d] = + get_double_from_token(tokens[property_offset[6] + d], __FILE__, __LINE__); + } + } + if (has_spin_velocity) { + const double spin_velocity_to_natural = TIME_UNIT_CONVERSION; + for (int d = 0; d < 3; ++d) { + cpu_spin_velocity_per_atom[n + N * d] = + get_double_from_token(tokens[property_offset[7] + d], __FILE__, __LINE__) * + spin_velocity_to_natural; + } + } + for (int m = 0; m < group.size(); ++m) { group[m].cpu_label[n] = get_int_from_token(tokens[property_offset[5] + m], __FILE__, __LINE__); @@ -493,12 +553,24 @@ void initialize_position( atom_symbols = get_atom_symbols(filename_potential); read_xyz_line_1(input, atom.number_of_atoms); - int property_offset[6] = {0, 0, 0, 0, 0, 0}; // species,pos,mass,vel,group + int property_offset[8] = {0, 0, 0, 0, 0, 0, 0, 0}; int num_columns = 0; bool has_mass = true; bool has_charge = true; + bool has_spin_velocity = false; read_xyz_line_2( - input, box, has_velocity_in_xyz, has_mass, has_charge, num_columns, property_offset, group); + input, + box, + has_velocity_in_xyz, + has_mass, + has_charge, + atom.has_spin, + has_spin_velocity, + num_columns, + property_offset, + group, + atom); + atom.spin_velocity_initialized = has_spin_velocity; read_xyz_in_line_3( input, @@ -506,6 +578,8 @@ void initialize_position( has_velocity_in_xyz, has_mass, has_charge, + atom.has_spin, + has_spin_velocity, num_columns, property_offset, number_of_types, @@ -516,6 +590,8 @@ void initialize_position( atom.cpu_charge, atom.cpu_position_per_atom, atom.cpu_velocity_per_atom, + atom.cpu_spin_per_atom, + atom.cpu_spin_velocity_per_atom, group); input.close(); @@ -560,6 +636,13 @@ void allocate_memory_gpu(std::vector& group, Atom& atom, GPU_Vector @@ -62,6 +63,7 @@ static bool is_compactable_nep(const std::vector& tokens) if (tokens.size() < 3) { return false; } + if (tokens[0].rfind("nep4_spin", 0) == 0) return false; return tokens[0].substr(0, 4) == "nep4" || NEP_Model_Input::is_new_format(tokens[0]); } @@ -419,7 +421,7 @@ void prepare_compact_nep_files( } std::vector first = get_first_line(potential_files.back()); - if (!is_compactable_nep(first)) { + if (!is_compactable_nep(first) || is_nep_spin_model_file(potential_files.back())) { return; } for (const std::string& filename : potential_files) { diff --git a/src/utilities/error.cu b/src/utilities/error.cu index 9f0a527b7..338d90fe6 100644 --- a/src/utilities/error.cu +++ b/src/utilities/error.cu @@ -145,7 +145,7 @@ std::vector get_tokens_without_unwanted_spaces(const std::string& l return tokens; } -std::vector get_tokens(std::ifstream& input) +std::vector get_tokens(std::istream& input) { std::string line; std::getline(input, line); diff --git a/src/utilities/error.cuh b/src/utilities/error.cuh index 3f7c1abe9..b3402680b 100644 --- a/src/utilities/error.cuh +++ b/src/utilities/error.cuh @@ -79,7 +79,7 @@ void print_line_1(void); void print_line_2(void); FILE* my_fopen(const char* filename, const char* mode); std::vector get_tokens(const std::string& line); -std::vector get_tokens(std::ifstream& input); +std::vector get_tokens(std::istream& input); std::vector get_tokens_without_comments(const std::string& line); std::vector get_tokens_without_comments(std::ifstream& input); std::vector get_tokens_without_unwanted_spaces(std::ifstream& input); diff --git a/src/utilities/fractional_region.cuh b/src/utilities/fractional_region.cuh new file mode 100644 index 000000000..08cf1bb86 --- /dev/null +++ b/src/utilities/fractional_region.cuh @@ -0,0 +1,46 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once + +#include "model/box.cuh" + +static __device__ void get_fractional_position( + const Box& box, + const double x, + const double y, + const double z, + double& sa, + double& sb, + double& sc) +{ + sa = box.cpu_h[9] * x + box.cpu_h[10] * y + box.cpu_h[11] * z; + sb = box.cpu_h[12] * x + box.cpu_h[13] * y + box.cpu_h[14] * z; + sc = box.cpu_h[15] * x + box.cpu_h[16] * y + box.cpu_h[17] * z; +} + +static __device__ bool is_in_region( + const double sa, + const double sb, + const double sc, + const double amin, + const double amax, + const double bmin, + const double bmax, + const double cmin, + const double cmax) +{ + return sa >= amin && sa < amax && sb >= bmin && sb < bmax && sc >= cmin && sc < cmax; +} diff --git a/src/utilities/gpu_vector.cuh b/src/utilities/gpu_vector.cuh index c3e6f4752..37dd06e7f 100644 --- a/src/utilities/gpu_vector.cuh +++ b/src/utilities/gpu_vector.cuh @@ -73,6 +73,7 @@ public: // only allocate memory void resize(const size_t size, const Memory_Type memory_type = Memory_Type::global) { + capacity_ = size; size_ = size; memory_ = size_ * sizeof(T); memory_type_ = memory_type; @@ -89,9 +90,23 @@ public: } } + // Change the logical length, retaining the allocation when it is large enough. + // Contents are unspecified after growth. Copies/fill use the logical length. + void resize_with_capacity(const size_t size) + { + if (!allocated_) { + resize(size ? size : 1); + } else if (size > capacity_) { + resize(size + size / 8 + 1); + } + size_ = size; + memory_ = size * sizeof(T); + } + // allocate memory and initialize void resize(const size_t size, const T value, const Memory_Type memory_type = Memory_Type::global) { + capacity_ = size; size_ = size; memory_ = size_ * sizeof(T); memory_type_ = memory_type; @@ -200,6 +215,7 @@ public: private: bool allocated_; // true for allocated memory + size_t capacity_ = 0; size_t size_; // number of elements size_t memory_; // memory in bytes Memory_Type memory_type_; // global or unified memory diff --git a/src/utilities/nep_model_input.cu b/src/utilities/nep_model_input.cu index 6fc96ea1c..801ae6bd4 100644 --- a/src/utilities/nep_model_input.cu +++ b/src/utilities/nep_model_input.cu @@ -16,6 +16,7 @@ #include "error.cuh" #include "nep_model_file.cuh" #include "nep_model_input.cuh" +#include "nep_spin_model_file.cuh" bool NEP_Model_Input::is_new_format(const std::string& token) { @@ -37,6 +38,11 @@ NEP_Model_Input::NEP_Model_Input(const std::string& filename) : file(filename) return; } + if (is_nep_spin_model_file(filename)) { + converted.str(read_nep_spin_model_input(filename)); + return; + } + NEP_Model_File model; std::string error; if (!model.read(file, error)) { diff --git a/src/utilities/nep_spin_legacy_parameters.cuh b/src/utilities/nep_spin_legacy_parameters.cuh new file mode 100644 index 000000000..394f82ac3 --- /dev/null +++ b/src/utilities/nep_spin_legacy_parameters.cuh @@ -0,0 +1,82 @@ +/* + Copyright 2017 Zheyong Fan and GPUMD development team + This file is part of GPUMD. + GPUMD is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + GPUMD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with GPUMD. If not, see . +*/ + +#pragma once + +#include + +// Convert between legacy Spin3 [basis][channel] file order and the +// [channel][basis] order used by training and the new block format. +inline void descriptor_parameters_to_channel_major( + float* parameters, + const int descriptor_offset, + const int num_channels, + const int n_max_radial, + const int n_max_angular, + const int basis_size_radial, + const int basis_size_angular) +{ + const int num_radial_basis = (n_max_radial + 1) * (basis_size_radial + 1); + const int num_angular_basis = (n_max_angular + 1) * (basis_size_angular + 1); + const int num_c_radial = num_channels * num_radial_basis; + const int num_descriptor_parameters = num_c_radial + num_channels * num_angular_basis; + std::vector descriptor_parameters(num_descriptor_parameters); + + for (int channel = 0; channel < num_channels; ++channel) { + for (int basis = 0; basis < num_radial_basis; ++basis) { + descriptor_parameters[channel * num_radial_basis + basis] = + parameters[descriptor_offset + basis * num_channels + channel]; + } + for (int basis = 0; basis < num_angular_basis; ++basis) { + descriptor_parameters[num_c_radial + channel * num_angular_basis + basis] = + parameters[descriptor_offset + num_c_radial + basis * num_channels + channel]; + } + } + + for (int n = 0; n < num_descriptor_parameters; ++n) { + parameters[descriptor_offset + n] = descriptor_parameters[n]; + } +} + +inline void descriptor_parameters_to_basis_major( + float* parameters, + const int descriptor_offset, + const int num_channels, + const int n_max_radial, + const int n_max_angular, + const int basis_size_radial, + const int basis_size_angular) +{ + const int num_radial_basis = (n_max_radial + 1) * (basis_size_radial + 1); + const int num_angular_basis = (n_max_angular + 1) * (basis_size_angular + 1); + const int num_c_radial = num_channels * num_radial_basis; + const int num_descriptor_parameters = num_c_radial + num_channels * num_angular_basis; + std::vector descriptor_parameters(num_descriptor_parameters); + + for (int channel = 0; channel < num_channels; ++channel) { + for (int basis = 0; basis < num_radial_basis; ++basis) { + descriptor_parameters[basis * num_channels + channel] = + parameters[descriptor_offset + channel * num_radial_basis + basis]; + } + for (int basis = 0; basis < num_angular_basis; ++basis) { + descriptor_parameters[num_c_radial + basis * num_channels + channel] = + parameters[descriptor_offset + num_c_radial + channel * num_angular_basis + basis]; + } + } + + for (int n = 0; n < num_descriptor_parameters; ++n) { + parameters[descriptor_offset + n] = descriptor_parameters[n]; + } +} diff --git a/src/utilities/nep_spin_model_file.cu b/src/utilities/nep_spin_model_file.cu new file mode 100644 index 000000000..8b29579a2 --- /dev/null +++ b/src/utilities/nep_spin_model_file.cu @@ -0,0 +1,143 @@ +/* This file is part of GPUMD. SPDX-License-Identifier: LGPL-3.0-or-later */ +#include "nep_spin_model_file.cuh" +#include "nep_file.cuh" +#include "nep_spin_legacy_parameters.cuh" +#include +#include +#include +#include +#include +#include +#include + +namespace { +NEP_File read_document(const std::string& filename) +{ + std::ifstream input(filename); + NEP_File document; + std::string error; + if (!document.read(input, error)) throw std::runtime_error(filename + ": " + error); + return document; +} +std::string first_token(const std::string& filename) +{ + std::ifstream input(filename); + std::string token; + if (!(input >> token)) throw std::runtime_error("Cannot read model " + filename); + for (char& c : token) c = std::tolower(static_cast(c)); + return token; +} +} + +bool is_nep_spin_model_file(const std::string& filename) +{ + const auto token = first_token(filename); + if (token == "nep4_spin3" || token == "nep4_spin3_zbl") return true; + if (token != "nep") return false; + const auto document = read_document(filename); + const auto& model = document.find_field("model")->values[0]; + return model == "nep_spin" || model == "nep_spin3"; +} + +std::string read_nep_spin_model_input(const std::string& filename) +{ + if (first_token(filename) != "nep") { + std::ifstream input(filename); + return std::string(std::istreambuf_iterator(input), {}); + } + const auto doc = read_document(filename); + const auto& model = doc.find_field("model")->values[0]; + if (model != "nep_spin" && model != "nep_spin3") + throw std::runtime_error("Expected model nep_spin in " + filename); + std::vector fields = {"format_version", "model"}; + auto field = [&](const char* name, size_t lo, size_t hi) -> const NEP_File::Field& { + const auto* f = doc.find_field(name); + if (!f || f->values.size() < lo || f->values.size() > hi) + throw std::runtime_error(std::string("Invalid Spin3 field ") + name); + fields.push_back(name); + return *f; + }; + auto integer = [&](const NEP_File::Field& f, size_t i, size_t hi) -> int { + size_t value; + if (!NEP_File::parse_size(f.values.at(i), value) || value > hi) + throw std::runtime_error("Invalid integer in Spin3 field " + f.name); + return int(value); + }; + std::ostringstream out; + out << std::setprecision(17); + const bool zbl = doc.find_field("zbl") != nullptr; + const int types = doc.elements.size(); + out << (zbl ? "nep4_spin3_zbl" : "nep4_spin3") << ' ' << types; + for (const auto& element : doc.elements) out << ' ' << element; + out << '\n'; + if (model == "nep_spin") { + const auto& version = field("spin_version", 1, 1); + if (version.values[0] != "1") + throw std::runtime_error("Unsupported spin_version (expected 1)"); + } else { + // The previous block format names this same model nep_spin3/spin_mode 3. + const auto& mode = field("spin_mode", 1, 1); + if (integer(mode, 0, 3) != 3) throw std::runtime_error("Expected spin_mode 3"); + } + const bool dof = doc.find_field("spin_dof_type") != nullptr; + const bool env = doc.find_field("spin_env_type") != nullptr; + out << "spin_mode 3 " << 9 + dof + env << '\n'; + auto line = [&](const NEP_File::Field& f, const char* name) { + out << name; + for (const auto& value : f.values) out << ' ' << value; + out << '\n'; + }; + line(field("energy_reference", types, types), "spin_baseline"); + for (const char* name : {"spin_basis_size", "spin_l_max", "spin_compress", "spin_order", "spin_soc", "spin_projection_size", "spin_scaler"}) + line(field(name, 1, 1), name); + line(field("spin_cutoff", 1, types), "spin_cutoff"); + if (dof) line(field("spin_dof_type", 1, types), "spin_dof_type"); + if (env) line(field("spin_env_type", 1, types), "spin_env_type"); + if (zbl) { + const auto& zbl_field = field("zbl", 2, 3); + double inner, outer; + if (!NEP_File::parse_double(zbl_field.values[0], inner) || + !NEP_File::parse_double(zbl_field.values[1], outer)) + throw std::runtime_error("Invalid Spin3 ZBL cutoffs"); + if (inner == 0 && outer == 0) + throw std::runtime_error("NEP-spin does not support flexible ZBL (zbl 0 0)."); + line(zbl_field, "zbl"); + } + line(field("cutoff", 4, 4), "cutoff"); + const auto& nmax = field("n_max", 2, 2); + const auto& basis = field("basis_size", 2, 2); + const auto& lmax = field("l_max", 3, 7); + const auto& ann = field("ann", 2, 2); + line(nmax, "n_max"); line(basis, "basis_size"); line(lmax, "l_max"); line(ann, "ANN"); + const int nr = integer(nmax, 0, 19), na = integer(nmax, 1, 19); + const int br = integer(basis, 0, 19), ba = integer(basis, 1, 19); + const int neurons = integer(ann, 0, 200); + if (neurons == 0 || integer(ann, 1, 0) != 0) throw std::runtime_error("Spin3 requires one hidden layer"); + const auto* parameters = doc.find_block("parameters"); + const auto* scaler = doc.find_block("q_scaler"); + if (!parameters || !scaler || scaler->values.empty() || scaler->values.size() > 199) + throw std::runtime_error("Invalid Spin3 parameter/scaler blocks"); + const int dim = scaler->values.size(); + const int ann_count = (dim + 2) * neurons * types + 1; + const int C = integer(*doc.find_field("spin_compress"), 0, 9); + const int sb = integer(*doc.find_field("spin_basis_size"), 0, 100); + const int projection = integer(*doc.find_field("spin_projection_size"), 0, 324); + const int count = ann_count + types * types * ((nr + 1) * (br + 1) + (na + 1) * (ba + 1) + C * (sb + 1)) + projection; + if (parameters->values.size() != size_t(count)) throw std::runtime_error("Spin3 parameter count mismatch"); + std::vector values; + for (double value : parameters->values) { + if (!std::isfinite(value) || std::abs(value) > std::numeric_limits::max()) + throw std::runtime_error("Spin3 parameter exceeds float range"); + values.push_back(static_cast(value)); + } + descriptor_parameters_to_basis_major(values.data(), ann_count, types * types, nr, na, br, ba); + for (float value : values) out << value << '\n'; + for (double value : scaler->values) { + if (!(value > 0) || value > std::numeric_limits::max()) throw std::runtime_error("Invalid Spin3 scaler"); + out << value << '\n'; + } + std::vector blocks = {"parameters", "q_scaler"}; + std::string error; + if (!doc.check_unhandled(fields, blocks, error)) throw std::runtime_error(error); + return out.str(); +} diff --git a/src/utilities/nep_spin_model_file.cuh b/src/utilities/nep_spin_model_file.cuh new file mode 100644 index 000000000..c65b3450d --- /dev/null +++ b/src/utilities/nep_spin_model_file.cuh @@ -0,0 +1,8 @@ +/* This file is part of GPUMD. SPDX-License-Identifier: LGPL-3.0-or-later */ +#pragma once +#include + +// Normalize the public block format to the counted Spin3 input consumed by +// the existing semantic validators. Legacy files keep their parameter order. +bool is_nep_spin_model_file(const std::string& filename); +std::string read_nep_spin_model_input(const std::string& filename); diff --git a/src/utilities/nep_utilities.cuh b/src/utilities/nep_utilities.cuh index 8067ad125..626b3951e 100644 --- a/src/utilities/nep_utilities.cuh +++ b/src/utilities/nep_utilities.cuh @@ -168,12 +168,14 @@ __constant__ float COVALENT_RADIUS[94] = { const int SIZE_BOX_AND_INVERSE_BOX = 18; // (3 * 3) * 2 const int MAX_NUM_N = 17; // basis_size_radial+1 = 16+1 const int MAX_DIM = 103; // 13 + 9 * 10 +const int MAX_DIM_SPIN = 199; // max structural 103 + max Spin3 96 const int MAX_DIM_ANGULAR = 90; // 9 * 10 +template static __device__ __forceinline__ void -complex_product(const float a, const float b, float& real_part, float& imag_part) +complex_product(const Real a, const Real b, Real& real_part, Real& imag_part) { - const float real_temp = real_part; + const Real real_temp = real_part; real_part = a * real_temp - b * imag_part; imag_part = a * imag_part + b * real_temp; } @@ -569,25 +571,26 @@ static __device__ __host__ __forceinline__ void find_fn_and_fnp( } } +template static __device__ __forceinline__ void get_f12_4body( - const float d12, - const float d12inv, - const float fn, - const float fnp, - const float Fp, - const float* s, - const float* r12, - float* f12) + const Real d12, + const Real d12inv, + const Real fn, + const Real fnp, + const Real Fp, + const Real* s, + const Real* r12, + Real* f12) { - float fn_factor = Fp * fn; - float fnp_factor = Fp * fnp * d12inv; - float y20 = (3.0f * r12[2] * r12[2] - d12 * d12); + Real fn_factor = Fp * fn; + Real fnp_factor = Fp * fnp * d12inv; + Real y20 = (3.0f * r12[2] * r12[2] - d12 * d12); // derivative wrt s[0] - float tmp0 = C4B[0] * 3.0f * s[0] * s[0] + C4B[1] * (s[1] * s[1] + s[2] * s[2]) + + Real tmp0 = C4B[0] * 3.0f * s[0] * s[0] + C4B[1] * (s[1] * s[1] + s[2] * s[2]) + C4B[2] * (s[3] * s[3] + s[4] * s[4]); - float tmp1 = tmp0 * y20 * fnp_factor; - float tmp2 = tmp0 * fn_factor; + Real tmp1 = tmp0 * y20 * fnp_factor; + Real tmp2 = tmp0 * fn_factor; f12[0] += tmp1 * r12[0] - tmp2 * 2.0f * r12[0]; f12[1] += tmp1 * r12[1] - tmp2 * 2.0f * r12[1]; f12[2] += tmp1 * r12[2] + tmp2 * 4.0f * r12[2]; @@ -1271,14 +1274,14 @@ static __device__ __forceinline__ void get_f12_4body_134( f12[2] += tmp1 * r12[2]; } -template +template static __device__ __forceinline__ void calculate_s_one( - const int n, const int n_max_angular_plus_1, const float* Fp, const float* sum_fxyz, float* s) + const int n, const int n_max_angular_plus_1, const float* Fp, const float* sum_fxyz, Real* s) { const int L_minus_1 = L - 1; const int L_twice_plus_1 = 2 * L + 1; const int L_square_minus_1 = L * L - 1; - float Fp_factor = 2.0f * Fp[L_minus_1 * n_max_angular_plus_1 + n]; + Real Fp_factor = 2.0f * Fp[L_minus_1 * n_max_angular_plus_1 + n]; s[0] = sum_fxyz[n * num_abc + L_square_minus_1] * C3B[L_square_minus_1] * Fp_factor; Fp_factor *= 2.0f; for (int k = 1; k < L_twice_plus_1; ++k) { @@ -1286,28 +1289,28 @@ static __device__ __forceinline__ void calculate_s_one( } } -template +template static __device__ __forceinline__ void accumulate_f12_one( - const float d12inv, const float fn, const float fnp, const float* s, const float* r12, float* f12) + const Real d12inv, const Real fn, const Real fnp, const Real* s, const Real* r12, Real* f12) { - const float dx[3] = { + const Real dx[3] = { (1.0f - r12[0] * r12[0]) * d12inv, -r12[0] * r12[1] * d12inv, -r12[0] * r12[2] * d12inv}; - const float dy[3] = { + const Real dy[3] = { -r12[0] * r12[1] * d12inv, (1.0f - r12[1] * r12[1]) * d12inv, -r12[1] * r12[2] * d12inv}; - const float dz[3] = { + const Real dz[3] = { -r12[0] * r12[2] * d12inv, -r12[1] * r12[2] * d12inv, (1.0f - r12[2] * r12[2]) * d12inv}; - float z_pow[L + 1] = {1.0f}; + Real z_pow[L + 1] = {1.0f}; for (int n = 1; n <= L; ++n) { z_pow[n] = r12[2] * z_pow[n - 1]; } - float real_part = 1.0f; - float imag_part = 0.0f; + Real real_part = 1.0f; + Real imag_part = 0.0f; for (int n1 = 0; n1 <= L; ++n1) { int n2_start = (L + n1) % 2 == 0 ? 0 : 1; - float z_factor = 0.0f; - float dz_factor = 0.0f; + Real z_factor = 0.0f; + Real dz_factor = 0.0f; for (int n2 = n2_start; n2 <= L - n1; n2 += 2) { if (L == 1) { z_factor += Z_COEFFICIENT_1[n1][n2] * z_pow[n2]; @@ -1363,16 +1366,16 @@ static __device__ __forceinline__ void accumulate_f12_one( f12[d] += s[0] * (z_factor * fnp * r12[d] + fn * dz_factor * dz[d]); } } else { - float real_part_n1 = n1 * real_part; - float imag_part_n1 = n1 * imag_part; + Real real_part_n1 = n1 * real_part; + Real imag_part_n1 = n1 * imag_part; for (int d = 0; d < 3; ++d) { - float real_part_dx = dx[d]; - float imag_part_dy = dy[d]; + Real real_part_dx = dx[d]; + Real imag_part_dy = dy[d]; complex_product(real_part_n1, imag_part_n1, real_part_dx, imag_part_dy); f12[d] += (s[2 * n1 - 1] * real_part_dx + s[2 * n1 - 0] * imag_part_dy) * z_factor * fn; } complex_product(r12[0], r12[1], real_part, imag_part); - const float xy_temp = s[2 * n1 - 1] * real_part + s[2 * n1 - 0] * imag_part; + const Real xy_temp = s[2 * n1 - 1] * real_part + s[2 * n1 - 0] * imag_part; for (int d = 0; d < 3; ++d) { f12[d] += xy_temp * (z_factor * fnp * r12[d] + fn * dz_factor * dz[d]); } diff --git a/tests_pytest/fixtures/nep_spin3/model_large_box.xyz b/tests_pytest/fixtures/nep_spin3/model_large_box.xyz new file mode 100644 index 000000000..11db477e3 --- /dev/null +++ b/tests_pytest/fixtures/nep_spin3/model_large_box.xyz @@ -0,0 +1,6 @@ +4 +Lattice="20 0 0 0 20 0 0 0 20" Properties=species:S:1:pos:R:3:spin:R:3 pbc="T T T" +Fe 0.2 0.2 0.2 1.0 0.2 0.0 +Fe 3.7 0.3 0.2 0.4 -0.3 0.7 +Fe 0.4 3.6 0.5 -0.2 0.8 0.5 +Fe 1.8 1.7 3.5 0.6 0.1 -0.4 diff --git a/tests_pytest/fixtures/nep_spin3/nep4_spin3_o3c2_uniform.nep b/tests_pytest/fixtures/nep_spin3/nep4_spin3_o3c2_uniform.nep new file mode 100644 index 000000000..e6f1f0b8a --- /dev/null +++ b/tests_pytest/fixtures/nep_spin3/nep4_spin3_o3c2_uniform.nep @@ -0,0 +1,5772 @@ +nep4_spin3 2 Fe Ge +spin_mode 3 11 +spin_baseline -1.7000000000000001e-01 2.3000000000000001e-01 +spin_basis_size 8 +spin_l_max 2 +spin_compress 2 +spin_cutoff 6.0 +spin_order 3 +spin_soc 1 +spin_projection_size 16 +spin_scaler 1 +spin_dof_type Fe +spin_env_type Fe Ge +cutoff 6 5 128 128 +n_max 4 4 +basis_size 8 8 +l_max 4 2 0 +ANN 30 0 + -5.4294483123e-02 + 5.2445451392e-02 + -1.1349283404e-03 + 1.4705426374e-01 + -8.3327266454e-02 + -3.8910187313e-02 + 7.1152803557e-03 + -6.1023422364e-02 + -9.7068267207e-02 + -4.7360286872e-02 + 3.9138684933e-02 + -8.2657708349e-02 + 1.3162048119e-01 + 1.2801099490e-02 + -8.1977598903e-02 + -3.5049616718e-02 + -3.5749944533e-03 + -8.9923732601e-02 + -6.8818761485e-02 + 3.9331039378e-02 + 1.6980609402e-03 + -5.2897276821e-02 + 2.9117663634e-02 + 1.1511852181e-01 + 6.4910999835e-02 + 8.6623778583e-02 + 2.7249059212e-02 + 1.3456548981e-01 + -3.4082393310e-02 + -1.5969141673e-01 + -9.7859171835e-03 + 6.8133924243e-02 + 5.7216127214e-02 + -1.7469326520e-02 + -4.0291931218e-03 + -6.0327841802e-02 + -3.9119142969e-02 + -6.8696980513e-02 + 8.9689458341e-02 + 1.5949423933e-01 + 6.4190866932e-02 + -2.1529664333e-03 + -5.8831815467e-02 + 3.1325559244e-02 + 7.4885307531e-02 + 1.0075171081e-01 + 9.4963642772e-02 + 1.7630239231e-01 + -6.4963959031e-02 + -4.8921833317e-02 + 1.9154187266e-02 + -2.0734788466e-02 + 2.9599537688e-02 + -2.1987727087e-02 + 5.5842475572e-02 + -3.9853149516e-02 + 5.1090840741e-02 + -1.3668800051e-01 + -5.0172036935e-02 + -4.3731881908e-02 + -6.8142900305e-02 + -9.0020615321e-02 + 5.0992747149e-02 + -7.8434798899e-02 + 1.9768175384e-02 + 5.3070789608e-02 + -2.4681723221e-02 + 7.2858683641e-02 + 1.2406287976e-01 + -8.4920309238e-02 + -2.1996432283e-03 + -3.0540201626e-02 + -4.3448926917e-02 + -3.1702661245e-02 + 8.6390991791e-02 + -9.7491636030e-02 + 1.3674404113e-02 + 3.4678805725e-04 + 9.9747157740e-03 + -1.3672612602e-01 + 3.5644933317e-02 + 1.0838386726e-02 + 8.9406735140e-02 + -2.9122697160e-02 + 7.3530125040e-02 + 1.2319309898e-02 + -1.0231906693e-01 + 2.4860218363e-02 + -4.2757829992e-02 + -6.7897222168e-02 + -9.7443051975e-02 + -5.5546379272e-02 + -1.7346373907e-01 + -3.2054031519e-01 + -7.7436328221e-03 + -8.0770197545e-03 + 9.4350233084e-02 + 5.9719384747e-02 + -1.2397682635e-02 + -5.2597105003e-02 + 3.5904112950e-02 + 1.2717145168e-01 + 1.5110134623e-02 + -1.2709101083e-01 + -1.2539029742e-01 + -5.0512212505e-02 + 4.2819531677e-02 + -8.1785553949e-02 + 1.0040381639e-01 + 6.7570171543e-03 + 7.1967377591e-02 + -7.9310450685e-03 + -5.0060340825e-02 + 5.9807194151e-02 + -2.7559130528e-02 + -4.6746765396e-02 + -3.3036994702e-02 + 1.6247577585e-01 + 1.3456497403e-01 + 1.0420161224e-01 + 1.0287979475e-03 + 1.0540450816e-01 + -5.4779640436e-03 + -3.5988868224e-02 + 6.9922512070e-02 + 1.5298509417e-02 + -1.1025860921e-01 + -8.7910982402e-02 + -1.0289486359e-01 + 6.7935189438e-02 + 1.0691754950e-02 + -7.6504806548e-02 + 6.2692252192e-02 + 7.3778617188e-02 + 3.1778523072e-02 + -2.6716644848e-02 + 8.6032416165e-02 + -1.5317678011e-01 + 1.5646455619e-01 + 3.8121874742e-02 + -1.1526718456e-01 + 1.2068108450e-01 + -5.4812546630e-02 + -2.5820914253e-02 + 9.9528692973e-02 + -1.1903928092e-01 + -7.8700042980e-02 + -2.5604253128e-02 + -6.0104343671e-03 + -7.4904307229e-03 + -9.9468717958e-02 + 1.1133973489e-01 + -8.7088342317e-02 + 4.8066328260e-02 + -1.9192298121e-02 + 6.7090212268e-02 + -1.2164446044e-01 + 2.4633222524e-02 + 2.7528255357e-02 + -4.4372692813e-02 + -5.6372184934e-02 + 7.1216237249e-02 + 6.9616144050e-02 + -2.6816831449e-02 + -1.0083139556e-01 + -1.5684640679e-01 + 7.8377976792e-02 + -1.8341180540e-03 + 1.6131014320e-01 + -6.8835093801e-02 + 1.0937725096e-01 + 2.2464616898e-01 + 1.4151197116e-01 + -1.1324561227e-02 + 2.8813376562e-04 + 3.5662459835e-02 + 9.9323802146e-02 + -4.2791608675e-02 + 9.6504855884e-02 + -1.4175944295e-01 + -3.3777646765e-02 + -5.9356478168e-02 + -1.1556504495e-01 + -8.9373706832e-02 + 5.5443255798e-02 + 3.6691202897e-02 + 7.7627934062e-02 + 5.8126510516e-02 + 7.1159616244e-03 + -7.4773101413e-04 + -1.3861095907e-01 + 1.7329184191e-01 + -9.7587543215e-02 + 1.4165941976e-02 + 1.4453925094e-01 + -1.1669187032e-01 + 1.1854468355e-01 + 6.7807248589e-02 + -6.1933661317e-02 + -6.4407651029e-02 + 4.6081181711e-02 + 6.7120793898e-02 + 5.7783784013e-02 + -5.5148715998e-02 + -6.0187986845e-02 + -6.3186291283e-03 + -7.1613840841e-02 + 1.9948159319e-01 + -8.9965551905e-02 + 6.6861878337e-02 + -4.1524617974e-02 + 1.3916421412e-02 + 2.3567186504e-02 + 8.3114074990e-02 + -1.7834329740e-02 + -2.5203413487e-02 + -8.3847291179e-02 + 3.5582101635e-02 + 3.3314518050e-02 + -2.1442193196e-01 + 7.5296819983e-02 + 4.3660668641e-04 + -7.3009403897e-02 + 5.5592788640e-02 + 1.4041995664e-01 + 7.5677285704e-02 + 1.6455604971e-02 + -4.2197954022e-02 + 6.1259140318e-02 + -1.6945548146e-02 + 6.7620911609e-02 + -1.1647732188e-02 + 6.4636717938e-02 + 1.1144545966e-01 + 1.4222050785e-01 + -1.5859844431e-02 + 4.9160921461e-02 + 7.7442912251e-02 + -7.4381620890e-02 + -1.7866461496e-02 + -5.2317794172e-02 + -3.1757981266e-02 + 1.0022266645e-02 + 2.9683454222e-02 + 1.6552389855e-02 + -4.8559489113e-02 + 2.6638247608e-02 + 4.6168875188e-02 + -4.0785627167e-02 + 1.7583707430e-01 + 8.0312723013e-02 + -1.2469603534e-01 + -7.5430696969e-04 + -1.3386024747e-02 + -1.8929543684e-01 + 1.1986092877e-01 + -4.2796684106e-02 + -9.7491590794e-03 + 1.0781241640e-01 + -1.1154895941e-02 + 1.0348859511e-01 + -1.1415768322e-01 + -2.6789597241e-02 + -2.0799878071e-02 + 5.5139896597e-02 + -1.5200372128e-02 + 1.0960086302e-01 + -1.4688871668e-02 + 1.1537998395e-01 + 8.9255845694e-02 + 4.8277304061e-02 + -2.7717840558e-02 + 3.4583566341e-02 + -7.0458746032e-02 + -7.5904141103e-02 + -7.9992242699e-03 + -6.4931788434e-02 + 1.9029091383e-01 + 3.6445141602e-02 + 5.0237687383e-02 + 1.4020737525e-01 + 8.8811207466e-02 + 9.9010992565e-02 + 4.8207865397e-02 + -1.0123661175e-01 + 3.0013178784e-02 + 4.3345968243e-02 + 1.0955584349e-02 + 5.8442759879e-02 + 1.1504751359e-01 + 1.0885341435e-01 + 3.1677494710e-02 + -2.7216953309e-03 + -1.3264138172e-01 + -4.9905529757e-02 + 9.3465040231e-02 + -2.7074402176e-02 + 6.0353197026e-02 + -1.6458965974e-02 + -7.0044862828e-02 + -4.5083450487e-02 + 5.0276617980e-02 + 1.2533289574e-01 + -4.7097612776e-03 + -7.5890349905e-02 + -1.8452284029e-02 + -4.1052360315e-02 + 2.6414755473e-02 + 2.5673333650e-02 + 4.0075818688e-02 + -1.5007735512e-02 + -8.3449229820e-02 + -1.5407162994e-01 + -6.8696279330e-03 + 1.1708698096e-01 + 2.4078835366e-02 + 4.0189680743e-02 + -9.4069549368e-02 + 7.7056401892e-03 + -1.6292857093e-01 + -5.6653214702e-02 + 1.5783409231e-01 + -6.0217813866e-02 + -1.0979661250e-01 + -5.0911877657e-03 + 8.0809066051e-02 + -9.8944277494e-02 + 5.2574185842e-02 + -6.1358254256e-02 + 7.1352773897e-02 + 1.3843286768e-01 + -7.1011939795e-03 + -3.1557353119e-02 + -4.2963123127e-02 + -4.1087323183e-02 + 3.7256854468e-02 + -1.2431542196e-02 + -2.1034297389e-02 + -2.3753281174e-03 + 2.1004565746e-02 + 1.2606117409e-02 + 1.0585729165e-02 + 5.3709899697e-02 + 4.1726923580e-02 + -6.0956533519e-02 + -6.2858068782e-02 + -1.5002387639e-01 + -2.9086718524e-02 + -1.2088285226e-01 + 1.7113131515e-02 + -6.3378279147e-02 + 1.6091353319e-02 + -4.8483722557e-02 + -1.0825765665e-01 + 3.5121569412e-02 + 1.0914895486e-01 + 1.0060075752e-01 + -4.6406563744e-02 + -9.5543446262e-02 + -5.5017233368e-02 + -1.2461187145e-01 + 2.2882222166e-02 + -8.1296350804e-02 + -1.4074651959e-02 + 6.0905265625e-02 + -1.6808491370e-01 + -5.2585857041e-02 + 1.3411615195e-01 + 9.9644894978e-02 + -1.4955356437e-02 + 8.6065188468e-02 + 8.1570138222e-02 + 1.3478681032e-01 + 7.3245748044e-02 + 1.3984614149e-03 + -8.8639762076e-02 + -1.0119499585e-01 + 6.1006577515e-02 + -5.9368408626e-02 + -7.3506696651e-02 + 5.7598795843e-02 + -5.8872918257e-02 + 7.0638115510e-03 + -2.1702232132e-02 + 7.5927280828e-02 + -1.6716398207e-02 + 1.0264785176e-01 + 3.1067633499e-02 + 5.4774106488e-02 + 6.0038694238e-02 + 8.8285403893e-02 + -6.0154091745e-02 + 1.0848992365e-02 + -1.2381487117e-01 + 8.2937301265e-02 + 5.2853659921e-03 + -9.9355055530e-02 + -8.3430138606e-03 + -1.1923622353e-01 + -1.7950996436e-01 + 4.8107721537e-02 + 5.3716095921e-03 + 1.0023769194e-01 + -8.2136260087e-02 + 6.0578355298e-02 + -5.0669672866e-02 + 2.2344217792e-01 + -1.5691771726e-02 + -1.0867656360e-01 + -1.0914385874e-02 + -1.1432040824e-02 + 1.5397641580e-01 + 9.6639676526e-02 + -1.0990341378e-03 + 5.6751010964e-02 + 3.2400656557e-02 + 9.6338886719e-02 + 1.0090446236e-01 + 2.9872791168e-02 + -4.4671433333e-02 + 8.4384063341e-02 + -8.4113090218e-02 + -4.2177157458e-02 + -3.0196735542e-02 + -7.6564126039e-02 + 3.6977662907e-02 + -7.1992495790e-02 + -7.0619190398e-02 + 4.7055512187e-02 + 1.0169938929e-01 + -7.5984979070e-03 + -4.4669368609e-02 + -1.1803010418e-02 + 3.5666133452e-02 + -4.0703026732e-02 + 2.1261318622e-02 + -4.0149401347e-02 + 1.5508978338e-01 + -9.7227548467e-02 + -9.5562803657e-02 + 8.4944275778e-02 + 3.6361772399e-02 + -1.1689456535e-01 + 8.6883317504e-02 + 3.9273848978e-02 + 8.7519305060e-02 + -6.4020385906e-02 + 5.3892431123e-02 + -1.1268685309e-01 + -6.0859500139e-02 + -1.2909707863e-01 + 5.7798341902e-02 + 5.0283591865e-03 + -6.2011697815e-02 + -7.8164883206e-02 + 9.6414491389e-02 + 3.2144865346e-02 + 2.6333017534e-02 + -2.4057268534e-02 + 3.8004092066e-02 + 2.8922501634e-02 + -5.8880038283e-02 + -1.4848821430e-01 + 2.0008681244e-02 + 1.0021880673e-01 + 5.7627170393e-02 + -9.7757162866e-02 + -8.9052621383e-03 + -5.2008678156e-02 + 3.4145256216e-02 + 7.8786120551e-02 + 9.2200451158e-02 + -1.1810074663e-01 + -9.8689590154e-02 + 4.0357580901e-02 + -9.3619698810e-02 + 1.1833206631e-01 + -2.9242080941e-02 + -2.2588653356e-02 + -1.4479294677e-02 + -1.7394485735e-02 + 1.0385729650e-01 + 1.2522825090e-02 + -7.2038915807e-02 + 3.0822335219e-02 + -4.8387845483e-02 + -6.9342513263e-02 + -4.6916625779e-02 + -8.2505121329e-02 + -1.2143110253e-02 + -3.4219628066e-02 + 2.7067045251e-02 + -1.0706191059e-01 + 4.3294613592e-02 + -1.0784541937e-01 + -6.3044808133e-02 + 6.3079758447e-02 + -3.1672468592e-02 + -1.4372614322e-01 + 2.2651695625e-02 + -9.9938016880e-02 + -3.8104393862e-02 + 4.3349149410e-02 + 1.2722650393e-01 + -2.8090887739e-03 + 2.5667236980e-02 + 2.6658940774e-02 + 2.1913894721e-02 + 1.7456843279e-02 + 1.6033126238e-01 + 2.5656705971e-02 + 1.1318176220e-01 + -6.1259088099e-02 + 1.5940956107e-02 + 1.1274537513e-01 + -8.2152053200e-02 + -6.5930831980e-02 + 2.3056170033e-02 + 2.1701488517e-02 + -2.9886066724e-02 + -9.0855978468e-03 + -5.8782294848e-02 + -1.2163333190e-01 + 1.5535284168e-02 + -1.4942277079e-01 + -7.7077227955e-03 + 7.8425955485e-02 + -1.1167843072e-01 + -1.7157097616e-02 + -1.2909867657e-02 + -8.1583896020e-02 + -3.3716179455e-03 + -3.3917430680e-02 + 1.7850266774e-02 + -1.7122384812e-01 + 1.5539658611e-01 + 5.9256130455e-03 + 1.9936839268e-02 + -4.1668205811e-02 + -1.5908517582e-02 + -9.0708162317e-02 + 4.3171626572e-02 + 8.3876361771e-02 + -8.1436372259e-03 + 1.5058857528e-01 + -2.9077476117e-01 + -9.1814469840e-03 + -4.6836719392e-02 + -6.2408860946e-02 + -6.5645236053e-02 + -4.2114007691e-02 + -1.2629830863e-01 + 4.4941820402e-02 + -1.4202913033e-01 + 4.4329718801e-03 + 2.6357693933e-03 + -5.9688544850e-02 + 8.3053728246e-02 + -1.4142352705e-01 + 9.8180468589e-02 + 1.2846954533e-02 + -1.0305086578e-01 + 7.0489771040e-02 + 6.0531447982e-02 + -7.2004567914e-02 + -1.2069541495e-01 + 2.0197153575e-01 + 3.7977368106e-03 + -1.3022016874e-01 + 1.2039477838e-01 + -4.1893315853e-02 + -7.0838772161e-02 + 7.1176114222e-02 + -4.1221028650e-02 + -7.1487567861e-02 + -4.4634400421e-02 + -3.1838260273e-02 + -4.6182600810e-02 + 1.2898358667e-01 + 2.2459888328e-03 + 1.3414744571e-01 + 6.8312249048e-02 + -4.4773273325e-03 + 1.4325434011e-01 + -4.7629161763e-02 + -3.5261258941e-02 + -1.2774064289e-01 + 1.2294634567e-01 + -1.4713184938e-01 + -3.1719488129e-02 + 4.7853279516e-03 + -1.3662620404e-02 + 7.9159410651e-02 + -5.7796361162e-02 + -6.4492232486e-02 + 1.0906759783e-02 + -5.0887217263e-02 + -5.4406520093e-02 + -1.8812231934e-02 + -8.6228935954e-02 + -1.3005895303e-01 + 1.1188849179e-02 + 9.2568610921e-04 + -2.6806768561e-02 + -4.7754663849e-03 + -3.4855556447e-02 + 3.0306813794e-02 + 7.8206968219e-02 + -1.0026519898e-01 + 9.3483746890e-02 + -5.7779747514e-02 + -3.7738596746e-02 + 4.8983599740e-02 + 1.1852954083e-01 + -1.6560834028e-01 + -1.1933741091e-02 + 7.5777926337e-02 + -6.8466132233e-02 + -1.2407473082e-01 + 6.6582187984e-02 + 4.8240643097e-02 + -6.1966325767e-02 + -8.5537373914e-02 + -9.1789427095e-04 + 4.6472233830e-02 + 3.1333339381e-02 + 6.5456356200e-02 + 1.3201247256e-01 + -1.4189221380e-02 + -9.3827226575e-03 + -4.9892321405e-02 + 9.1316824618e-02 + 9.3264921217e-02 + -8.7833902573e-02 + 5.1325686112e-02 + -1.0586870764e-01 + 8.4935678631e-03 + -4.8883668768e-02 + -6.8005043381e-03 + 9.9942824481e-02 + -8.4938086204e-02 + -6.5675211031e-02 + 6.8503069306e-02 + 1.1334267509e-01 + 5.1365137332e-02 + -1.4024292543e-01 + 1.4202220295e-01 + -7.7830277128e-03 + -6.5240921730e-02 + 2.0372394187e-02 + 4.7517166954e-02 + -2.1835148103e-01 + -9.3151164437e-03 + 9.0288726096e-02 + -5.3745670383e-02 + -1.0505132040e-02 + 2.6398392137e-02 + -7.3936932367e-02 + -1.8561007786e-02 + -8.6675124509e-02 + 4.0233723142e-02 + -9.2503140865e-02 + 8.1725490010e-02 + 1.5455369661e-02 + 2.2356748821e-02 + 1.0543977537e-01 + -5.3371844991e-02 + -1.8539004958e-01 + -1.2441217767e-01 + -8.0710989643e-02 + 5.7720897270e-02 + 1.5716289646e-02 + 9.8134166215e-03 + 1.7667824706e-02 + -2.0538474102e-01 + 6.1105140728e-02 + 8.3259054084e-02 + -4.3403041593e-02 + -9.3439697057e-03 + -3.6755465433e-02 + 9.7174443200e-02 + 1.4566146551e-01 + 2.3294873396e-02 + 1.5294868338e-01 + -4.1617016452e-02 + -9.0154375122e-03 + 2.9953727485e-03 + -3.1643336308e-02 + 1.0985468126e-02 + -1.6011541652e-03 + 1.9512800074e-01 + -4.6762173567e-02 + 1.0949069647e-02 + -1.8077317562e-02 + -8.4603163972e-02 + 1.1867409659e-01 + 8.6488295627e-02 + -1.1211761093e-01 + -3.5915077683e-03 + -5.8706645838e-02 + -3.2592472417e-03 + -5.9858922864e-02 + -8.0380370159e-02 + -1.5533684969e-01 + 1.8381089610e-01 + -2.8057291785e-02 + 3.3518417278e-02 + 3.4361223489e-02 + 7.1057053396e-02 + -1.0931094066e-01 + 6.1122090729e-02 + 8.6779381891e-02 + -2.1562008669e-02 + -1.2600542484e-01 + -9.1397639356e-02 + -2.4196381864e-02 + -1.1364262062e-01 + -6.4191810117e-03 + -2.1973664510e-02 + -2.1732982280e-02 + 1.2515665795e-01 + -1.8427207783e-01 + 1.6518201968e-02 + 3.3142994931e-02 + 1.9573231993e-02 + 1.0604621587e-02 + -5.5106586492e-04 + -1.1166560752e-01 + -6.2756066470e-02 + 6.5674732345e-02 + 3.2999594274e-02 + 1.0230926035e-01 + -2.2210756219e-02 + -5.9381229776e-02 + -8.7192537703e-02 + -8.1712778062e-02 + -1.1690920770e-01 + 5.1876009651e-02 + -1.6474189682e-02 + 3.0069219252e-02 + 1.7773013854e-02 + 1.1550326445e-01 + -4.3455048819e-02 + -5.3718646372e-02 + -9.7325716571e-02 + -1.6242012404e-01 + 7.1464428080e-02 + -5.6799843934e-02 + 3.1997460478e-02 + -1.1421785914e-01 + 4.6414067210e-02 + 2.1644560953e-02 + -3.9213053441e-02 + -2.2255471219e-02 + -1.2864231685e-01 + 4.6760131657e-02 + 4.7988366856e-02 + -9.0150695851e-02 + 4.5425045757e-02 + 3.7091175321e-02 + 2.6166052663e-02 + -1.7366932919e-02 + 6.0464575602e-03 + 5.6075695453e-02 + 4.4347889790e-02 + -4.0571116017e-02 + 4.7199064000e-02 + -5.5249182835e-02 + -8.1721885497e-02 + -1.0857348414e-01 + -2.9477450286e-02 + -8.6132939694e-02 + 3.6102971216e-02 + 5.8618019451e-03 + -1.8366712919e-01 + 2.0683351298e-02 + -5.0746203481e-02 + -3.3886223179e-02 + -2.4528929274e-02 + -4.4332292430e-03 + 1.2893286988e-02 + 8.1677404677e-02 + 5.6269259517e-02 + 1.2583585701e-01 + 1.2750074362e-03 + 6.2413990751e-02 + 6.9413823318e-02 + 1.2472405816e-01 + 6.2779500679e-02 + 1.1016309391e-02 + -7.5703715586e-02 + -1.9846916887e-01 + 6.5128600501e-02 + 3.1701509507e-02 + 1.2196006305e-01 + 1.1496065801e-02 + -1.5106159596e-02 + 7.1758733689e-02 + -5.1403386014e-02 + 1.6371660201e-01 + -6.2105399847e-02 + -6.0197330970e-02 + -5.3491648049e-02 + 6.3324517685e-02 + -3.7931627065e-02 + 3.0223848919e-02 + 3.3593315056e-02 + 1.3737486598e-01 + -7.3157267877e-02 + -5.6220761769e-02 + -4.5938789544e-02 + 5.9927419008e-02 + 6.0240222498e-04 + -5.6736959035e-02 + -1.6854575150e-01 + -2.0119845447e-02 + -3.7446118689e-02 + -3.5470249223e-02 + 3.5971498635e-02 + -6.8671515276e-02 + 1.1169328750e-02 + 2.5941547818e-01 + -3.0360336309e-02 + -2.7728333098e-02 + 1.1797008045e-01 + 1.8349371625e-02 + -6.0469977809e-03 + 6.3956384458e-02 + 9.5064669090e-02 + 4.6972123366e-02 + -6.1123182276e-03 + -2.5918905256e-02 + -3.9082916371e-02 + -1.4255836539e-01 + -7.3212081109e-03 + -1.5130262526e-02 + 1.8528053119e-02 + 7.4412586664e-02 + 2.1025959853e-01 + -6.7253606514e-02 + -3.1589490804e-02 + -9.0272974932e-02 + -9.6544338458e-02 + -1.1442736446e-01 + -8.6618709473e-02 + 2.0091451510e-01 + -1.9520796003e-02 + 1.6115320872e-01 + -1.8744464017e-01 + -8.0551670398e-02 + -2.3609368077e-02 + 8.6307571302e-02 + -1.0901781292e-01 + -7.3768300021e-02 + 2.6239860457e-01 + 1.1677416701e-02 + 4.7721663119e-02 + 8.5396476912e-02 + 1.0315492675e-01 + -3.3331893866e-02 + 1.1791892074e-02 + -6.3453468381e-02 + 1.8081305308e-02 + 2.6645365126e-02 + -1.9993678736e-02 + 3.7290410139e-02 + 1.1919000577e-01 + -4.4106506275e-02 + -6.0091602127e-02 + -2.3729803713e-03 + -4.1769473819e-02 + 5.2791411521e-02 + -2.3008870063e-02 + -3.3583398696e-02 + 8.3846685779e-02 + 5.0537423117e-02 + 2.1217135244e-02 + 1.4450436797e-01 + -4.9151587626e-02 + -3.1433068633e-02 + 1.0641621252e-01 + -3.1080824498e-02 + 5.1506431655e-02 + -1.5919768951e-02 + -2.8946872941e-02 + 1.2834489690e-02 + 3.4034268849e-02 + 6.5451209754e-02 + 7.0495437752e-02 + -2.8303121056e-02 + 1.3058746109e-02 + 1.2055909837e-01 + 8.3900102079e-03 + 2.2422390380e-02 + 1.0078319187e-01 + 9.7079634052e-02 + -1.2533552368e-01 + 4.1001931440e-02 + 1.4339845694e-02 + -1.6064523227e-01 + 3.9072001165e-02 + -3.0741623188e-02 + -6.9818167961e-02 + -2.3264177667e-02 + 3.9396103549e-03 + -6.6604036156e-02 + -1.5328611353e-01 + 2.0659648503e-01 + -3.9393759894e-02 + 1.8376840247e-02 + 1.4090925013e-02 + -5.0764827110e-02 + -3.4466132011e-02 + 2.9064027950e-02 + -5.8869429541e-02 + 7.0740362833e-02 + -1.1042615570e-01 + -4.1319850371e-02 + -2.1082417981e-02 + -1.7949858873e-02 + -8.9542622643e-02 + -2.5844534008e-03 + 1.3932209215e-01 + -2.8003598847e-03 + -8.1670864426e-02 + 2.6883943212e-02 + -1.8354703978e-02 + 7.3433018201e-02 + -5.5169153161e-02 + 4.4846362149e-02 + -1.3869457626e-01 + 8.4052931323e-03 + 1.2760377406e-01 + -9.7195152512e-02 + -1.0118307873e-01 + -6.4367713880e-02 + 3.4144138273e-02 + -2.0454005170e-01 + 7.0959419009e-02 + -9.9145710501e-02 + -4.1489345396e-02 + 7.3111276683e-02 + -4.7945608927e-02 + 2.1174201141e-02 + -2.0896565370e-02 + 7.4653418315e-02 + 1.3421565484e-01 + 1.1812881780e-01 + 5.3752980808e-02 + -1.6705180088e-02 + 5.7539152285e-02 + 1.5085850618e-01 + -1.6067710020e-02 + -4.3480424432e-02 + -1.0583091027e-01 + -3.4414839269e-02 + -6.5336562380e-02 + -1.4260591419e-02 + -1.2756617502e-01 + -1.9685781555e-02 + -6.6965441484e-02 + -1.5488908511e-01 + -1.4258299461e-01 + -8.8284089041e-03 + 5.4241092595e-02 + 3.2965750789e-02 + -1.2505166924e-02 + 2.0070220549e-02 + -8.8021070816e-03 + 5.8924898284e-02 + -3.6813987190e-03 + -1.7139600267e-01 + 1.4103500797e-02 + 1.1037595046e-01 + -4.2351199747e-02 + 6.7800103467e-03 + -6.8438346722e-03 + 1.4493983154e-01 + 3.5425619546e-02 + -9.8057234432e-02 + 3.6547632952e-02 + 2.1822724562e-02 + 3.1866833209e-03 + 7.4376629423e-02 + 5.9881272861e-02 + -4.4251464579e-02 + 1.3732462914e-02 + 1.3033082085e-01 + -1.5767327174e-01 + 2.0796540924e-02 + 3.4436672194e-02 + -1.3061119316e-02 + 8.1493186905e-02 + -5.3175629103e-02 + -5.2407328726e-02 + 1.6491959213e-02 + -8.2915377139e-02 + 1.2556501629e-03 + 9.7744475944e-02 + -2.3237902556e-01 + 1.4370133347e-01 + 1.1454555684e-01 + -6.3330111705e-02 + -4.8101159788e-02 + -5.0717344948e-02 + 9.7791105611e-02 + 6.8352253496e-02 + 1.4143146465e-01 + -1.2678322160e-02 + -9.4286960948e-02 + 2.5703948948e-02 + -4.8325005562e-02 + 2.0091720746e-02 + -4.6411904843e-02 + -3.3058694374e-02 + -2.6885591645e-02 + 1.2444972011e-02 + 4.3065482833e-02 + -2.5480791943e-02 + 5.3887304126e-03 + -3.4034920298e-02 + -1.4008805794e-01 + 6.4777261846e-03 + -1.9252060988e-01 + 1.5781094998e-02 + 1.3934269829e-01 + -2.6047699628e-02 + -3.4042813840e-02 + -4.5791134570e-02 + 9.2135475839e-02 + -1.2639732262e-02 + -1.5781610196e-01 + 3.8225772539e-02 + -1.2994214117e-01 + -5.9231787000e-03 + -4.7225370453e-02 + 8.2417503384e-02 + 9.5273334392e-02 + 9.0702819259e-02 + -9.7203926821e-02 + 1.5415695745e-02 + -1.7141626605e-01 + -6.2935849701e-02 + 6.0432459273e-02 + -1.1777215723e-01 + 3.4277941935e-02 + 9.4090827082e-02 + -8.7419866764e-02 + -2.3134924340e-02 + -1.3334551869e-01 + -2.0589724086e-02 + -2.0654493869e-01 + -4.1747871634e-03 + 1.3023357566e-01 + -9.4775913303e-02 + 1.2824996888e-01 + 2.5531166498e-03 + 9.8711625642e-02 + 1.6388755319e-01 + 8.1905997734e-02 + -8.8654729207e-02 + 3.9982185385e-02 + 2.5000965942e-02 + -6.8556578742e-02 + 7.6540167574e-02 + -2.0341524191e-02 + -5.6478525649e-02 + -2.5282796343e-02 + 5.2824102302e-02 + -1.0711157176e-01 + 2.9862125168e-02 + -6.6000316125e-02 + -9.3131118623e-02 + 3.7528118131e-02 + 9.9083710213e-02 + 4.7842094200e-02 + -6.8540426616e-02 + 1.4940229730e-01 + 4.1193565854e-02 + -9.5208613628e-02 + -9.4031337398e-03 + -5.7690811541e-02 + 7.3152271904e-02 + 4.9512537480e-02 + -7.8541387881e-02 + 7.8663138523e-05 + -1.1322482852e-01 + 1.5770918823e-02 + -3.1677907144e-02 + -2.9154793843e-02 + 4.8039047570e-02 + -2.7980228430e-02 + -9.3704249676e-02 + 8.2193880432e-02 + 3.0221116617e-02 + 5.0088414015e-03 + -5.1792504108e-02 + 1.1706637388e-01 + 1.0751030694e-01 + -1.7655764277e-01 + 4.2380690663e-02 + 4.6061170476e-02 + 1.4900786500e-01 + -1.1783102412e-01 + 9.7554407824e-03 + -2.6530608789e-02 + 4.4847354928e-03 + -4.4596770564e-02 + -6.1529643729e-02 + -3.1156295818e-02 + 1.4814066822e-01 + -8.6817510024e-02 + 6.3296316933e-02 + -5.4401047768e-03 + -4.0498258258e-02 + -4.6914654288e-02 + 1.1355883448e-01 + 5.4109292201e-02 + -7.6232223519e-02 + 6.7598254459e-02 + 4.0354785085e-02 + -1.2414758218e-01 + -5.6634676707e-02 + -3.3774880150e-02 + 9.2916489926e-02 + 3.4369112812e-02 + 3.9832988272e-02 + 1.4990516882e-01 + -5.7738005936e-02 + 1.3969424870e-01 + 9.2925409659e-02 + 1.2746262266e-01 + -1.7019670464e-02 + -2.8945599484e-02 + 3.9681002291e-02 + 2.9591112352e-02 + -9.3534951707e-02 + -2.3877451965e-02 + -5.4045537271e-02 + -2.6638791022e-02 + 1.1652604666e-01 + 1.4739205004e-01 + -4.3588082409e-02 + 3.6078418944e-02 + 8.5017759130e-03 + 6.1059601632e-02 + -9.9729582904e-02 + 5.6587816990e-02 + 2.4570178611e-02 + 3.7900173073e-02 + 2.2872010228e-02 + -1.5231311203e-02 + -4.8718694411e-02 + 8.1248232426e-02 + -9.5571134031e-02 + -1.6039794175e-01 + -1.1628358147e-01 + 6.0142761336e-02 + 1.6214110841e-02 + 8.9149988601e-02 + -1.0663647173e-01 + 6.5035894016e-02 + 9.4737059422e-02 + 6.5555843172e-03 + 7.9187557202e-02 + 5.0181935754e-02 + -7.3339349508e-03 + -9.9264453387e-04 + -1.2172857460e-01 + -1.0669859007e-02 + 3.6915167738e-02 + 5.6218910973e-02 + -4.4847047186e-02 + -1.6583380210e-02 + -6.8264969379e-02 + 3.5248594893e-02 + -1.1200801491e-02 + 4.0322877863e-02 + 9.3602349823e-02 + 1.2156970891e-01 + -6.4283681017e-02 + 7.4664440491e-03 + 1.1662055416e-01 + 3.8863979620e-02 + 3.0329318738e-02 + -1.1945354993e-01 + 8.1466136977e-02 + 1.1849684530e-01 + 7.4780891700e-02 + -1.1750497308e-01 + 3.4454517034e-02 + -5.3149648504e-02 + 9.5850111410e-02 + 5.4721039302e-02 + -3.6689256091e-02 + 1.1247206459e-01 + 7.3868208568e-02 + 5.2512566201e-02 + 3.0479504577e-02 + 2.2034151555e-01 + -1.4568769574e-01 + 7.7555945965e-02 + -7.3644091631e-02 + 7.6559805082e-02 + -2.3750541143e-02 + -1.6741806593e-01 + -8.6439715485e-02 + -1.9836354344e-02 + -5.7561851032e-02 + -7.1165720559e-02 + -8.0146633083e-02 + 1.0222506225e-01 + 9.3834093149e-02 + -5.7291103493e-02 + -1.9548677236e-02 + -2.6907127717e-04 + 9.3015107499e-03 + -4.5715154906e-02 + 3.8490593375e-03 + 1.1753829555e-01 + 2.5204930820e-02 + 1.2934675886e-01 + -3.4174450964e-02 + -1.7380707882e-02 + -5.8213191544e-02 + -3.0134876583e-02 + -5.3308521620e-02 + -6.8693451317e-02 + 1.1700469200e-02 + 2.3750781048e-02 + -1.0575360812e-02 + 2.6226858018e-02 + -4.2691727452e-02 + -6.5506251172e-02 + 6.6585416880e-02 + -1.6909451164e-01 + 8.3954543387e-02 + -5.9996111110e-02 + 5.4832405434e-02 + 1.1406010270e-01 + -9.6286789553e-02 + -4.6044928585e-02 + -1.1708111563e-01 + 1.6654135571e-01 + 1.3549252643e-02 + -2.3964406144e-03 + 6.2922959997e-03 + -3.6190102217e-02 + -1.7904538302e-03 + -4.0204226413e-02 + 4.3771528320e-02 + -1.4258539855e-01 + 1.5536979973e-02 + -5.8496346040e-02 + 3.4523777928e-02 + -7.4499370126e-03 + -1.1113970758e-01 + -4.5254394111e-02 + 9.2954191037e-02 + -5.5118484925e-03 + -1.3916444068e-01 + 1.4720457704e-01 + 2.3809241106e-03 + 9.6294998570e-02 + 5.1137095816e-02 + 6.3370281308e-02 + 8.9425369330e-02 + 7.2430925433e-02 + 3.2837757346e-03 + 1.3769871909e-01 + 7.2122956063e-03 + 1.2546757764e-01 + -1.7858155018e-02 + -8.4920796668e-02 + 9.6922042551e-02 + -6.6124920702e-02 + 3.1198032481e-02 + 1.4764094112e-01 + 1.6606253496e-01 + 9.6831385660e-02 + 5.7568208217e-02 + -3.5918073455e-02 + 4.6070494077e-03 + 8.5991879257e-02 + -1.4984520538e-03 + 8.6254501144e-02 + -9.3386306850e-02 + -4.3681980192e-02 + -3.7238488167e-02 + -1.0122052532e-02 + 3.0987509501e-02 + -4.0943972791e-02 + -1.1070110960e-02 + -2.4483250339e-02 + 8.7683639300e-02 + -7.3048845418e-02 + 6.9536499334e-02 + -4.8096066465e-02 + 6.4087179186e-02 + -1.1344096112e-01 + 1.3716111825e-02 + 8.7497249193e-03 + 2.5085645513e-02 + 3.8699273402e-02 + -3.8806505068e-04 + 1.1070386241e-01 + 2.7538385130e-02 + -8.0360142237e-03 + -5.0694399732e-03 + -1.7711743364e-01 + -4.5144102561e-02 + 1.2731382309e-02 + 6.3235563940e-02 + 4.2583900102e-03 + 6.0405708924e-02 + -1.2823975315e-01 + 2.6638946176e-02 + 4.7170837023e-02 + -6.5525991192e-02 + 5.1243807459e-02 + 7.7328560452e-02 + -1.5160176736e-02 + 1.7727793410e-01 + -9.1750196830e-02 + -1.3373145597e-02 + -1.3981316086e-02 + 4.3682472630e-02 + 3.2475153044e-02 + 1.7528601410e-02 + -6.5318557158e-02 + -1.2531263236e-01 + 1.6850942572e-01 + 8.0795625159e-02 + -1.8795984546e-02 + 4.1599413877e-02 + -7.7997843328e-02 + 3.8282747390e-02 + 5.0506433768e-02 + -2.7693606006e-02 + -4.5782730121e-02 + 1.4684948235e-01 + -5.3043398185e-04 + 1.3307777223e-01 + -2.9695306778e-03 + 1.8123151397e-02 + -4.5748678351e-02 + 4.4167573145e-02 + -5.5192704329e-02 + 8.8006496957e-02 + -1.1015353729e-01 + 2.0140348406e-03 + 3.9532098158e-02 + 5.9492203428e-02 + -1.4940052899e-01 + 9.7823274028e-02 + 7.8856837672e-02 + 9.3093756640e-02 + -3.4692388545e-02 + 5.2216080634e-02 + 4.1680361628e-02 + 4.5526153182e-02 + -1.2125012930e-01 + 1.4858731187e-01 + -2.0205681230e-02 + 7.5689672998e-02 + -7.7110517806e-02 + 1.1891237854e-01 + 4.0897131010e-02 + -7.1157434990e-02 + -1.8954330339e-02 + 4.9028641336e-02 + 5.1379098786e-02 + 5.0951248836e-02 + -9.2283616881e-02 + 1.1783658195e-01 + -7.4786994523e-02 + 6.1936580457e-02 + -9.4123021022e-02 + -1.0357605661e-01 + 1.0602743698e-01 + 1.3730364139e-01 + -3.5435513855e-02 + 1.1383879613e-01 + 9.8782101557e-02 + -5.7184233424e-02 + 6.6429741566e-02 + -7.1716386257e-02 + 2.7276932317e-02 + -3.8180777955e-02 + 1.3288955298e-02 + 2.1151357503e-02 + -5.6272028823e-02 + -3.0660825166e-02 + -1.1227184926e-01 + -8.4872739463e-02 + -1.0275550869e-01 + -8.5560563849e-02 + 8.7770886893e-02 + -6.0920912267e-02 + -1.0362525339e-02 + -1.0401333752e-01 + -6.5231342758e-02 + 3.7860975185e-02 + -1.4615254185e-01 + 6.1451479261e-02 + 6.3599114359e-02 + 1.3691403600e-01 + 5.1778464427e-03 + 1.3632418568e-01 + 6.3940417908e-02 + 1.0476689619e-02 + 8.6455216896e-02 + -2.0141735880e-03 + -1.0175460852e-01 + 3.3201702335e-03 + 4.8466786077e-02 + -2.3763079992e-02 + 1.0618519758e-01 + 6.7135888546e-03 + -5.8021235527e-02 + 1.9559484796e-01 + 2.7986558216e-02 + 3.4540452538e-02 + 3.0577619942e-02 + 1.7470774043e-01 + -2.3772321780e-02 + -2.6054512981e-02 + 1.1039706759e-01 + -1.4963191325e-01 + -3.2627701730e-02 + 1.1599376113e-02 + 7.7130533340e-02 + 1.2664334896e-01 + -6.6823424260e-02 + 1.4904894407e-01 + -8.7978217872e-02 + 1.5059972976e-03 + 4.2843791948e-02 + -2.8067933029e-02 + -2.6562780287e-02 + 1.5945225262e-01 + -1.0433082025e-01 + -7.5831126232e-02 + -2.0132940743e-01 + 5.9730223852e-02 + -6.7644930417e-02 + 1.2749448678e-01 + 6.1964948275e-03 + -2.0614063374e-02 + -4.5380502281e-02 + 2.2910851634e-01 + 2.1621750166e-02 + -2.4085835837e-02 + -4.4981631500e-02 + 1.2852636630e-01 + -1.6343352163e-01 + -1.1521358056e-02 + 1.4915785156e-02 + 5.1255599378e-02 + -9.0178234128e-02 + 4.8022363205e-02 + 9.9704934555e-02 + -2.0632111974e-01 + -2.3993733975e-02 + 1.4454151006e-01 + -2.4329257939e-02 + -1.0750524592e-01 + 1.0229890012e-01 + -2.1702554721e-02 + -1.0536480246e-01 + 8.8781927977e-03 + 4.6330902966e-02 + 4.7552776316e-02 + -1.6507806714e-02 + -1.0768010066e-01 + 1.2908548251e-01 + -1.5707874164e-01 + -1.1030218008e-01 + -1.7154457268e-02 + -6.1112198733e-02 + 1.2763858177e-01 + 2.8671912472e-02 + -8.5900749214e-02 + -6.7900675426e-02 + -7.7019391712e-02 + -1.1269532177e-01 + 1.2821134615e-01 + -8.3419714935e-02 + 4.1206243846e-02 + 4.5902469968e-02 + 4.7264086529e-02 + -3.4066087545e-02 + 1.4691134879e-02 + -4.0448454289e-02 + 3.9240933878e-02 + 6.8262466420e-02 + -1.2848829426e-03 + 1.3359667692e-01 + 6.6631898281e-02 + 7.0558804880e-02 + -1.3695046306e-03 + -1.9747054647e-02 + 1.0965324765e-01 + -1.0967295723e-01 + -1.8384742601e-01 + -2.1325844292e-02 + -6.2942451630e-02 + 5.7706561131e-02 + -1.0314431292e-01 + 3.0450205694e-02 + 9.2344593768e-02 + -4.8236018639e-02 + 1.8159679642e-01 + -7.3071645492e-03 + 4.6221497863e-02 + 1.8100870839e-02 + -7.9365971690e-02 + -6.1014662757e-02 + -4.8135431349e-02 + 1.0106766698e-01 + 5.5679971628e-02 + 1.3909522971e-01 + -6.8496888429e-02 + -5.1948322671e-02 + 9.1893390178e-03 + 2.7999000068e-02 + -7.2411414903e-02 + 8.9816766903e-02 + 6.6481939635e-02 + -9.6684731428e-02 + 5.7280712513e-02 + -9.8583591826e-02 + -1.2337514748e-02 + -8.3216618960e-02 + -3.3263784397e-02 + -1.4422461671e-01 + 2.5076448601e-02 + 1.0759810890e-01 + -1.9557235583e-02 + -8.3686594813e-02 + -1.8040173638e-02 + -6.4879753290e-02 + 3.0406891933e-02 + 5.9245936181e-02 + -3.1895095885e-02 + 1.1365835385e-02 + -2.5189476245e-02 + 1.2537339347e-01 + -3.8474991134e-02 + -4.7195657465e-02 + -1.7508976634e-01 + 5.4753463194e-02 + 2.1015213530e-02 + 7.3686657522e-02 + -6.9022588116e-02 + 1.1810998230e-02 + -6.2648919003e-02 + 7.9037413587e-02 + -4.3395722002e-02 + 1.0963657680e-01 + -1.2531504451e-01 + 2.2782235957e-02 + 7.8341236149e-02 + -9.9708429873e-02 + 9.4295250372e-02 + -1.1648185007e-01 + -6.3405531471e-02 + -1.3884498968e-01 + 6.8499997291e-02 + 1.3840045016e-01 + 6.5742634362e-02 + -5.7447363895e-02 + -8.4311369110e-03 + -1.1249661782e-01 + -1.0134521050e-01 + 1.0976092918e-02 + 2.4449218158e-02 + -3.7296571858e-02 + -1.8656719977e-01 + -5.9940483479e-02 + 1.7741465992e-02 + 1.0693560275e-01 + -4.6374074222e-02 + 1.7342345508e-01 + -7.0344721878e-03 + -8.3597698206e-02 + -3.1067114756e-02 + 5.4535987454e-02 + 3.4442878003e-03 + 4.8460807607e-02 + -6.3934386364e-02 + 1.5656635383e-01 + -3.9961742685e-02 + 7.6542613134e-02 + -1.3151878344e-01 + 4.9806367315e-02 + 4.2451351548e-02 + 5.3948059728e-02 + -3.3793256580e-02 + 8.0533104739e-02 + -8.8978589151e-02 + 6.3332835539e-03 + 8.3251224169e-02 + 1.5393851924e-01 + -5.1329026100e-02 + 4.6842981593e-02 + -1.1058990490e-02 + 1.2799007900e-01 + 2.6455472098e-02 + -8.9935180218e-02 + 1.0678618921e-02 + 2.0589189042e-01 + -1.0536598302e-01 + -1.6944880419e-01 + 2.9460475617e-02 + 4.2699097079e-02 + 1.0387105297e-01 + 6.3463487855e-02 + -3.2993955681e-02 + 9.7331203812e-02 + 1.1695866839e-01 + -6.4804269272e-02 + 3.2234230109e-02 + -1.4616663335e-01 + -5.9041621582e-02 + -8.3339126840e-02 + 4.6846318464e-02 + -7.0487074294e-03 + -3.9964209267e-02 + 1.0035290172e-01 + -6.5649329012e-02 + -8.7657414605e-03 + 2.2487582181e-03 + -9.1202758251e-02 + 4.7383188154e-03 + -7.8626372433e-02 + 2.5252181241e-02 + 2.6840141168e-02 + -6.2465009686e-02 + 1.5135647205e-02 + 2.8528887786e-02 + 3.7773815613e-02 + -2.6113123540e-02 + -4.8248934620e-03 + 6.1608951294e-02 + -3.7502008158e-02 + -4.1740626566e-02 + 2.0472371488e-01 + -5.3574207192e-02 + -5.4546479472e-02 + 5.8729046886e-02 + 4.9218797863e-02 + -1.7136793874e-01 + 5.2479481562e-02 + 1.1183857479e-01 + -9.4843331836e-02 + 2.7192435511e-02 + 1.6807838163e-01 + -9.3666301496e-02 + -1.0111556909e-02 + -7.0851487051e-02 + 4.2397110127e-03 + -1.0138307927e-01 + 3.4510164681e-02 + -1.1115385630e-02 + -4.0816386953e-02 + -1.3193813925e-01 + -7.0606149989e-02 + -1.5460166790e-01 + -8.3466775096e-02 + 2.3600355305e-02 + -8.5279896039e-02 + -8.2567321226e-02 + 7.2154258549e-02 + 3.0946767099e-02 + -1.1324595739e-01 + 2.2006443294e-03 + 5.1195907238e-02 + 2.6829862590e-02 + 1.4980579997e-01 + 1.5956262704e-01 + 4.2182578568e-02 + 1.2945341451e-01 + -4.6252771872e-02 + 1.8472874217e-02 + -9.4220877954e-02 + 8.7579675862e-02 + 3.4657279563e-02 + 1.3905370790e-01 + -2.0255837706e-01 + -5.0527149853e-02 + 3.5885748185e-03 + 6.3620737283e-02 + -2.2221572173e-02 + -6.1896253072e-02 + -4.1578201922e-02 + -1.8884483014e-01 + -6.7149978115e-02 + 1.1786723384e-01 + 3.7983877933e-02 + 1.5292021075e-01 + 3.3680596716e-02 + 6.2339016952e-02 + 3.2901827203e-02 + -9.2003616091e-02 + -2.0429841320e-01 + 1.5227212065e-01 + 1.3582768677e-02 + 1.2589833565e-01 + 1.1711468272e-01 + -2.6679015147e-02 + 9.2776064576e-02 + 1.3983284241e-01 + 3.3078642376e-02 + 1.4289669295e-01 + -2.7543884912e-02 + 1.3251179603e-02 + -5.2712242814e-04 + -3.6907501275e-02 + -5.1810030541e-03 + 5.8524126384e-02 + -7.3431774795e-02 + 4.2962180193e-03 + 9.5126285264e-02 + -9.0317872406e-02 + -3.4662127867e-02 + -1.1132969451e-01 + 9.3321115864e-02 + -1.4065030885e-02 + -1.2416595543e-01 + 5.8100079948e-02 + 7.6598781949e-04 + 1.0706087909e-02 + -4.2520882129e-02 + 2.6224170018e-03 + 3.3096701933e-02 + -3.8841704929e-02 + -1.5001084806e-01 + -4.1437255527e-02 + 2.5734168207e-02 + -1.2428862821e-01 + 9.3511843132e-02 + -1.4119192200e-01 + 3.4803492121e-02 + 5.6912306613e-02 + -4.1871781467e-02 + -6.9981503966e-02 + -7.5574177974e-02 + 1.1191073427e-01 + 4.4958619866e-02 + 2.3874168357e-03 + 9.4490030254e-02 + -4.6144221048e-03 + -1.2686066538e-01 + 4.6579164008e-02 + -6.4827932724e-02 + -1.0462548634e-01 + -1.2219544221e-02 + -1.8236720177e-01 + -1.3064034874e-01 + 2.0820186203e-02 + 9.0998611260e-02 + -5.6490902153e-02 + 9.6537250048e-02 + 3.1406902883e-02 + 1.1556677509e-02 + 7.4574506207e-03 + -5.3984513300e-02 + 2.8588644364e-02 + -1.0514841954e-01 + 6.2292427924e-02 + 9.4636752796e-02 + 3.0081911916e-03 + -2.6074495829e-02 + 1.6837396715e-02 + -1.0556688309e-01 + 5.2754185219e-02 + 5.0638346365e-02 + -3.7388754840e-02 + -9.4944230935e-03 + 1.6514146279e-01 + -4.6645712614e-02 + -1.2721570845e-02 + 6.5793964224e-02 + 1.3579276671e-01 + 4.1519154111e-02 + -7.2193804795e-02 + -1.1206766062e-02 + -1.0510191754e-02 + -1.5078850340e-01 + 8.2128540686e-02 + -5.9199875751e-03 + -3.2407998831e-02 + 5.4833652412e-02 + -2.2816860265e-02 + 3.2998502998e-02 + 6.2842440846e-02 + 1.5362010290e-02 + -2.4918525396e-02 + -2.2805455113e-02 + 5.9845840945e-02 + -1.9369939123e-01 + -2.4297027857e-02 + -2.8491452547e-02 + 8.1981632634e-02 + 3.7903738631e-02 + 6.8732714326e-02 + 4.7683354804e-02 + -1.4141415507e-01 + 3.9904917521e-02 + 4.6932249197e-02 + -2.1501569671e-03 + 9.9069398025e-03 + -4.7048190950e-03 + 5.3259042590e-02 + 8.3696975545e-04 + 6.6759310966e-02 + 6.3266449726e-03 + 4.0150347967e-02 + 1.2043774025e-01 + 7.1412919854e-02 + 1.3801105112e-01 + 3.9391370686e-02 + -7.3478918075e-02 + 5.7012395262e-02 + -2.4752798047e-02 + 1.2697128378e-01 + -2.8491576032e-02 + -2.8510264089e-02 + 1.3063182017e-01 + 4.5350908870e-02 + -1.0189779064e-01 + -1.5617609593e-01 + -5.8457688679e-02 + -9.6709911378e-02 + -8.0875917755e-02 + -1.4181400740e-01 + 5.5223312563e-03 + -5.4377265913e-02 + 1.4004434201e-01 + 1.8738967480e-02 + -1.7803124315e-01 + -1.6051707435e-03 + -7.8265785458e-02 + 4.0798689020e-02 + -5.2156472926e-02 + -2.2126223180e-02 + 4.6011537276e-02 + -5.6590231996e-02 + 2.5795501921e-02 + -3.3272936868e-03 + -1.1076056370e-01 + -1.1105518630e-02 + -2.5471883577e-02 + 1.1457041672e-01 + -1.3985705590e-03 + -5.3901586252e-02 + -7.5133248766e-02 + -1.2104935590e-01 + -5.7956667683e-02 + -1.6688479464e-01 + 9.3460654669e-02 + -5.9730431571e-02 + -1.0917420129e-01 + 1.4210720881e-01 + -1.5404366088e-02 + 6.1792050798e-02 + -4.1806987812e-02 + 1.6773335920e-02 + 2.9676435238e-02 + 2.1953697056e-02 + 2.7993249620e-02 + -9.7516928207e-02 + 9.2504719850e-02 + 1.1185869055e-01 + 2.3579606131e-02 + 1.2638888317e-03 + 4.9120420405e-02 + 2.3698656844e-03 + 1.4892410971e-01 + -4.8501493458e-02 + 1.3730568437e-01 + 3.7752641591e-02 + -6.2513786729e-03 + 1.0320075446e-01 + -7.6124142203e-02 + -2.7900711813e-02 + -8.9015360448e-02 + -5.1995146892e-02 + -4.6152304238e-02 + 1.1298305428e-02 + 9.6737901648e-02 + 6.0946568224e-02 + 5.5091016339e-05 + -4.7515588477e-02 + 3.8325636987e-02 + 4.5417442760e-02 + -4.3551030625e-02 + -3.3732613738e-02 + 1.1929749810e-02 + 9.9457517074e-03 + 1.7694058202e-01 + 6.2209327866e-02 + -5.6745760263e-02 + -1.7183046168e-02 + 8.2619305340e-02 + -9.4571121523e-02 + -1.2022559855e-01 + 1.0771133602e-01 + -6.3210807148e-02 + -4.1635974819e-02 + 2.2455474740e-02 + -5.1348550570e-02 + -3.8203020251e-02 + 1.6984658182e-02 + 6.6487539042e-02 + 5.1169792190e-02 + 2.4383129642e-02 + -1.4903732412e-01 + -1.4263399881e-01 + -4.1859816306e-02 + -4.9296860712e-02 + -4.2911800973e-02 + 2.8294418790e-02 + -9.6653809809e-03 + -5.4047790601e-02 + 1.3379017034e-01 + 1.3318779358e-01 + -2.1644114986e-03 + -2.8837476226e-02 + -5.6712776904e-02 + 1.0868702702e-02 + -4.6876733518e-02 + 2.4112072453e-02 + 3.6291555817e-02 + -9.0233590960e-02 + -4.3605689195e-02 + 1.9794105295e-02 + -7.8913275362e-02 + 1.3142184757e-01 + -2.0222398042e-02 + -2.0395705472e-02 + -3.8826270803e-02 + -3.5222917569e-02 + -1.0891092521e-01 + -1.4334304951e-01 + -2.7747278079e-02 + 3.8898417566e-02 + 8.5720105517e-02 + 6.5367486088e-04 + 1.8370793490e-02 + -9.0778640772e-02 + -9.0405282783e-02 + 6.6854025082e-03 + -1.6920895067e-02 + 6.9345269008e-02 + -7.8302860050e-02 + 8.1991659804e-02 + 1.5936176453e-01 + 3.8273259835e-02 + 1.4326504762e-01 + -7.9376344216e-02 + -5.9617806737e-02 + -4.9972350539e-02 + 4.2743534633e-02 + 1.8702536811e-02 + 1.5015378750e-02 + 1.0664283725e-02 + -3.3793764048e-02 + 2.1092897304e-02 + -1.7958955215e-01 + -1.0948135526e-02 + 4.5551676674e-02 + 5.5707597529e-03 + -3.6669030539e-02 + 4.1145069186e-02 + -3.8455544118e-02 + -7.2694139588e-02 + -3.7732162671e-02 + 5.4244709007e-02 + 2.4686369493e-02 + 4.2568202834e-02 + 3.8631722679e-02 + -1.1345056844e-01 + -8.3465424112e-02 + -1.2104206316e-01 + -1.8753051794e-02 + 1.4143399905e-01 + -2.0034679820e-01 + -4.3336524488e-02 + 1.2371390985e-02 + 4.4880752423e-02 + 8.6079689841e-02 + -4.7921484407e-02 + 3.3784167298e-02 + -9.0976936275e-03 + -6.4840747431e-02 + 8.9246072705e-02 + 5.0063295000e-02 + -6.7544869549e-02 + -2.5720802707e-03 + -9.3126379251e-02 + -4.2859604015e-02 + 3.3399827909e-02 + 1.9878266591e-01 + 1.0327909180e-01 + -1.0739928183e-01 + 3.7383215820e-02 + 2.0298021618e-02 + 1.9359165390e-01 + -4.4963151996e-02 + -7.6653519771e-03 + 1.1286790796e-01 + 1.0160203826e-02 + -7.2891149733e-02 + 1.2957736051e-01 + 1.4532137097e-02 + 4.4295962012e-02 + 4.2607898120e-02 + -8.6039600939e-02 + 1.9708395759e-01 + 8.9321071769e-02 + 4.2692257276e-03 + 1.8165153152e-02 + -2.4241658583e-02 + 2.6645914388e-02 + 1.1666113181e-01 + -1.3171298055e-02 + -3.6142515360e-02 + -1.3958640651e-01 + 9.8907721655e-02 + 3.9931520519e-02 + 1.2293868497e-02 + -2.4953018688e-02 + 1.2128810209e-01 + -5.5485701388e-02 + 1.3524324300e-02 + -2.6475382186e-02 + -7.9919008415e-02 + 1.0375335029e-02 + 4.8396380615e-02 + 7.9522499656e-02 + 5.7785670566e-03 + 8.5395505927e-02 + -4.8786466637e-02 + 3.9269056745e-02 + -1.0064226954e-02 + 6.0372245276e-02 + -1.9964355192e-02 + -1.7717454586e-02 + -1.4629225817e-01 + -5.7419080589e-02 + -4.9454040246e-02 + -5.2854430229e-02 + -2.7050718969e-02 + -1.9030133032e-01 + 3.2349162194e-02 + 4.2444969605e-02 + -2.1094098216e-02 + 2.4067315758e-02 + 3.9924774233e-02 + 1.4246648619e-01 + -1.9617950006e-02 + 8.4676667208e-02 + -1.4958874526e-02 + -6.2250656492e-03 + 1.2928188296e-02 + 8.0202966562e-02 + -4.4643907341e-02 + -3.3676549142e-02 + -1.9011149689e-01 + -1.7096599991e-02 + 4.0572072844e-03 + 1.4435136943e-01 + 2.2049278494e-02 + -7.1135474736e-03 + 8.3263839481e-02 + 3.5861771962e-02 + 1.5342860629e-01 + -1.4483497483e-02 + -3.0108766992e-02 + 7.2012550011e-02 + -8.8841475049e-02 + -6.5552183328e-03 + -2.1101146754e-01 + -6.2966533641e-02 + 5.3813566099e-02 + -2.7865772342e-02 + 3.5099251872e-02 + 9.2557479709e-02 + 2.8934303031e-02 + 1.6256768882e-01 + 7.6508831551e-02 + -1.5542539714e-01 + -1.3497363842e-02 + -1.3601132582e-01 + -1.3002728353e-01 + -3.5200632795e-02 + 1.5365483813e-01 + 5.5809302607e-02 + -5.6528114786e-03 + 2.1037908432e-02 + 2.6968129475e-03 + 6.0596186874e-02 + 6.6299756548e-04 + 7.5774953038e-04 + 1.2807694704e-02 + -5.3279865583e-02 + 1.1984921338e-03 + 1.7405807964e-02 + 1.3376709542e-01 + 2.3156896500e-02 + 1.0705372864e-01 + 1.0435543711e-02 + -5.5713908599e-02 + 1.9588146958e-02 + 5.1008191427e-02 + -9.4845177885e-02 + -9.5204893312e-02 + -1.0705411205e-01 + -1.8188496677e-02 + -1.4310288558e-01 + 5.6589154128e-02 + 1.1461571797e-02 + 2.3841829824e-02 + -9.6824490088e-03 + 2.0170097630e-02 + -2.2153817008e-03 + -8.9857591935e-02 + -5.6149801671e-02 + -6.0580593182e-02 + 1.0456234705e-01 + -1.4421818379e-01 + 1.2169036511e-01 + -5.3134402240e-02 + -1.2622758381e-01 + 3.1716359460e-02 + 6.9815074567e-02 + -1.1256257255e-01 + -8.8552057220e-02 + -7.9942000479e-02 + -1.0124971347e-01 + 7.9793522539e-02 + 8.8666855982e-02 + -1.4163520238e-01 + -1.9132032112e-02 + -1.5289139879e-01 + -1.0095314138e-01 + 8.9695452560e-02 + -9.4525963339e-02 + 6.7092312661e-02 + 8.0216274738e-03 + 7.4068708014e-02 + 2.5972148169e-02 + 2.1402035937e-03 + 5.5568930199e-03 + 1.3279338420e-02 + -1.9312573409e-02 + 2.2841763896e-02 + 9.3457063358e-02 + -2.8603537280e-02 + -9.7685162927e-02 + -3.5647260305e-02 + -1.1035137443e-01 + 1.0046594949e-02 + 1.2952704661e-02 + -6.6818450225e-02 + 1.9503470053e-02 + -6.6135198005e-02 + 1.3095074457e-02 + -1.5803428371e-01 + -1.3468862630e-01 + -6.8317305159e-02 + 6.8501905813e-02 + 5.4326191085e-02 + 6.0792834373e-02 + 3.3140713387e-02 + -1.8120853835e-02 + 6.9490921140e-02 + -1.0818901705e-01 + -1.4180100613e-01 + 6.3602671669e-02 + -9.5421950484e-03 + -1.3905147091e-02 + 1.5109156118e-01 + -8.8233995413e-02 + -6.7199911130e-02 + 4.4623656196e-02 + 1.3070407442e-03 + -2.1208708406e-02 + 2.6385044260e-02 + 1.5552274916e-01 + -1.4321695102e-01 + -7.5244028120e-02 + -8.5393203714e-02 + 3.9175721901e-02 + -2.1462956553e-02 + -9.3758294043e-02 + -2.3126412827e-02 + 3.0168011446e-02 + -5.8952224236e-02 + -1.0903480501e-02 + -8.0932017846e-02 + 3.2983735545e-02 + 6.4460428244e-02 + 2.3688507225e-01 + 8.5137414851e-02 + -2.8609327427e-02 + 5.7180283354e-02 + 4.5943240583e-02 + -2.4544998057e-03 + 1.1966142263e-01 + 4.7483628226e-02 + 1.0572179079e-01 + 1.4926296890e-01 + -2.5405112809e-02 + 9.8957379115e-03 + -2.2138453232e-02 + 5.1691508062e-02 + -2.0003427877e-01 + 4.0300819288e-02 + 6.3648280732e-02 + -1.3447121855e-02 + 7.9876811808e-02 + -1.1745132072e-01 + -1.3419345275e-01 + 4.8748615261e-02 + -1.2726073371e-02 + -5.4571731724e-02 + -6.4630160188e-02 + 3.5955420767e-02 + -4.7882103424e-02 + -4.9701235182e-02 + 9.6485803730e-02 + 1.1056881407e-02 + 5.5089069965e-02 + 8.6823473105e-02 + -1.0558918052e-01 + 9.8626649510e-02 + -6.8608727600e-02 + 1.0173899738e-01 + -3.3227743138e-02 + 6.5091405484e-02 + 7.9130075675e-02 + -5.2302293144e-02 + 3.7556167795e-02 + 7.8004627606e-02 + -8.2217601929e-02 + -2.5166626562e-02 + -7.0228334529e-02 + -5.5646556488e-02 + 1.2450097332e-02 + 1.0958800340e-01 + 1.3929735621e-01 + 2.6154736778e-02 + -1.0592645189e-01 + -9.6929963076e-03 + 4.1833990082e-02 + 8.1235483994e-02 + -1.4170499181e-01 + 1.0258504428e-02 + 5.8440106433e-02 + -2.7317422793e-02 + -2.8326927146e-02 + 2.1129834887e-02 + 9.9402341047e-02 + -6.9423885103e-02 + 5.8123561501e-02 + 1.0467454160e-01 + -1.3053286766e-01 + 3.1553898334e-02 + -5.5111801695e-02 + -5.4990645650e-02 + -2.0902181225e-02 + 1.1148132781e-01 + 7.7273445800e-02 + -7.0034817119e-02 + 3.0837196011e-02 + -8.0716088526e-03 + -2.3626385260e-01 + 2.7215525841e-02 + -1.4639447009e-01 + 1.9122786877e-01 + -2.3813566114e-02 + -1.6660701851e-01 + 1.4551548814e-01 + -9.4352768332e-02 + -1.3263812756e-02 + -7.6793710015e-02 + 1.1930678570e-01 + -1.2798918466e-01 + -6.9914421028e-02 + -8.0504704923e-02 + 2.6073458098e-02 + -1.1625855793e-01 + -8.7672829926e-02 + 5.1073309847e-02 + 7.4854668731e-02 + -5.3547037223e-02 + -1.3688412758e-01 + -9.7619912845e-02 + -8.4357591208e-02 + 1.3313574551e-02 + -5.6099923425e-02 + 9.6406370927e-02 + -1.1328389640e-01 + -2.3278090776e-02 + 1.0089864195e-01 + -1.3077604804e-01 + -1.9602823103e-01 + 7.7716352087e-02 + -1.5758359813e-01 + 7.8316244075e-02 + 2.0308695457e-02 + 7.2443695292e-02 + 3.2410456180e-03 + -6.9704306539e-02 + 1.8979122771e-01 + -1.0558632583e-01 + -3.4556475900e-02 + -1.3578433659e-02 + 5.2902822507e-02 + -1.4732908525e-01 + 2.3719688397e-02 + -3.6445026471e-02 + 3.8889536494e-02 + -1.1033405985e-01 + 9.4180202910e-02 + -3.3934630737e-02 + 3.8121356568e-02 + 1.3810252416e-02 + -3.2048425236e-02 + -9.8208991358e-02 + -1.1901726779e-01 + 2.6137781975e-02 + 2.0186223805e-02 + 9.9429461578e-02 + 8.5963108571e-02 + 1.2795799358e-01 + 6.8721511586e-03 + 8.5533909309e-02 + -7.6620077838e-02 + -4.6888552148e-02 + -3.7208114357e-02 + -1.0089636024e-02 + -2.6247315024e-02 + 5.8913939933e-02 + 2.1529654800e-02 + 1.0714088293e-01 + 1.1874185105e-01 + 3.9340868737e-02 + 1.1738578406e-01 + 4.1463192927e-02 + -4.6612730885e-02 + 6.6380463643e-02 + 2.7338616158e-02 + -9.8412758353e-02 + -8.8414624988e-02 + -8.2741770273e-02 + 3.0226137399e-02 + -1.3806294862e-01 + 6.5491927060e-03 + 6.1221854202e-02 + 1.4281952119e-02 + -1.2206119945e-02 + -5.2347037894e-02 + -2.9974062534e-02 + -3.4479960139e-02 + -4.6187819740e-02 + 6.6276781728e-02 + 5.7111809034e-03 + -3.7153521908e-02 + 1.5736353267e-01 + 2.6090362336e-02 + -1.7305554089e-01 + 4.0260518279e-02 + 9.5297420470e-02 + 5.2273117736e-02 + 1.4286507964e-01 + 1.4125512776e-01 + 5.8463060557e-02 + -5.5666898361e-02 + 5.3415170571e-02 + -2.3234189342e-02 + 1.0975765701e-01 + 8.4316066361e-02 + -1.5732815660e-03 + 2.2369775044e-02 + -2.3301701458e-02 + 3.5287122542e-02 + 1.6533257595e-02 + -8.9290020919e-03 + 1.6546375265e-01 + 9.0099630284e-02 + -1.3275873691e-01 + -2.9460145628e-02 + -1.7305789855e-02 + 9.1646234267e-02 + 6.7321850121e-03 + 4.8190970538e-02 + -1.3777532801e-01 + -7.7196876977e-02 + 1.2339111219e-02 + 4.3048125594e-02 + 1.7402503252e-02 + 1.4011833927e-01 + 1.3023835089e-02 + 7.3729663753e-02 + -8.1168740200e-02 + -5.2985126655e-02 + -2.0891848478e-02 + 3.4198623481e-02 + 7.8275108898e-02 + -6.0960583556e-02 + 1.5404103797e-02 + 2.9649131661e-02 + 8.9716294411e-02 + -8.3207625766e-02 + 8.3942423125e-03 + -9.3760211485e-02 + -7.7789550090e-02 + 2.1164844249e-02 + -1.7065740767e-01 + -1.1423626044e-02 + 1.0480830994e-01 + 4.4011732360e-02 + 3.7262238508e-02 + 8.4850026644e-02 + 5.0750112572e-02 + 7.9688689195e-03 + 9.3494663206e-02 + -1.0548679000e-01 + -1.0872653674e-01 + 1.0321552298e-01 + -8.0965583417e-02 + 8.4509060551e-02 + -1.7306027750e-02 + -2.4437201856e-02 + 1.4096499990e-01 + -4.0384581821e-02 + -2.2763670040e-02 + -2.3493692079e-02 + 1.8328309713e-02 + 4.6125655631e-02 + -1.5716912404e-01 + 9.2824562519e-03 + 7.0470842874e-02 + -2.3671742465e-02 + -3.5769298314e-02 + 5.8725315767e-02 + 6.3021657613e-02 + -5.3935428917e-02 + -1.8277194023e-02 + -7.6944920382e-02 + -9.1010576427e-02 + -1.0634867883e-01 + -3.9811675445e-02 + 7.4992572248e-02 + 6.7190338453e-02 + 7.9319647627e-02 + 2.4868997536e-02 + -1.0832663434e-01 + 5.7597135948e-02 + -6.0909726095e-02 + 4.9963949323e-02 + 4.1091454932e-02 + 1.8947744252e-01 + 1.8554425829e-02 + -3.3853715943e-02 + -9.8542555599e-02 + 6.5639533321e-02 + -4.9391259085e-02 + -2.9653380940e-02 + 1.0360080138e-01 + -4.2459080730e-02 + 1.5609077858e-01 + 6.6637496653e-02 + -7.7568631476e-02 + -1.8561902458e-02 + -5.2271333366e-02 + -5.3938983943e-02 + 1.1642511227e-02 + 8.9431891772e-02 + 1.2035529718e-03 + 1.4747028444e-02 + -3.4192127169e-02 + 3.5565409556e-02 + 7.5438822856e-02 + 2.0804135159e-03 + -3.1388436790e-02 + 3.9132523425e-02 + -8.3530250999e-02 + -3.3138398246e-02 + -2.2311120216e-01 + -2.0448644949e-01 + -4.9088401465e-02 + 4.1472557090e-02 + 8.3873824940e-02 + 3.3529487533e-02 + -9.5270742433e-02 + 6.1445395005e-03 + 5.1201330877e-02 + -1.2766566240e-01 + 2.3761628456e-02 + 1.7267312738e-02 + -3.2584342188e-02 + -7.0634131183e-02 + -5.8749629684e-02 + -1.2625265134e-01 + -3.8401188168e-02 + -1.0529255899e-01 + 5.3869622345e-02 + 4.6986603379e-02 + 1.3907354813e-01 + -5.7211087688e-02 + -1.0880749445e-02 + -9.7859601534e-02 + -8.8786081760e-02 + 1.1893860073e-01 + -2.1569464363e-02 + -1.1494969718e-02 + 6.3410674840e-02 + -7.5062952182e-02 + -2.1111296732e-03 + 2.7488129519e-01 + 1.1633599296e-02 + 1.5099659402e-02 + 2.5832257645e-01 + 3.6729061693e-03 + 2.2450222631e-02 + -7.8357277188e-02 + 1.3027341525e-01 + 3.8675649877e-02 + -5.7418638072e-03 + 1.2667056499e-01 + 5.1917316633e-02 + 1.0848500473e-01 + 5.7987486550e-02 + 1.6342753332e-02 + 7.3821061280e-02 + -5.1069069431e-02 + 3.3004386694e-02 + -2.6346033641e-02 + 6.7606762947e-02 + 7.5714569287e-02 + 2.5307588209e-02 + 9.5048980438e-02 + 9.2010534198e-02 + -1.2013625446e-02 + 1.1789435549e-02 + -2.7489110707e-02 + -1.6079206191e-02 + 8.0324772548e-02 + -1.3013898281e-01 + -2.2944972716e-02 + -1.4439373032e-02 + 3.9504575547e-02 + 5.6959683034e-02 + -9.8785466962e-03 + 1.7731065886e-01 + -2.0847036151e-02 + 1.2892631701e-01 + -4.6685026240e-02 + -8.7835894915e-02 + -7.6127075894e-02 + 1.9012368704e-02 + 2.0862797238e-02 + -1.0509856947e-01 + -1.0493277995e-01 + 1.1913402310e-01 + -1.1441465314e-01 + 7.9957006016e-02 + 1.7176244603e-01 + -1.0676326386e-02 + -5.3354297366e-02 + 6.7002963603e-02 + -2.3582967787e-02 + 3.2964323670e-02 + -7.7113127387e-02 + 5.2469067609e-02 + 2.0777799111e-02 + -1.7436877980e-01 + 5.1942117726e-03 + -5.6089893192e-02 + 7.8813717130e-02 + 4.9595840307e-02 + 1.3159233320e-02 + -1.0676224892e-02 + -1.4372620360e-01 + 9.7820066122e-02 + -2.4421987411e-02 + 4.3139947366e-02 + 1.5903910377e-02 + -9.1588919414e-02 + 1.4944088053e-01 + 6.9929079470e-02 + -4.9510040837e-02 + -7.2857680672e-02 + 6.9858164663e-02 + -1.9733022733e-02 + 4.9652782440e-02 + 3.9591685443e-02 + -2.0696749870e-01 + -5.3854104853e-02 + -4.5002896075e-02 + 4.0555392936e-03 + -2.2056503482e-02 + -9.0030341795e-02 + -1.2635530657e-01 + 8.0630349012e-02 + 6.8382923314e-02 + -3.4769133609e-02 + -1.3130049356e-02 + -3.0124562222e-02 + -1.2693643447e-02 + -5.6152947473e-02 + 3.2659550555e-02 + -1.3335236723e-01 + 7.2907460479e-02 + -2.0345466378e-02 + 5.1945628382e-02 + 1.0175858646e-02 + -5.1218538807e-02 + 9.1753547625e-02 + 5.4318072340e-02 + 3.2069871568e-02 + -8.2844057373e-02 + -6.6575301372e-02 + -1.5879013396e-02 + 8.2191642565e-02 + -8.1591660966e-02 + -8.8587200785e-02 + 1.0469239370e-01 + -4.1250835912e-02 + -1.4477708179e-01 + 6.2451928600e-02 + -1.1622358897e-01 + -1.2649513797e-01 + 1.0056550958e-02 + -3.5049752794e-02 + 1.2807618630e-01 + 5.0370775442e-02 + 6.7509538360e-02 + -3.9197583627e-02 + -1.0833223519e-02 + 4.2285956331e-02 + -2.2631778034e-02 + -9.4269080788e-02 + -5.2443950124e-02 + -6.3986908743e-02 + -5.0971192355e-02 + 1.7610167712e-01 + -2.1322127780e-03 + 1.6181256414e-01 + -5.8405238398e-02 + 2.7194931548e-03 + 4.5417405507e-02 + 1.9111015055e-04 + -1.0820145032e-01 + -8.1599253953e-02 + 3.8388096634e-02 + -3.9691081162e-02 + -7.5806441986e-02 + -1.6643244979e-01 + -3.8360314460e-02 + 1.8459965222e-01 + 6.8641427812e-02 + -5.0532044371e-02 + -1.0324609952e-01 + -2.1010771358e-02 + 8.6598107004e-02 + -8.2576612230e-02 + 5.1444305836e-03 + -5.1655878636e-02 + -1.0857498189e-01 + -7.4142549751e-02 + -6.2713655062e-02 + -8.1545772199e-02 + 1.2159461328e-01 + -7.9420050332e-02 + -2.4600325525e-01 + 3.0558057258e-02 + -9.0626811465e-02 + 6.5142066283e-02 + 5.5119899037e-02 + 1.9518828290e-02 + -1.0528134219e-01 + 4.5188428960e-03 + 8.7833959180e-02 + -2.1478491814e-02 + 1.1112377615e-01 + -4.4527269250e-02 + 2.5948165541e-02 + 1.0770738630e-01 + -2.5582220107e-02 + 1.0221726822e-01 + -1.1933676324e-02 + -2.4526269401e-02 + -3.9196632789e-02 + -3.5029267467e-02 + 4.3368508768e-02 + 3.2978702255e-02 + 2.4641594979e-02 + 6.0289687443e-02 + 3.9028494964e-02 + -1.4049074186e-01 + 2.1987083687e-01 + 1.7274532392e-02 + -2.1053303910e-02 + -1.2419266543e-01 + 5.1638289756e-02 + 1.0691838189e-01 + -5.4947163655e-02 + 8.4523907194e-02 + -9.9762609288e-02 + 6.2765925448e-03 + -4.6315744133e-02 + 5.9411362908e-02 + 8.1908731443e-02 + 4.0282493558e-02 + -3.2007085284e-02 + 9.6729350153e-02 + 1.5661069328e-02 + -2.7546559246e-03 + -7.9765195581e-02 + 5.9385350921e-03 + -1.7439286069e-02 + 3.6538456056e-02 + 3.9237629943e-02 + 1.2954742770e-01 + -1.7550058348e-01 + -7.5149839331e-02 + -4.4183162520e-03 + 1.4383370517e-01 + 9.6469339547e-02 + 2.5299837763e-02 + 1.1331471397e-02 + -9.7461935943e-02 + -2.7550184183e-02 + -1.2822988290e-01 + -1.0014914632e-01 + 8.9286544795e-02 + -6.6824770849e-02 + 4.3084279774e-02 + -4.9785222944e-02 + 9.6791298998e-02 + -7.2772875249e-02 + 4.5300324075e-02 + -3.5423204725e-02 + -2.5714725691e-02 + -1.3260842242e-01 + 7.7175393480e-02 + -3.1362112394e-02 + -1.6983403817e-01 + 4.4898028520e-02 + 3.7466103443e-02 + 6.7450104657e-02 + -4.7297826356e-02 + -7.5336617481e-02 + 6.3258744451e-02 + 1.4078940875e-01 + -5.0994550759e-02 + 7.7454536041e-02 + -1.5841925640e-01 + 9.3201805785e-02 + 9.3902215013e-02 + 8.8413067762e-02 + 5.2996133920e-02 + 3.2740028477e-02 + -2.8877643292e-02 + 6.3659857697e-02 + -1.3380143062e-02 + -1.0660943157e-01 + -6.5414421453e-02 + -2.0696277895e-02 + 1.1625487779e-01 + 5.4688847648e-02 + -9.6768127457e-04 + -7.0866188080e-02 + 4.7458152772e-02 + -5.7056260527e-02 + 1.8846138708e-01 + -1.1410081452e-01 + 3.8488246876e-02 + 3.5272163717e-02 + -9.8040075262e-02 + -8.7247354514e-02 + -8.0404654959e-02 + -1.6332226205e-02 + 1.1075875053e-01 + -5.7771378864e-02 + 3.3806690411e-02 + -1.9166630714e-02 + 1.5133811585e-02 + 9.4169704571e-04 + -5.6238890543e-04 + 4.7291248924e-02 + -1.4134856298e-02 + -6.1746173777e-02 + 1.2102962045e-01 + 1.0288193153e-02 + 5.5211631715e-02 + 5.7652794394e-02 + -5.0149075553e-02 + 2.2607558724e-02 + 8.7724993537e-02 + -2.9207631293e-02 + 1.0383653570e-01 + 3.6970559581e-02 + 1.8884893226e-02 + 1.5331511926e-03 + -8.9631603007e-02 + -1.9359456483e-02 + -4.0149222274e-02 + -8.4363780676e-02 + -1.6660768041e-01 + 8.6543601774e-02 + 6.0096069625e-02 + 2.0696496787e-01 + -7.8490880731e-02 + 7.0970753548e-03 + -6.6158660955e-02 + 6.4292167481e-02 + -1.0931616815e-01 + -7.1372048166e-03 + 1.6059305818e-01 + 2.9765007005e-02 + 3.0791822945e-02 + -8.3917069522e-02 + -8.8364322081e-02 + -1.8224559335e-02 + 5.7737435854e-02 + 6.6399606111e-02 + -6.6244026698e-02 + 3.8160855222e-02 + -4.9595100635e-02 + -6.8588660628e-02 + 1.2519187153e-01 + -8.0452461489e-02 + 3.0866275351e-02 + -9.2009422461e-02 + 3.3989531454e-02 + 4.7439573802e-02 + -4.5141965807e-02 + 7.7735214181e-02 + 1.1643933183e-01 + -2.0063619016e-02 + -4.0039190660e-02 + 7.4562062135e-02 + 8.6735035937e-02 + -7.2609567562e-02 + -8.8308939818e-03 + 7.0156397669e-02 + 9.3581161584e-03 + -3.3821322346e-02 + 5.9817733649e-02 + -4.8664758426e-02 + 7.1027332145e-02 + 3.6700216201e-02 + 7.3083449517e-02 + 8.4560336250e-02 + 1.2351987715e-01 + -8.9185757164e-02 + 1.1152809684e-01 + -2.1470868226e-02 + -1.6465384667e-02 + -5.9577717799e-02 + 1.9911207247e-01 + -1.7777970368e-02 + -1.7285456248e-03 + -7.0613231630e-02 + -1.9085472386e-01 + 1.0401147927e-02 + 6.0795478018e-02 + 4.4713561018e-02 + -1.2711076961e-01 + -3.2275693749e-04 + -2.6268478366e-02 + 1.9425051814e-02 + 1.9445204753e-02 + 1.8892630637e-02 + -1.0073323286e-01 + 1.4891351195e-01 + 7.5574141590e-02 + 8.6184167344e-02 + 4.4937580616e-03 + -1.4290312503e-01 + -1.2682431645e-01 + 4.0831363777e-02 + 5.2962731233e-02 + -3.1401602144e-02 + -7.5399372918e-02 + 1.4939428088e-02 + 1.9705351927e-02 + 5.5783365223e-03 + 2.0584094111e-01 + -3.4436135577e-02 + 4.9335781418e-03 + 8.8315429652e-03 + 9.2921767121e-02 + 4.6830611134e-02 + -1.4073657418e-01 + 7.8930750380e-02 + -3.5955174284e-02 + 3.8146078873e-02 + -1.3073351559e-02 + -1.4160338009e-01 + 3.9670305144e-02 + -2.9831879029e-02 + 1.2370047370e-03 + 5.1033063376e-02 + 1.1747402496e-01 + 4.0902194261e-02 + 6.2041492292e-02 + 6.2378542981e-02 + 1.1459915461e-01 + -9.2779223166e-02 + 1.4837407525e-02 + -8.7998055386e-03 + -5.5709409686e-03 + -3.8760432267e-02 + -2.5994647186e-03 + 2.0101125780e-02 + 4.5998224358e-03 + -8.2208945193e-02 + -1.4019840750e-01 + 5.8939995584e-02 + 1.1611810343e-01 + -1.0782338787e-01 + -9.3295911167e-03 + -2.8797859256e-02 + -1.8920989804e-02 + 7.1143414726e-02 + 1.7158532442e-01 + 6.9243296225e-02 + -2.6374203648e-03 + 6.1937377733e-02 + 1.1242060038e-02 + -1.8067508053e-01 + -2.2604505080e-02 + -9.3681976912e-02 + 3.2014533326e-02 + -4.6295582959e-02 + -5.6157884606e-02 + 7.9308336217e-02 + 2.1852014057e-02 + -3.4504147114e-02 + -7.0898896299e-02 + -2.7160576709e-02 + -3.0643879086e-02 + -1.0601922440e-01 + 2.7811121003e-02 + -2.1257600672e-02 + 3.0967518345e-02 + -1.3014987376e-01 + -7.9088792768e-02 + -8.5608985994e-02 + 4.5251025899e-02 + -2.1444153206e-02 + -6.3521995134e-02 + 6.8339470583e-02 + 7.9964197041e-02 + 1.1157383578e-01 + -2.9279135754e-02 + -4.4493149545e-03 + 2.1799283514e-02 + -2.1660924817e-02 + -6.2514583592e-02 + 5.8299880058e-02 + 5.1952937581e-03 + -4.1303045755e-02 + -1.1302039630e-01 + -1.2887765107e-01 + -3.5586826529e-02 + -6.3975152326e-02 + -9.4745430303e-02 + -4.0459693789e-02 + 1.4617422259e-02 + -9.5867474150e-02 + -8.6026649408e-02 + -7.8066091009e-02 + -8.8897728010e-02 + -7.6390820918e-02 + -1.0807877110e-01 + -4.3640158144e-02 + 2.2590257938e-02 + -1.4590169448e-02 + -8.1014386408e-02 + -7.1933325488e-02 + 2.0913443447e-01 + -3.4066392168e-02 + 4.7457069673e-02 + 3.6401630087e-02 + -5.1845175578e-02 + -9.5095255827e-03 + 5.3494860969e-02 + -2.3725859265e-02 + -9.3036297268e-02 + 6.1419703185e-02 + 7.2656845889e-03 + -3.8262613519e-02 + 5.1304178931e-02 + 8.5297922452e-02 + 2.5618047400e-02 + -7.4996008116e-02 + 4.2605824304e-02 + 9.1471257441e-02 + -4.0932790384e-02 + 1.3728303003e-01 + -1.5959005456e-02 + 5.2289397571e-02 + -1.1319788979e-01 + -1.8767419476e-02 + -5.5854954874e-02 + -4.3718812588e-02 + 3.2936904469e-02 + 1.8886966853e-02 + -2.7854958790e-02 + 1.2991885774e-02 + -4.6622274159e-02 + 1.3350830256e-01 + -1.6593330666e-01 + 1.9448758198e-01 + -1.1130368035e-01 + 3.1091254201e-02 + -3.6394621458e-02 + -2.2066841641e-02 + 1.4058088816e-01 + 4.3405924471e-02 + 3.3530123905e-02 + -1.1801551898e-01 + 1.3123099156e-01 + 6.2537746459e-03 + -5.0467083145e-02 + -7.8229193668e-02 + 3.8067529591e-03 + 9.3958356294e-02 + -2.6438984762e-04 + 6.3423916298e-02 + 1.5410722019e-03 + -9.0200121251e-03 + 1.8778971088e-02 + 1.3051236450e-01 + -1.1470922073e-02 + 1.4183077901e-01 + 1.9135192867e-02 + -3.1727184266e-02 + 5.3260766502e-02 + 6.4782607103e-03 + 4.2446824773e-02 + -6.8784360522e-02 + -3.1725968739e-02 + -3.6131031443e-02 + -2.0626016590e-02 + 1.4316532324e-01 + 4.8759048660e-02 + -1.2090279638e-01 + 3.5278146253e-02 + -8.4536532100e-02 + 1.0330843000e-01 + 8.2948350845e-02 + 7.0919862891e-02 + 8.6754063743e-02 + 1.3019341579e-01 + 5.1880705049e-03 + 1.5068457150e-01 + -6.7293853301e-02 + -6.1026861149e-02 + 8.5174501569e-02 + -1.6466517665e-02 + 1.0012353348e-01 + 5.5952753961e-02 + -5.0483646858e-03 + -9.5367512742e-02 + -8.9072881830e-02 + 7.0724095532e-02 + -6.8539446535e-02 + 6.7019499375e-02 + -6.3862128851e-02 + 4.2624256342e-02 + 5.2789395604e-02 + 5.4133525111e-02 + -3.9952682801e-02 + 6.9488463950e-02 + -9.6843649479e-02 + 1.0024283450e-01 + 1.1414745389e-01 + -3.1285480338e-03 + 1.7977431945e-01 + -4.9796768864e-02 + 4.3417217083e-02 + -7.0052649479e-03 + -1.3906458039e-02 + 1.3696746706e-02 + 1.1514126603e-01 + 7.1583023877e-02 + 4.8589942650e-02 + -1.6294267915e-01 + -1.2279908904e-01 + 5.3046075781e-02 + -7.8561235140e-02 + 4.4868237835e-02 + -3.7972342154e-02 + -4.0930881585e-02 + 8.3134871942e-02 + 1.3540006160e-02 + 8.4942361163e-02 + -6.5479101984e-02 + -5.4264008468e-04 + 5.9736823473e-02 + -9.4592366279e-02 + 4.3599493427e-03 + -1.3936237555e-01 + 3.4058427799e-02 + -5.7117985377e-02 + -5.5091651470e-02 + -1.0497270919e-01 + -2.1325146180e-03 + 1.0140731005e-01 + -7.4295443791e-02 + 1.2628761668e-01 + -7.3506196727e-02 + 4.6514517319e-02 + 8.2067077054e-02 + 7.8448134294e-02 + 8.5150610974e-02 + 2.7730914542e-02 + 2.2027126088e-02 + -5.9140153953e-02 + 2.2783427672e-02 + -1.8996630446e-01 + -1.2157815703e-02 + -5.8100341428e-02 + -1.7257482813e-01 + 3.2580460044e-02 + 5.1281404142e-02 + 6.2297481943e-03 + 1.0978903531e-01 + 3.8661659984e-02 + 2.1003763398e-02 + -4.1010872792e-02 + -8.6190886162e-02 + -4.4403599566e-02 + 1.2708558331e-01 + -6.9170741947e-02 + -1.3317023374e-01 + -7.1132551044e-03 + -5.5512205605e-02 + -9.1362189951e-02 + 3.9503433855e-02 + 7.7169512857e-03 + 1.6548060590e-02 + -3.0153895122e-02 + -6.6271605019e-02 + 1.3797967723e-02 + 5.7379626190e-02 + 4.4102673666e-02 + -3.6361481870e-02 + 1.4729542173e-02 + -5.4728706761e-02 + 2.0677959259e-02 + 2.2269239820e-02 + -3.4048779185e-02 + 2.0806244990e-02 + -3.0972612557e-02 + -7.2396290422e-02 + 2.8885444697e-03 + -4.9872598547e-02 + -9.8827107628e-02 + -4.3063785052e-03 + 5.0750226244e-02 + -1.3646713480e-01 + 5.7873257749e-02 + 1.4941751685e-02 + -6.5657330352e-02 + -6.1825477146e-02 + -4.5699880511e-02 + -8.2030226440e-02 + -3.1194801213e-02 + -8.8578682425e-02 + -1.2562021236e-02 + 5.7253692201e-02 + 1.1698447099e-01 + -1.1334850462e-01 + 8.5783905034e-02 + 1.0718655063e-01 + -1.1325834200e-01 + -6.7964748996e-02 + 3.6176179252e-02 + 1.7375058748e-02 + -4.1105081794e-02 + -2.9586950755e-02 + 5.5155289076e-02 + 4.7470287180e-02 + -4.0651726673e-02 + -3.9730667296e-02 + -6.2735324499e-02 + -2.7589211675e-02 + 2.0561279822e-02 + 3.1542711136e-02 + 5.0987610245e-03 + -1.0958384189e-01 + -9.3177850247e-02 + 1.7593436373e-01 + 2.6434147652e-02 + 4.1058242762e-02 + -3.5177875956e-02 + 5.6319137035e-02 + -1.5014488491e-01 + 1.6505125528e-01 + 6.2267018872e-02 + 9.2622476925e-02 + -6.4807773533e-02 + -1.7540900180e-02 + -1.9416843921e-01 + 1.6037044749e-02 + 7.6998681736e-02 + -1.1866384407e-01 + -8.2077603671e-02 + -7.7198887843e-03 + 4.0679237185e-02 + -8.5959357938e-02 + -1.3266887254e-01 + -8.5506641053e-02 + 3.1935251448e-03 + 7.9400701774e-02 + -4.5894986054e-02 + 6.7470115467e-03 + -1.0425290826e-01 + -6.1915612787e-02 + -2.7802831681e-02 + -1.4133403508e-01 + -2.8240117333e-02 + 1.0440474171e-01 + 9.2805619325e-03 + 6.8657765060e-02 + -3.3037095444e-02 + 6.4776687998e-02 + 8.2693585131e-03 + 4.4924627913e-02 + 1.1409742537e-02 + -4.2260398959e-02 + -4.7117227620e-02 + 4.9934731316e-02 + -2.4530041840e-02 + 1.1479785710e-01 + 1.4363706052e-01 + -1.6941808647e-01 + -7.0648693068e-02 + 2.4923433252e-02 + -5.9767004386e-02 + 4.1666257213e-02 + -2.6717143915e-02 + 3.8342430747e-02 + -2.9367117690e-02 + -1.4342270946e-01 + 2.6893018252e-02 + -3.7743059357e-02 + -5.4210632661e-02 + 7.3058812997e-03 + 3.4838964183e-02 + -8.5799513703e-03 + 9.3900460954e-02 + 4.1760818558e-02 + -1.1815116875e-01 + 8.4201885879e-02 + -6.3348530073e-03 + 1.3456910995e-01 + 8.6583080918e-03 + -1.6636914175e-01 + 2.3555817396e-02 + -2.8486227202e-02 + -4.4564269723e-02 + 1.1055792145e-02 + -9.8696106940e-02 + 4.9072736783e-03 + -2.3626499095e-01 + 4.2163612631e-02 + 2.1208560485e-02 + -7.0983699670e-02 + 1.2294376665e-01 + 1.4819415963e-01 + -1.1000521740e-02 + 1.1264312684e-01 + 6.1434403045e-02 + -1.4268027302e-02 + 2.8841846669e-02 + -1.3209148836e-01 + -1.7620161751e-01 + -7.9473886544e-03 + 9.2864293117e-02 + 2.6025717098e-02 + 1.7198467605e-04 + -1.5008719149e-02 + 1.1240979196e-01 + -1.7849867974e-02 + 6.4027417355e-02 + -5.8139176242e-02 + 4.4051153847e-02 + 6.5062202601e-02 + -4.6263160337e-05 + -5.9854203910e-03 + 7.3872505260e-02 + -1.7721451861e-02 + -1.5879741254e-01 + -5.2703350271e-02 + 6.2868294147e-02 + -6.8204768656e-02 + -2.3525538994e-03 + -9.8107557691e-02 + -1.2132464067e-01 + -3.6767425810e-02 + -1.5895770074e-01 + -8.2073190557e-02 + 1.0019132100e-01 + -2.3502673822e-02 + -2.5955783728e-03 + -1.2422027093e-01 + -1.0346614599e-02 + -6.1679267140e-02 + -9.3772601922e-02 + -2.5075508903e-02 + -3.4995865717e-02 + -4.4425283174e-03 + -4.5037442386e-02 + 4.6548766138e-02 + 2.8455158489e-02 + -8.6887352019e-02 + -1.3809632480e-01 + -3.3817523622e-02 + 7.6819805488e-02 + 9.3841351851e-02 + 9.4809468579e-02 + 9.9844249720e-03 + 9.6043373876e-02 + -2.3002723713e-02 + 1.1791943324e-01 + -6.3989316716e-02 + 4.4061932222e-03 + -4.9481152105e-03 + 1.2287286197e-01 + -7.4671090055e-02 + -6.4848433420e-03 + -4.0371827111e-02 + 5.6950027460e-02 + -8.5212483871e-02 + -1.4678504185e-02 + 1.2704125846e-02 + 7.7525631607e-02 + -2.5686430400e-02 + 3.8167856174e-02 + -2.2602670056e-02 + -1.1694977714e-01 + -3.8767381471e-02 + 8.5237058631e-02 + -9.1889826531e-02 + 5.8859550334e-02 + 7.9412830747e-02 + 2.4543803075e-02 + -1.0796019415e-01 + 4.9526186430e-03 + 1.6135821076e-01 + 9.2695642247e-02 + -4.5467829420e-02 + 7.4904817566e-02 + 6.0118635822e-02 + -4.0345795776e-02 + -1.7440764296e-02 + -1.2577047324e-01 + -6.0864573469e-02 + 1.0578731092e-01 + -1.1157456921e-02 + 4.7583116593e-02 + -5.2907665004e-02 + -1.6361669308e-02 + 9.9483719949e-02 + -4.5785981972e-02 + -9.2048538336e-02 + 2.5077882739e-02 + -7.0063272112e-02 + 4.7234201426e-02 + -1.3158866878e-01 + 8.9696605968e-02 + -4.4324714616e-02 + 2.8038874514e-02 + 1.5734206991e-01 + 7.5025912510e-02 + 6.7772127807e-02 + -1.7373735300e-01 + 7.6063107703e-02 + -7.1926204430e-02 + 7.3439611987e-02 + 3.1091948163e-02 + -1.0174270247e-01 + 3.1433278117e-02 + 2.7141298520e-02 + -1.5046977568e-01 + -6.0003637392e-02 + -1.2859771149e-02 + -1.0043573146e-01 + -6.8373339211e-02 + 1.5902842911e-02 + 1.2986648660e-01 + 9.8177962440e-03 + -3.2936264491e-02 + -3.3644397104e-02 + 1.4414292206e-02 + -1.6764840519e-02 + 5.2394716880e-02 + -7.4001655057e-02 + 1.2050231803e-01 + -3.2354988334e-02 + -8.5031397600e-02 + -2.2097351075e-01 + -7.2261337956e-02 + 6.6439026702e-02 + -5.1232412353e-02 + 5.5887626534e-02 + -1.5993252247e-02 + 2.3129369025e-02 + 1.2829494903e-02 + -1.5215408296e-01 + 1.5060812737e-02 + 7.7875239260e-02 + -5.8163394273e-02 + -1.1516256526e-01 + 1.5858873682e-01 + -5.2744706636e-02 + 1.5615698953e-02 + -3.2592203774e-02 + -3.7071097692e-02 + -3.5878957983e-02 + 9.8841449547e-02 + 7.0536362117e-02 + 1.5715802623e-01 + -5.2645896798e-02 + 5.7116140396e-02 + -2.7478049688e-02 + -1.1927837173e-01 + 6.8655682373e-02 + 8.8158424143e-02 + -3.8284065071e-02 + -9.2982882367e-02 + 5.5169224684e-02 + -1.2426602629e-01 + 5.2317780308e-02 + -7.0258854717e-02 + 2.3819234240e-02 + -1.3903820791e-01 + -7.1676040308e-02 + 7.2415698176e-02 + -2.3507291432e-01 + -5.3134475028e-02 + 4.7497904897e-02 + -4.0063040162e-02 + -1.1637914675e-01 + -6.7409146023e-02 + 1.8426458776e-01 + -1.1305797248e-01 + -1.5839210155e-01 + 2.3785237779e-03 + 1.4405798220e-02 + -3.9821608904e-02 + -9.0823230104e-02 + 4.9463414411e-02 + 7.3685577692e-02 + -8.8569314948e-02 + -2.0002014800e-01 + 1.0123930519e-01 + -9.2299123867e-03 + -8.0341433448e-02 + 1.0908587650e-01 + 6.0494974161e-02 + -6.7425796076e-02 + -5.6686044114e-02 + -6.0841839247e-02 + -1.9336442851e-01 + 1.4768881857e-01 + 8.3821716228e-02 + -5.7600092021e-02 + -4.0311445496e-02 + 9.7613781186e-02 + 7.5646140926e-02 + 4.9652421807e-02 + 4.9838540048e-02 + -7.2905613550e-02 + 4.7013193975e-02 + -3.3326136858e-02 + 2.3638291951e-02 + -4.3754752288e-02 + 1.0164301685e-02 + -1.1466743797e-01 + 5.5141754268e-02 + 1.1438321673e-01 + -3.0439215451e-03 + 1.6516116866e-02 + 7.4878403568e-03 + -9.8577706518e-02 + -6.0395532406e-02 + -4.6908598319e-02 + -2.2189936349e-02 + -5.6598940452e-02 + -2.7249965086e-04 + -2.7272353890e-03 + 1.8800875169e-02 + -5.3477774526e-02 + -3.1032410539e-03 + -2.9403215079e-02 + 4.8357329110e-02 + 6.9359607554e-02 + 1.2129219990e-03 + -7.1085202890e-02 + -1.0898370762e-01 + -1.2820694084e-01 + -7.4949496075e-02 + -1.6648084465e-01 + -1.0797751528e-01 + -1.1095386185e-01 + 1.7031356865e-01 + -1.8233162849e-02 + 9.2828173665e-02 + 9.3824179378e-02 + 1.2810083225e-02 + -3.0521122871e-02 + -3.1575879827e-02 + -4.0520966694e-02 + -2.6318921474e-02 + -4.9258210174e-03 + 6.9005803008e-02 + 3.1399424244e-02 + 7.4365418105e-02 + -8.2112072324e-02 + -1.1946610989e-01 + 4.2178985191e-02 + -1.4314466428e-01 + -3.6866048856e-02 + -2.3493248873e-02 + 4.3374642876e-02 + -1.3518632705e-02 + 1.4019009788e-01 + 4.2105781223e-02 + -5.8505838886e-02 + 5.2604525872e-02 + -7.7083289148e-02 + 7.6323143745e-02 + -8.1148768154e-02 + -1.1899647754e-01 + 7.4238021416e-02 + 7.5836090527e-02 + 1.0449275003e-02 + 2.6863245902e-02 + -1.0808642666e-01 + 1.0018928107e-01 + 6.1602886187e-02 + -1.1865517809e-02 + 3.6121034898e-02 + 3.0597132328e-02 + 7.0741326222e-02 + 1.0555376008e-02 + 4.5926714621e-02 + -4.9157890362e-02 + 1.2334150049e-01 + -3.9978720150e-02 + 2.0774246580e-02 + 1.2118322199e-01 + 1.5168929248e-02 + 3.5184182315e-02 + -2.3858683281e-02 + 1.7947857975e-01 + -7.5165053525e-02 + -1.0024581919e-01 + -1.2654090525e-04 + 7.5151865699e-03 + -1.8720135283e-02 + 1.5151455655e-01 + -1.0853758171e-01 + 1.9828585136e-02 + 1.3705125649e-01 + -6.6644975597e-04 + 1.2876192608e-02 + -7.9873574095e-02 + 8.3352280315e-02 + -1.0309566018e-01 + 2.0563544355e-01 + -3.2669214652e-03 + 3.7242691903e-02 + -7.7107305368e-02 + -5.6871070849e-03 + 1.0863863543e-02 + -5.4417973095e-02 + 4.5479489994e-02 + 7.2140769320e-03 + -3.8391162723e-02 + 5.9193030010e-02 + 5.6550899469e-02 + 6.0025396840e-02 + 5.9260441298e-02 + 4.7764312957e-02 + 8.1501084493e-03 + -7.4274953505e-02 + 6.9734140896e-02 + -1.5302298359e-01 + 1.1572174222e-02 + -1.7135948973e-02 + -6.5637236252e-03 + -2.6842306081e-01 + 8.8888869402e-02 + -2.4216937076e-02 + -7.9139244660e-02 + -7.9207447170e-03 + -3.0669437212e-03 + 1.5271319822e-01 + 3.2961909324e-03 + -4.0110706558e-02 + -3.6511793606e-02 + -1.6767204962e-01 + -9.4129366013e-02 + -9.9574665214e-02 + -8.7349908156e-02 + 7.5095704381e-02 + -1.3536392994e-02 + 4.3933921541e-02 + 2.1120014605e-02 + -3.8998482390e-02 + -1.4635373193e-01 + -9.6970360595e-02 + 2.4994809163e-02 + 3.7672457014e-02 + 1.0094344796e-01 + 2.2420460289e-02 + 1.2993165417e-01 + -9.2249645241e-02 + 1.5866445671e-02 + 4.5632870178e-02 + -1.0647578607e-01 + -6.5497448396e-02 + 5.3710300048e-02 + -4.2565937102e-02 + -6.8654396766e-02 + 9.8165618642e-02 + -1.1054945706e-01 + 6.1896429543e-02 + 1.9874840435e-02 + 1.6036991486e-02 + 1.2005234885e-02 + -6.6845746195e-02 + -2.6082863289e-02 + -1.1614219783e-01 + 2.2108784271e-02 + 1.4794652987e-02 + 1.4759326964e-01 + -5.2731897207e-02 + -6.9722255437e-03 + 1.1819567059e-01 + 1.6325960095e-02 + 2.3859299695e-02 + 1.4580046409e-02 + -1.3687064907e-01 + 4.6187737299e-02 + 8.4502666943e-03 + -1.1332305645e-01 + -1.0908453361e-01 + 5.5772232624e-02 + -5.9796385396e-02 + -9.3371809153e-02 + -5.7614869126e-02 + -2.8831819972e-02 + -4.5283886468e-02 + -2.4006077919e-02 + 3.8183065940e-03 + 7.6794631926e-02 + 1.3402191800e-01 + 7.3867097649e-02 + 9.8999505447e-02 + -7.2004173796e-02 + 5.2160209631e-03 + -4.2930863512e-02 + 2.7123691015e-03 + -3.4325603901e-03 + 1.4409228480e-01 + -1.4493393684e-01 + 6.2897125455e-02 + 3.1172109442e-02 + 1.0593310674e-01 + 4.6943619551e-02 + 7.5362745113e-02 + -2.1370108575e-02 + 3.1800822240e-03 + -1.8750481055e-01 + -3.2175811115e-03 + 2.8866295116e-02 + -1.0850194775e-01 + -2.4734236494e-02 + 7.0347649040e-04 + -6.2514118049e-02 + -3.9042702713e-02 + -2.7179247269e-02 + -1.4665185782e-01 + 6.8629717138e-02 + -1.1922567860e-01 + -1.0162823687e-02 + -1.7251490531e-02 + 8.1541451556e-02 + 2.9485403563e-02 + -7.4570413416e-02 + 4.6968443308e-03 + 1.6628674626e-01 + 6.4875923767e-02 + -5.8799794888e-04 + 3.0650356974e-02 + -8.8032320228e-02 + 1.8233868803e-02 + 4.0381743932e-02 + -7.6705767247e-02 + -6.4568089587e-02 + 4.2297420222e-02 + 1.1835820200e-01 + 1.9638876983e-02 + 5.2689485566e-02 + 2.3439385844e-02 + 4.0706950914e-02 + -1.5385813764e-01 + -2.3924868262e-02 + 3.6287160494e-02 + 1.1944482921e-01 + 5.7722302525e-02 + -5.5411336057e-03 + 2.2070195003e-02 + -6.1010685555e-02 + 2.5356888015e-01 + -3.8412990772e-02 + 1.1083915845e-01 + -6.2720324081e-02 + -6.5539886733e-02 + -9.0532398778e-02 + 1.1977681307e-02 + 5.5788198089e-02 + 7.0204789204e-02 + 5.5618884663e-02 + 3.4783574719e-02 + -1.0404985175e-01 + 1.7528013518e-01 + -4.9101713994e-02 + -3.1487495194e-02 + 8.7751370964e-02 + -8.1522909783e-02 + -1.0919163781e-01 + -2.2530974803e-02 + 9.7823295628e-02 + -8.0223260661e-02 + 4.1373983643e-02 + -1.8020172085e-02 + 1.8057034766e-01 + 1.8479411140e-01 + 9.2369107266e-02 + 1.2201888424e-02 + -2.4648761558e-02 + 5.0227031978e-02 + -1.8443615419e-02 + 7.6575352557e-02 + 2.3996827622e-02 + -1.7038319191e-01 + 7.3984840418e-02 + -9.5222448930e-02 + -1.9955784353e-02 + -5.7808233282e-02 + 2.9779733976e-02 + 3.1052326452e-02 + 4.9156719171e-02 + -4.9982751011e-02 + 3.7509609469e-02 + -4.3448019421e-02 + -3.6755410301e-02 + 1.5854447921e-01 + -1.7612096799e-01 + 1.0774071948e-01 + 4.9464338738e-02 + -6.4445902825e-03 + -1.3959596653e-01 + -3.0868728448e-02 + -2.7743578250e-02 + 7.1460496482e-02 + 3.3123257167e-02 + 7.6032915267e-02 + 7.9277062839e-02 + -5.9866966127e-02 + 9.2049948509e-02 + 1.7640735730e-01 + 1.2840321715e-01 + 2.0050513310e-01 + 3.3815186835e-02 + -1.8885925687e-02 + 7.1123311630e-02 + 1.0624656473e-01 + -8.5044629397e-02 + -3.0210509249e-02 + 3.3177751113e-02 + 1.3176588963e-01 + -7.6403907132e-02 + 1.9959860351e-01 + 2.3425627922e-02 + -2.7674468388e-02 + 3.7211242190e-02 + 1.3658581167e-01 + -7.6875476948e-02 + 1.4304281009e-01 + -6.4625624878e-02 + -1.3950140980e-02 + -5.6396484312e-02 + 9.1008624202e-03 + 2.8843347081e-02 + -8.6105816102e-02 + -1.5365025420e-01 + -5.4197660058e-02 + -1.3741104922e-01 + 3.8469089722e-02 + 8.4592481979e-02 + 7.4220895812e-03 + -4.5296822214e-02 + 1.6020863839e-02 + -9.5145339939e-02 + -6.2081440785e-02 + -3.5499620093e-02 + -7.1133878328e-02 + 2.3987558348e-02 + -5.4770879706e-02 + 6.3329691103e-02 + 6.0823661889e-02 + -1.6049555976e-02 + -3.0254853242e-02 + -1.8623463230e-01 + 8.0951549290e-03 + 9.9108930763e-02 + -5.0868576822e-02 + -1.3829470429e-01 + 4.9471286405e-02 + 1.5714623404e-03 + -3.7123946854e-02 + -1.1885100076e-01 + 8.9859673988e-02 + -8.0502476728e-02 + -3.8117340898e-03 + 1.0936758340e-01 + -7.0308444667e-02 + -5.6584859012e-02 + 2.4942947528e-02 + -1.0316527481e-01 + -1.1148804233e-01 + 1.2313939613e-01 + 5.3549795929e-02 + 4.3467046523e-02 + 6.9004471795e-02 + -1.2675430074e-01 + 1.0280305485e-01 + 8.1893510247e-02 + 1.5101604051e-01 + -1.7860056529e-02 + 6.6599132430e-02 + -3.0901376303e-02 + -6.4805106578e-02 + 1.0937282256e-01 + -1.6642023709e-01 + 5.3568227109e-02 + -6.7271738491e-03 + -1.5289772917e-01 + -4.2024167080e-02 + 4.2912008680e-03 + 1.2101695550e-01 + -1.2704577765e-01 + 5.3157170025e-02 + -7.3588360694e-02 + -5.3080288114e-02 + -2.7395926099e-02 + -3.3011462148e-02 + 8.8242822513e-02 + -9.5093685955e-02 + -1.0739070593e-01 + 4.3497217838e-02 + -5.4489062062e-02 + 3.5183464155e-02 + 1.3940024838e-01 + 1.8310407970e-02 + 1.3129796635e-02 + -9.2388325593e-03 + 8.6738346529e-02 + 9.3388045783e-02 + 5.1095941697e-02 + -5.6194370303e-03 + 9.3158114863e-03 + 9.1017239722e-02 + -1.0865354376e-01 + 3.9839702137e-02 + 1.4920580322e-01 + -3.0578996341e-03 + -7.4063666616e-02 + 1.1529792181e-01 + 2.7859324691e-01 + 9.7292565855e-02 + 3.1431231216e-02 + 9.9750079040e-02 + -7.9520571155e-02 + 1.1514341585e-02 + -7.0282535936e-02 + 8.4393750477e-05 + 5.3707272487e-02 + -7.1642551248e-02 + 3.9079735447e-02 + -1.1636306713e-01 + -9.5017518278e-02 + -8.6274583730e-03 + -1.8660430606e-01 + -4.5241197962e-02 + -1.1070020959e-01 + 2.9259598508e-02 + 6.0363001051e-02 + 7.5561946250e-02 + 4.6966895883e-02 + 3.7242178090e-02 + -1.5565658934e-02 + -6.9820586193e-03 + 1.3300158016e-01 + -7.4363785117e-02 + -1.9848281819e-02 + -2.2707838804e-02 + -5.7584243068e-04 + -4.6497954774e-02 + -6.8719059802e-03 + -3.3442935771e-02 + 7.8550382292e-02 + -1.4657004275e-01 + -1.1509930145e-01 + -4.6771296289e-02 + 1.4489476484e-01 + 2.0195464157e-01 + 8.2275515720e-02 + -2.7390944716e-02 + 5.7363989774e-02 + 3.3046967174e-02 + -4.2942746862e-02 + -6.6651514330e-02 + -6.0043372372e-02 + 8.8490318284e-02 + 5.9541947921e-02 + -1.2881765591e-02 + -3.5477948240e-02 + -1.6992423905e-01 + -6.9815168749e-02 + 3.5139583205e-02 + -5.1023916371e-02 + -1.4029697155e-01 + 2.2260375818e-02 + -5.8288857547e-02 + 4.0115559959e-02 + 3.3706658979e-02 + -1.0194028529e-01 + -5.3299639410e-02 + 1.0811505719e-01 + -1.0202387907e-01 + 5.2105843075e-02 + -4.8161825872e-02 + 7.0242152364e-02 + 1.2086269498e-02 + 5.1593093410e-02 + -1.3099422015e-01 + -1.2368726945e-01 + 6.3786776706e-02 + 9.7944035161e-03 + 1.9727498368e-03 + 4.5608504241e-02 + -5.1832287171e-02 + 6.2491401423e-02 + 8.2482174871e-02 + 9.3936682510e-02 + 3.9488586868e-03 + 3.5099755636e-02 + 8.6247382690e-02 + -2.0218839229e-02 + 1.0420051399e-01 + -6.3384143955e-02 + -7.9312854811e-03 + -1.1016512260e-01 + -1.0765140861e-01 + -5.2722788282e-02 + -1.2500362696e-02 + -3.7570691829e-02 + 2.0807241107e-01 + -9.8305149822e-02 + -1.0819002057e-01 + 1.5776554236e-01 + 1.3526341077e-03 + 1.3873748165e-01 + -3.0484758825e-02 + 5.7199211065e-02 + -1.3036837592e-01 + -1.4259077603e-01 + 7.5826414285e-03 + -1.4200851448e-02 + -6.8977903427e-02 + -7.2462566339e-02 + 7.4778853733e-02 + 1.7945166084e-01 + -9.7351743596e-02 + -6.8422796211e-02 + -1.1414405662e-01 + 1.3677528019e-02 + 6.0053417050e-02 + -5.1856193380e-02 + -5.0487825445e-02 + 3.6163241001e-02 + -1.4426975917e-02 + 9.6471701337e-02 + 2.4138711133e-02 + 1.1203962694e-01 + -6.0952848986e-02 + -7.9634348279e-02 + 1.1230203433e-02 + -2.7700066119e-02 + -8.1988327252e-02 + -7.2531101560e-02 + 2.5189036294e-02 + 1.0484172595e-02 + 2.9575601661e-02 + -2.8212513350e-02 + 1.5472051437e-02 + 2.1996647137e-02 + -9.3025864328e-04 + -6.2846610288e-02 + 9.6098931195e-03 + 4.0712358836e-02 + 6.8647451568e-02 + -3.4601925766e-02 + -8.9468937472e-03 + 7.7441219273e-02 + 1.2516831840e-02 + 7.0083889381e-02 + 6.5026107803e-02 + 9.2284105286e-03 + -1.0323402512e-01 + 1.6266567326e-01 + -1.4999753133e-01 + 1.2634326742e-01 + 9.9059285957e-02 + 1.2611353236e-01 + -6.9020438861e-02 + 4.5054271467e-02 + -1.1021516291e-01 + 6.4356224291e-02 + 4.3106424721e-02 + -6.2820284038e-02 + -6.3654509123e-02 + 1.0492854884e-03 + 7.4799407131e-03 + 7.3138932896e-02 + 9.8414138959e-02 + -5.2055499098e-02 + 1.7350452642e-01 + 2.0051279989e-02 + 4.3274148162e-02 + 1.5374435552e-01 + -6.2766715838e-02 + 3.4278746368e-02 + -5.6405549075e-02 + 8.2923684820e-02 + 8.6835609050e-02 + -8.5289481696e-02 + -4.0902519274e-03 + -6.0985088172e-02 + 7.9098507454e-02 + -7.0998621724e-02 + -8.3473998042e-02 + -7.1183172976e-02 + -7.8112070352e-03 + -1.1544906762e-01 + -1.7076486758e-02 + -1.4661414271e-01 + 5.1664388354e-02 + 1.0197466840e-01 + -4.9742125886e-02 + 3.8332180857e-02 + 9.9502728208e-02 + 1.1017161151e-02 + -2.1616151593e-01 + -3.6778350081e-02 + -3.9731224671e-02 + 5.0465926315e-02 + -6.7838505350e-02 + -9.3830944490e-02 + -9.6418103625e-02 + 7.9625754724e-02 + 2.6684754740e-02 + 6.8326859334e-02 + -8.4364799393e-02 + -7.6367079180e-02 + 1.5441183287e-02 + 9.5909184856e-03 + 1.5254411958e-01 + -2.4548178781e-02 + 6.1134254034e-02 + 1.0968317175e-02 + -1.5517743943e-01 + 8.5695120391e-02 + -2.6211612464e-02 + -2.5281308952e-02 + -1.6734435954e-01 + 2.0428950753e-02 + -5.2758532672e-02 + 1.9400234212e-01 + 1.6116174956e-01 + -1.1828286413e-01 + 4.9424492403e-02 + 9.7478347663e-02 + 1.6896412085e-01 + 8.4598480917e-02 + 1.1676959586e-01 + -2.5641411117e-02 + -7.4859523970e-02 + 8.1065465494e-02 + 2.1509735144e-02 + 8.0190703748e-02 + -4.5082547397e-03 + -8.1163063168e-03 + 1.8159418016e-03 + 1.2468553051e-01 + 2.8296078873e-02 + -6.8342838890e-02 + -3.3241862923e-02 + 2.7995094588e-02 + 1.2892499635e-02 + 7.9195887945e-02 + -3.5491414143e-03 + 5.6798301835e-02 + 2.3299580184e-03 + 1.4687823755e-02 + -3.4899995240e-02 + -6.7676701366e-02 + -1.4461407978e-01 + 5.9602321606e-03 + -5.0969813799e-02 + 3.3756404242e-02 + -1.4226928356e-02 + -1.5717550602e-01 + -2.2412195053e-02 + 1.4801017559e-01 + 7.0720648436e-02 + -2.2805371478e-03 + -1.0770876537e-01 + -5.8815157297e-02 + -6.2277715934e-03 + -7.2631991323e-02 + -3.1508639098e-02 + 4.7065475573e-02 + -9.3448449778e-02 + -5.0347762531e-02 + 8.3646376659e-02 + -7.1892797796e-02 + -6.3090438321e-03 + -1.0901214004e-01 + -2.2644551821e-02 + 9.2745213230e-02 + -4.7124172206e-03 + -4.9312363567e-02 + 6.7726644113e-02 + 4.3040850881e-02 + -2.7864287970e-02 + 1.0074997971e-01 + 1.4998457993e-02 + 4.2066985684e-03 + 3.0590200103e-02 + 2.0963986594e-02 + -8.9802883200e-02 + -5.0787574923e-02 + 7.4481681791e-02 + 2.0132278295e-02 + 7.6655576090e-03 + 5.6616209468e-02 + 8.9157197558e-02 + -2.7110269297e-02 + -2.1271547999e-01 + -5.0143283860e-02 + -8.8390537552e-02 + -8.5236063441e-02 + 4.1766632175e-03 + 1.7555289047e-01 + -1.2749302556e-01 + 7.0703924240e-02 + 1.1592286549e-01 + -6.2863263069e-02 + -7.6532592326e-02 + -2.3258118387e-02 + -3.1050099048e-02 + -3.1313593427e-03 + 1.2428424162e-01 + -2.2213843721e-02 + 2.1069052752e-01 + 1.0039768632e-01 + 3.4954099250e-03 + -6.2438072054e-02 + -2.2360005628e-02 + 1.6327667727e-02 + -2.9859283970e-02 + -1.4674549178e-01 + -4.5705420465e-02 + -2.1180184262e-01 + 2.8506216793e-03 + -7.0485118801e-02 + -4.8202181301e-02 + 1.7511247368e-01 + -5.0053018633e-03 + 1.1055338401e-02 + 1.2238367385e-01 + -1.0542165502e-02 + 1.0399664214e-01 + -2.5685900954e-02 + 9.3767581831e-02 + -1.1595486911e-01 + 5.5303311353e-02 + -2.3099950488e-02 + -3.2129063647e-02 + -6.6933855437e-02 + -4.7834093467e-02 + -2.1572803342e-02 + 2.8970062799e-02 + -1.1506434323e-01 + -1.7059882289e-02 + -1.2930410261e-01 + 8.2633771331e-02 + -2.7135546271e-02 + -1.3012302276e-01 + -3.3546572378e-02 + -1.0847887670e-01 + -1.1142718874e-01 + 1.0399824123e-01 + 5.2609930480e-02 + -1.0428034339e-01 + 8.8512196295e-02 + 5.3742349616e-02 + 3.5189273168e-02 + 2.3902841532e-03 + -8.5663260369e-02 + 4.0774499020e-02 + -1.0721949446e-02 + 5.2289016226e-02 + -1.4593438337e-01 + -9.7948046353e-02 + -1.2417295249e-01 + -5.3692268010e-02 + -1.5360767465e-01 + -5.1703960405e-02 + -1.9082860327e-02 + -7.0785299659e-02 + 7.8622925766e-02 + 1.4322895254e-01 + 1.0420652360e-01 + -6.4523988583e-03 + 1.6428250390e-01 + -5.2823432484e-02 + -5.6118415438e-02 + -7.9100174211e-02 + 1.1243569127e-01 + -1.1773273650e-01 + 9.8528164081e-02 + 7.8901717910e-02 + 3.8275067451e-02 + -7.2836479889e-02 + -7.0720185115e-02 + -5.6330965121e-02 + -5.0176563583e-03 + 4.9161964664e-02 + -6.5136771465e-02 + -4.4418193229e-02 + 8.6803598731e-02 + 1.3633051507e-01 + 1.2886016193e-01 + -6.4753159337e-02 + 3.9853326338e-02 + -9.2895973071e-02 + 2.4056126627e-02 + -1.0715694711e-01 + -6.6554082621e-02 + 4.0188678655e-02 + 1.1063390011e-01 + -5.9338766156e-02 + 2.9416212621e-02 + 1.2227969284e-01 + 6.4137192399e-02 + 6.2394446212e-04 + -4.9420213404e-02 + 1.8385321492e-01 + -3.9026038217e-02 + -5.1613624452e-02 + -5.4946464368e-03 + -1.4372099983e-02 + 2.5034232413e-02 + 3.6917745061e-02 + -8.1208534297e-02 + 1.2762240718e-01 + 9.7945561318e-02 + -3.6432309261e-02 + -7.0611664834e-03 + 2.6449990221e-02 + -1.2592713703e-01 + -7.1109612374e-02 + -6.6047509391e-02 + -8.8130916633e-02 + -8.4998185550e-03 + -2.0375984865e-01 + 1.0340894725e-01 + 9.2397743956e-03 + 1.7349659856e-02 + -6.6649113339e-02 + 6.0616582756e-02 + -3.6587193617e-03 + 1.3369793783e-01 + 2.7782707594e-02 + 7.4899034017e-02 + 4.9906817326e-02 + 3.2751916136e-02 + 7.4514171976e-02 + 8.0338789946e-02 + 4.3583082670e-02 + -1.3784531108e-02 + -1.5526580671e-02 + 3.9840262357e-02 + -8.7929931296e-02 + 7.4084436191e-02 + 3.3499023291e-02 + -6.8521161175e-02 + -1.2309448423e-01 + 3.7535837348e-02 + 6.2804615558e-02 + 7.1433044605e-02 + -1.2604143560e-01 + 1.3012201533e-01 + -9.5721393420e-03 + -1.6818083594e-01 + 2.6521386829e-02 + 3.1119814740e-03 + 1.8459733991e-02 + 1.3381005817e-01 + -2.6031766296e-02 + 5.7902690503e-02 + 2.1635061421e-02 + 1.0425626412e-01 + -5.9619944639e-02 + 4.4165876879e-02 + 1.4157358226e-02 + 4.1000996267e-02 + 1.3760186844e-01 + 8.8242378230e-02 + 1.0393308312e-01 + -1.9088300573e-02 + 1.8258024094e-02 + 1.7433109444e-02 + 3.3689471860e-03 + 4.0810127522e-02 + -3.4275483980e-02 + 1.4839984235e-01 + 6.7220188089e-02 + 1.1732283435e-02 + -8.5608015992e-02 + 2.9368457780e-02 + -4.4012537220e-02 + -6.8966745090e-02 + 6.2776337417e-02 + 1.0764877992e-01 + 1.7311608973e-01 + -2.2192173599e-02 + -3.9293816566e-02 + -1.9593814980e-02 + 7.3746814072e-02 + 1.2978273322e-01 + -7.7509151387e-02 + -8.4930508020e-02 + 1.2468828353e-01 + -3.6568425557e-02 + 1.6871246811e-02 + -2.0052438246e-02 + 4.8547128114e-02 + -4.4619270907e-02 + 3.4285108066e-02 + 3.4544314021e-02 + 1.2425852879e-01 + -2.8616333925e-01 + 2.9099243800e-02 + -3.0847921465e-02 + 7.6337470928e-02 + -6.1810391073e-02 + -1.7305087285e-02 + 5.5416246802e-02 + -1.1570816144e-01 + -6.7448489474e-02 + 6.0295240146e-02 + -1.9563417789e-02 + 8.2536214057e-03 + -4.9940878471e-02 + -5.4924855225e-02 + -5.8788745465e-02 + 2.2800674157e-02 + -1.0369152990e-01 + -7.1367252815e-02 + -4.5363347156e-02 + 6.9336402713e-02 + -2.8861405871e-02 + 1.2725455293e-01 + -4.0398845900e-02 + 5.6077051629e-04 + 9.0796542005e-02 + 1.0912995777e-02 + 3.8500922980e-02 + -1.8406605547e-02 + 4.1898182168e-02 + -3.3569664124e-02 + -4.9972562890e-02 + -2.1357515029e-02 + 4.8087832456e-02 + -5.7451759242e-02 + 6.3776083287e-02 + -1.7126454788e-02 + -1.2233088421e-01 + 5.4000566010e-02 + 5.1234254740e-02 + 1.2591291513e-01 + 7.4719174682e-02 + 6.6964827566e-02 + 1.0592593465e-02 + 4.7890102931e-02 + 6.0588883802e-02 + 2.1035411229e-01 + 1.0054771117e-01 + 1.9401674848e-02 + 8.7864852492e-03 + -4.4393899294e-02 + -1.0942235597e-02 + -1.3455486889e-01 + -8.3020846267e-02 + -1.1759069573e-02 + -1.7572690252e-02 + 3.2287792789e-02 + -7.4913613487e-02 + 5.8618824847e-02 + -7.4368615229e-02 + -1.8349356328e-01 + 1.0005187913e-01 + 2.9033665652e-02 + 2.6568045027e-02 + 1.1792950657e-01 + 9.5396613914e-02 + -1.4653435463e-01 + 1.5991203759e-02 + -3.9426661717e-02 + 7.4395530874e-02 + 1.6700441329e-02 + -7.6464307562e-02 + 2.2768832802e-02 + 7.4332145901e-02 + 3.0119137580e-02 + 2.7028650322e-02 + -5.7323266654e-02 + -7.2718879228e-02 + 3.0874049855e-02 + 1.0402949687e-01 + 7.4146282670e-02 + -2.2672371869e-02 + -8.4312280314e-02 + -1.8616468179e-01 + -3.7839658380e-02 + 4.1712753799e-02 + 1.2878170651e-01 + -5.3852929327e-02 + 9.8411298546e-02 + -9.4597398719e-02 + -9.0278445729e-05 + 8.9697052767e-03 + -9.6159794458e-02 + 6.8682174354e-02 + 1.0288276614e-01 + 8.0161972091e-02 + 4.2851659963e-02 + -2.4450345379e-02 + 2.5554821837e-02 + -3.5110843881e-02 + -1.2768896642e-02 + 2.2515639855e-02 + 8.1587417629e-02 + 3.6225078632e-02 + -3.6521049948e-02 + -9.3215775274e-02 + 1.0933229064e-01 + -1.9289791651e-02 + 1.1963619950e-01 + 1.0384101121e-02 + 9.0340719124e-03 + 6.8828662051e-02 + 4.4408272047e-02 + 8.5758437527e-02 + -6.0235442526e-02 + 8.9421204768e-02 + 6.3648995974e-03 + -1.8827034995e-02 + -1.0861798622e-02 + -3.8364250835e-02 + 1.6281875777e-02 + -7.4878550362e-02 + -1.0017718287e-01 + -1.0511240962e-01 + 2.4878987024e-02 + 4.6124471447e-02 + -1.2820990108e-02 + -1.9221622829e-01 + -1.1430099726e-01 + -1.2439326528e-01 + 8.3113280216e-02 + 7.9923714747e-03 + 1.1669239019e-03 + -9.6421020776e-03 + -4.4222065392e-02 + 1.5181784913e-02 + -9.3557306896e-02 + -4.2559165789e-02 + -1.3742955902e-02 + 1.0152011517e-01 + 6.0511136075e-02 + 2.4827924293e-02 + -2.6305704664e-02 + 1.6843466094e-01 + 4.4063573200e-02 + 1.3132040123e-01 + -4.6517940120e-05 + -9.9415166205e-02 + -2.6146392152e-02 + -2.9564362729e-02 + 3.6690198654e-02 + -9.5644891756e-03 + 4.0412569952e-02 + 4.1347935901e-02 + -9.1980028220e-02 + -1.7009023213e-01 + 3.1899975692e-02 + -6.4680982303e-02 + -1.0708155437e-02 + -1.4765449062e-02 + 7.7354098727e-02 + 4.5168300833e-03 + 3.8346163138e-02 + -2.8892664171e-03 + 7.7915989643e-03 + -8.5551366161e-02 + 7.5866024055e-02 + 8.8400371393e-02 + -7.0280148373e-02 + -3.0895606756e-02 + -5.2421806659e-02 + 1.0535308033e-01 + 1.1782844203e-01 + 2.9198168728e-03 + -1.4271635547e-01 + 4.0908978719e-02 + 9.5297653040e-02 + -1.4401079165e-02 + -1.4492685469e-01 + -1.0199435436e-02 + 3.3605041789e-02 + 4.0524101610e-02 + -2.9012615784e-03 + -1.4292618191e-01 + -1.3718639220e-01 + -2.4454531268e-01 + 5.6327751791e-02 + 2.7837621905e-02 + -9.9327174169e-02 + -2.0143515164e-03 + -8.7616400458e-02 + 6.8661882053e-02 + 2.2926610301e-03 + 1.5104783820e-02 + 2.0196809138e-02 + -2.1909826786e-02 + -1.9814619076e-02 + 6.1359066001e-02 + -5.1704230104e-02 + 9.0534585729e-02 + -1.3733840493e-01 + -8.6459105829e-02 + 7.6827351392e-03 + -1.1267931804e-01 + 3.0089542117e-02 + -9.6983995582e-02 + -1.1829716188e-01 + -1.1004519751e-02 + -8.3905426480e-02 + 6.8376123364e-02 + 4.9444701622e-02 + 7.5275174897e-02 + 4.3531198457e-02 + 7.5553481294e-02 + 8.2607529758e-02 + -4.7860273879e-02 + -1.6698883203e-02 + 4.5920979643e-02 + 1.1476340678e-01 + -1.2266119102e-02 + 1.7898283636e-02 + -8.4697607735e-02 + -2.4599308111e-02 + -3.5408730837e-02 + 4.3382190769e-02 + 2.6505317728e-03 + -4.0339280656e-02 + 1.2810686928e-01 + -6.9191007057e-02 + -1.4779508950e-02 + 1.6010593618e-01 + -9.1548831643e-03 + -1.0372342991e-03 + -6.4500624518e-02 + -2.1941201380e-02 + -9.3482330754e-02 + -4.7129432449e-02 + -7.8323146548e-02 + -1.5296077130e-01 + -5.0875009932e-02 + 7.4336633593e-02 + 8.3424301639e-02 + 3.0130839700e-02 + 3.0965227334e-02 + -7.4859218936e-02 + -1.3296862630e-01 + -7.1963447418e-02 + 7.5084546905e-03 + 1.1178681181e-01 + -1.9016046162e-01 + -5.3671965441e-02 + -2.2257499037e-02 + 3.9379481402e-02 + -4.3967839561e-02 + 4.3307730031e-02 + -4.4189785821e-02 + 9.8979928272e-02 + 8.3094360759e-03 + -9.5324872769e-02 + 5.5582242928e-02 + -3.6537840398e-03 + -1.0169026116e-01 + -7.8917009823e-02 + 4.6643340328e-02 + -7.9645844632e-02 + 1.1388220181e-01 + -1.2617712217e-01 + 5.9155691323e-02 + -4.5782039824e-03 + 4.2898941203e-02 + -5.6723620560e-02 + 3.7934957832e-02 + 9.8565777948e-02 + 5.5030292887e-02 + 7.2301170248e-02 + 7.5008832393e-02 + -1.8567699559e-02 + 3.7395410005e-02 + 9.1587578533e-02 + 8.5630087708e-02 + 1.4808550206e-01 + -1.7694013772e-01 + -1.4698034732e-01 + 4.9757078553e-02 + -8.3388718980e-03 + -8.9542699762e-03 + -7.4118260008e-02 + -5.2254459963e-02 + 8.5289897107e-02 + 1.0012638982e-01 + 1.3974373794e-01 + 2.7808996626e-02 + -3.3525599343e-02 + 2.5570442853e-03 + 7.0104935189e-02 + -6.7637515871e-02 + 3.0641479657e-02 + -3.1366909819e-02 + -1.5916440366e-01 + 1.2848670437e-01 + -1.1717221794e-02 + 4.1595148349e-02 + 1.0034436441e-01 + -2.0212782351e-02 + 2.0805730548e-03 + 7.6966444943e-02 + 4.1869334519e-03 + 4.3488142460e-02 + -5.0991876340e-02 + 2.5975366174e-02 + -2.9295276071e-02 + -8.1529599630e-02 + 1.9781995814e-02 + -1.2434043693e-01 + -1.0226311581e-01 + -2.2525746265e-02 + -3.4469302374e-02 + 4.4438673381e-02 + 1.0785629540e-01 + 9.1514076617e-02 + -9.3992594491e-02 + 7.4053845968e-02 + -6.7917291092e-02 + 2.5422887302e-02 + -4.5317432246e-03 + -3.8194218802e-02 + -7.8331676697e-02 + -2.1486844556e-02 + 6.0544258923e-02 + -1.6868741638e-01 + -1.7045500475e-02 + -1.2796161731e-02 + -1.2653035364e-01 + 9.7602451109e-02 + 1.8465476041e-02 + 2.0001134044e-02 + -2.6862880626e-02 + 1.8276750113e-02 + -1.7903550859e-02 + -9.2766843982e-02 + -5.8227326679e-02 + 2.7667487434e-02 + -2.9212921603e-02 + 8.8982937771e-02 + -5.1814489115e-02 + -3.1196034943e-03 + 7.8363042646e-02 + 3.0816121825e-02 + 1.9831473087e-02 + 1.8742077387e-02 + 5.5700772330e-03 + -1.4727753321e-01 + -1.0261101497e-01 + 6.0846701119e-02 + 9.1377894669e-02 + 4.9278703859e-02 + -4.3717367416e-04 + -4.2442916788e-02 + 4.1397902380e-02 + -1.7410293803e-02 + 1.9673207945e-04 + 9.0870712844e-02 + 4.9454032336e-03 + -6.3607691050e-02 + 1.7740789007e-01 + -6.2752552808e-02 + 1.1793870829e-01 + 7.4504515006e-02 + -1.0713445892e-01 + -5.9057856542e-02 + 1.2076354051e-01 + 5.3988009404e-02 + 9.7198945466e-02 + 4.1648472916e-02 + 4.7431285863e-02 + -1.4334759897e-02 + -7.1292523702e-02 + -2.9586366088e-03 + 1.2986395038e-01 + -8.2224634946e-02 + -7.9657091064e-02 + 4.1199275780e-02 + 4.4305587255e-02 + 5.8533113769e-02 + 8.0013740897e-04 + -1.2285979914e-01 + -2.6038306499e-03 + -7.0751249886e-02 + 8.6347127854e-02 + -1.9089263312e-02 + 9.2725537506e-02 + 8.1692262548e-03 + -1.7681404891e-01 + 1.1852819642e-01 + 5.1100579174e-02 + 8.1031570279e-02 + 8.1368584016e-02 + -8.5176103967e-02 + -8.5596168169e-03 + 3.4453898902e-02 + -5.0270265970e-03 + 3.7391260263e-02 + -1.4897341265e-01 + -6.5596389784e-03 + 3.6343529945e-02 + -1.3014053688e-01 + -1.6165023855e-02 + 7.1650654410e-02 + -2.5086829790e-02 + 1.0033604632e-01 + 1.3614218906e-01 + 8.3036454519e-02 + -8.7880821828e-02 + -1.2141980157e-02 + -1.0346871700e-01 + -1.6551880419e-02 + -1.6400206877e-02 + 6.1260936951e-02 + 1.2213751014e-01 + 2.3830724544e-02 + 1.3837692877e-01 + 9.3505441197e-02 + 8.9867015606e-02 + 2.0837298304e-01 + 2.5275922078e-02 + -8.8326387100e-03 + 9.7910752488e-02 + 4.4886287306e-02 + -1.0182649390e-01 + 8.4711632402e-02 + 1.3259680695e-03 + -1.5548712649e-03 + 5.1008264090e-03 + 2.6955610360e-02 + -4.3414336809e-02 + 1.0328049462e-01 + -1.0055267125e-01 + -6.1839441113e-02 + -1.1818345123e-03 + 9.2771177157e-02 + -6.2532748636e-02 + 7.3115660946e-02 + -1.0026753500e-02 + -1.7972038898e-01 + 6.7525459324e-02 + -1.2113184358e-01 + -2.3513068255e-02 + -8.3928812006e-04 + 1.1007758312e-01 + 2.3351354346e-03 + 1.7089587127e-02 + 2.8518482995e-02 + -1.5088040400e-01 + -1.3236015938e-01 + 5.4515610087e-02 + 9.1655705953e-04 + 1.2114691242e-01 + -7.6126914624e-03 + 1.3565520237e-01 + 2.8988400008e-02 + -2.6782721045e-02 + 2.5887881834e-03 + -1.2031269642e-01 + 7.8554884806e-03 + -3.9983624887e-02 + 4.3316996741e-02 + 9.4646425765e-02 + 9.3229043715e-02 + 4.7146921583e-02 + -1.1585908760e-02 + -2.2434659600e-01 + 1.2314859515e-01 + 6.4063417681e-02 + 3.0871876590e-02 + -4.7471250768e-03 + -4.4646051447e-02 + 2.2198461545e-02 + -7.6322346092e-02 + -5.3602049790e-02 + 3.5827560621e-02 + -1.4454667118e-02 + -1.2897531257e-01 + 1.9825541278e-01 + 1.0176954250e-01 + 2.0511480457e-02 + -2.2006191292e-02 + -1.1399473404e-01 + 1.8474059858e-02 + 8.0125322174e-02 + -1.8885014906e-02 + -4.3796506320e-02 + 2.5283410650e-02 + -5.4097916489e-02 + 8.8221124302e-02 + -7.5127935990e-02 + -8.3011814482e-02 + -3.6582736679e-02 + -2.9968666689e-03 + 7.7800186286e-02 + 1.8995512674e-01 + 4.3024898271e-02 + -6.1377874039e-02 + 2.1431067156e-01 + 4.2900259904e-02 + 8.1620377429e-02 + -2.3081614627e-01 + -1.0387164230e-01 + 9.4350776324e-02 + 9.3774532417e-03 + -2.3121345479e-02 + -5.5494823720e-02 + -1.4623219617e-01 + 7.0201428529e-03 + 6.8609184201e-02 + -4.7440182307e-02 + -6.6542247713e-02 + -9.3413811659e-02 + -1.1028518275e-01 + -2.2320100927e-02 + -3.6163295180e-02 + -3.3219134622e-02 + -1.3953272319e-01 + 8.4061843230e-02 + -6.6264871745e-02 + -9.1185600964e-02 + -1.3870811394e-01 + -1.7025363447e-02 + -5.1605882686e-02 + 6.2389211732e-02 + -8.4852609187e-02 + -4.0474166312e-02 + -1.4220799900e-02 + -1.4947314205e-01 + -3.2119767191e-02 + -7.7021725893e-04 + -7.8943426716e-02 + -4.4450892235e-02 + -1.1572091643e-01 + 6.5025399030e-02 + 3.1551692383e-02 + 2.5858638485e-02 + 8.0223703723e-02 + -2.1771768016e-02 + 6.6418890026e-02 + -6.9933489903e-02 + 6.0769555866e-02 + -4.8511109978e-02 + 6.0309555817e-03 + 6.5226094713e-02 + 2.3574452035e-02 + -1.8067977415e-02 + 8.6829379462e-03 + 1.3003022375e-01 + 1.6841231046e-02 + 9.6930385649e-02 + 5.0464011975e-02 + 2.5145281454e-02 + 1.3837843308e-03 + -8.3940257478e-02 + 8.8201084810e-02 + 6.6881340084e-03 + 7.4199904944e-02 + 8.2095122606e-04 + 8.2888488909e-02 + 4.5398621329e-03 + 9.3913269252e-02 + 7.1389390093e-02 + -2.5348818291e-03 + -6.4438179726e-02 + -4.4790804245e-02 + 8.6062970257e-02 + -9.5587035144e-02 + 6.4495682664e-02 + -7.5122465631e-02 + -8.5791821020e-02 + -4.2042114386e-02 + 2.7306826660e-02 + 1.2580101193e-01 + 6.3819208860e-02 + 3.6348487184e-02 + 1.4330509518e-01 + 7.8994208068e-02 + -5.0800296258e-02 + -5.0170660670e-02 + -3.4073155543e-02 + -1.7289330360e-02 + -1.4795794261e-02 + 1.5249236145e-01 + -1.0089793315e-01 + -8.3701635109e-02 + -7.7765265275e-02 + 2.0129793397e-01 + -1.1730098367e-01 + -3.6577610334e-02 + -8.8079955311e-02 + -3.8795075852e-02 + -5.8645093696e-03 + 1.0220882962e-01 + 1.5813314189e-01 + -2.3902115912e-02 + 1.6767432177e-01 + -5.6187859390e-02 + -9.5581183426e-03 + -6.2905311694e-02 + 2.8426337487e-02 + 1.1615202301e-01 + -3.1898855768e-02 + -4.1065310192e-02 + -3.1650444296e-02 + -3.2677132410e-02 + 4.3823623655e-03 + -3.4503947690e-02 + -6.6082375620e-03 + 2.6715992959e-03 + -1.2471289921e-01 + 7.6318478906e-02 + -3.0863072153e-02 + 8.9549606190e-03 + 7.1908085242e-02 + 1.3230132286e-02 + -1.2288766702e-02 + -6.0691263248e-02 + 1.3554526087e-01 + 3.5799129088e-02 + 1.7222068332e-05 + -8.8477950338e-02 + -4.5692211710e-02 + 1.3058103769e-01 + -3.4224991748e-02 + -1.3310133091e-03 + 1.5061051785e-01 + 5.9029826183e-02 + 3.9874989406e-02 + -1.3612913502e-01 + -3.0724906948e-02 + 1.1889210647e-02 + 1.8026073686e-02 + -2.1949388111e-03 + 7.1325830622e-02 + 1.6811765052e-02 + 1.1454491155e-01 + 9.5878747217e-04 + 8.0372086862e-03 + -8.0660560102e-02 + -1.0124344208e-01 + -3.0390056039e-02 + 2.4097117106e-01 + 2.8939136214e-02 + 4.2643555035e-02 + 1.1558631311e-01 + 6.8811389097e-02 + -2.1893120495e-02 + 3.9032070027e-02 + 5.3213031178e-02 + -9.6093295815e-02 + -6.9605177404e-02 + -4.5868294943e-02 + -7.4270745376e-02 + -9.2938451740e-02 + 4.6640658076e-02 + -2.1428954357e-02 + 1.7916539188e-02 + 5.5549365233e-02 + -6.2243570730e-02 + 2.6980275022e-02 + 6.2564791044e-02 + -1.0508987585e-02 + -5.8905817014e-03 + 6.6906561419e-02 + 6.8365709110e-02 + -1.2396001290e-01 + 2.4664155341e-02 + 1.6897010824e-01 + 5.6650585063e-03 + -1.0176727102e-01 + -5.0543278976e-03 + 7.0407363143e-02 + -7.0969470684e-02 + -1.0723947530e-01 + 4.1394612589e-02 + -5.9074326870e-02 + -7.0825642469e-03 + -8.3718907152e-02 + -1.0774514993e-01 + -6.9916535132e-03 + 2.7121598442e-02 + 3.9505832706e-02 + 6.1543559935e-03 + -1.3154913429e-01 + 3.8747406450e-02 + 5.1841199826e-02 + 5.1926468048e-02 + -2.8762743028e-02 + 4.8661384580e-02 + 1.3139469961e-02 + -1.9447380663e-02 + -3.5232321766e-02 + -1.6240485963e-02 + -6.1350612532e-02 + 4.0107426795e-02 + -1.3837209695e-02 + -2.8627583551e-03 + 9.8679010194e-02 + -1.7390315142e-01 + -6.1685618623e-02 + 1.3409210263e-01 + -1.7066715957e-01 + 6.1549173885e-02 + -9.3580606681e-02 + -1.1623980356e-02 + -9.9697673649e-03 + -3.4845144911e-02 + -3.3984822696e-02 + 1.4374323011e-01 + -1.0018277707e-01 + 2.3856851133e-02 + -1.2275718825e-01 + -6.1233574113e-02 + 2.2099016283e-03 + -3.9072147976e-02 + 5.5039314532e-02 + 4.4137409883e-02 + -7.8774603209e-02 + 1.5063480079e-01 + -4.6437565565e-02 + 1.2570812870e-02 + -1.1427810961e-02 + -9.1764985491e-02 + -5.8667537499e-02 + -7.5809776586e-02 + 5.7907903637e-03 + 7.0839494768e-02 + 8.3187179611e-02 + -6.3516612956e-02 + -5.9253843734e-02 + -2.1663972546e-02 + 5.0990563568e-02 + -5.5790942569e-02 + 7.5583607343e-02 + -8.2054175254e-02 + 6.8033108245e-03 + 7.5530246030e-02 + 2.8483883539e-02 + -4.9349095032e-02 + -6.9561707808e-02 + 1.3777477825e-02 + 4.9766241508e-02 + 1.5436839681e-01 + 6.0258530011e-02 + 5.0385868758e-02 + 6.3662287379e-02 + 1.3093073817e-01 + 2.1572188562e-01 + -6.7101525323e-02 + 9.9948890429e-02 + 1.0147921873e-01 + 1.4123416733e-01 + 1.7242176448e-01 + 1.6444799317e-02 + 3.8846732182e-03 + 2.2235986694e-02 + -5.4573041275e-02 + -6.7413341335e-02 + 2.4111415045e-02 + -8.0403588299e-02 + 9.9034942707e-03 + -1.2687219491e-01 + 1.6476482562e-02 + 6.1901263266e-02 + -1.5200206706e-01 + -1.7388595195e-02 + -7.4038041949e-02 + 1.8655787577e-02 + -8.3991846713e-02 + -7.3573496903e-02 + 2.0951409580e-02 + -3.0719298626e-02 + -1.8317228098e-02 + 1.3503594796e-01 + 3.6505269660e-02 + 3.2880981182e-02 + -1.0326427100e-02 + 2.5293281710e-02 + 3.9665164305e-02 + 1.0579661279e-01 + 5.4234671053e-02 + 1.2392696954e-02 + 4.4658972756e-02 + -4.9794748587e-02 + -1.6444645362e-01 + 7.1292964602e-04 + 3.8376356125e-02 + 3.9351565088e-02 + 7.7249675796e-02 + 9.0397524764e-02 + -9.8226826947e-02 + -1.3507937283e-01 + -1.7752472795e-02 + -2.1821906892e-02 + -9.6662749748e-03 + 5.2637895602e-02 + 7.8146305386e-02 + -1.9257647836e-01 + -3.7166693751e-02 + -1.1161813935e-01 + 4.8651333922e-02 + 3.8382274867e-02 + -1.1322499334e-02 + -2.6570758966e-01 + -6.7843605285e-02 + -1.1378667374e-01 + -5.4615872479e-02 + -1.0354343770e-01 + 3.0167343010e-02 + 3.5162766416e-02 + -1.1033986591e-02 + -7.6830888876e-02 + 6.2659698440e-02 + 1.0172878640e-01 + -4.1767863773e-02 + -6.4246061295e-03 + -1.2813669114e-02 + 5.4331961909e-02 + 1.9600545276e-02 + -8.1334789680e-02 + 1.2362977959e-01 + 2.2392593545e-02 + 7.1198321449e-02 + 3.1849823513e-02 + -6.7926792646e-02 + -8.4860343622e-03 + 5.6470333276e-02 + 4.7673953342e-02 + 3.4709889791e-02 + 8.6397708307e-03 + -7.4918903976e-02 + 5.3358675377e-02 + -2.1824610716e-02 + -8.8908745375e-02 + -6.9286903788e-02 + 6.5111917395e-02 + -7.8433613799e-02 + 3.2787033518e-02 + 4.1909405935e-02 + -1.3968564129e-02 + -6.4021754704e-03 + -4.3602659988e-03 + 3.5370414763e-02 + -9.0905288417e-02 + -2.4179905985e-02 + -9.2278314688e-02 + -5.9868548317e-02 + -6.2394669504e-02 + -7.9805499961e-02 + -1.3819562198e-01 + 3.3771248449e-02 + 1.7638425077e-01 + -1.0295142731e-01 + -1.7973334942e-01 + -8.1367791508e-02 + -1.8549148581e-02 + 5.1538721426e-02 + -9.0419403291e-02 + 1.7660687614e-02 + 1.6502769670e-01 + -4.0940753104e-03 + -2.9119588248e-02 + -2.2187449731e-02 + 4.3028058427e-02 + -2.3707061753e-02 + -4.4445326616e-03 + -3.1739939955e-03 + -8.4726657030e-02 + -4.1193020675e-02 + 5.7243547060e-03 + -1.0642320246e-01 + -1.5227982462e-01 + -5.2860595430e-02 + -7.2772668109e-02 + 2.0596095303e-02 + -7.1232471648e-02 + -3.2671736687e-02 + 3.0622339686e-02 + 9.9590105044e-02 + 9.0579539347e-02 + -7.7898955191e-03 + -5.5624150648e-02 + -1.6556996226e-02 + -5.7811439114e-02 + -9.5284679810e-02 + -3.1779794988e-02 + 7.5689048666e-02 + 1.3743932093e-01 + 1.7867275824e-01 + 8.2409891854e-02 + -1.1435970221e-01 + 5.6891867005e-04 + -1.2692896849e-02 + -3.9263652618e-05 + 9.3531906850e-02 + -2.3082442023e-02 + -1.0254763975e-02 + -1.6902741032e-02 + -5.6310084195e-02 + 1.5069615246e-01 + -3.0805342442e-02 + -1.8735237460e-02 + -3.9950116480e-02 + -1.4878846972e-01 + 2.7378514925e-02 + -3.6336751483e-02 + 4.7261570663e-02 + -3.8253959338e-02 + -6.9803039595e-02 + 4.7059690608e-03 + 7.9700342980e-02 + 9.3264101793e-02 + 2.2471864293e-02 + -7.8086560201e-02 + 7.4705711535e-02 + -3.2366576741e-02 + -1.1036497557e-01 + -2.9600584205e-04 + 1.3506025877e-01 + 1.2212121229e-01 + -7.9014269204e-02 + -9.7243528839e-02 + 6.7621358943e-02 + -5.6478767193e-02 + -1.5125736734e-01 + 2.5303479719e-02 + -2.2963712572e-02 + -7.3101312733e-02 + 9.3198751891e-02 + -1.4788750062e-01 + 1.7639505066e-02 + -1.1140468748e-01 + 7.7059958026e-03 + 1.8501113558e-01 + 1.2674464712e-01 + -1.0450998078e-01 + -1.5078296221e-02 + 5.9304963159e-02 + -3.6173295752e-02 + -8.6753760933e-03 + 6.8428083377e-02 + 8.1366558882e-02 + 1.5435460128e-02 + 1.1531523395e-01 + -9.2208547997e-02 + -1.2814481023e-01 + -1.6442645883e-01 + 4.9068796609e-03 + 1.4877274119e-01 + 5.2919395512e-02 + 2.0598168215e-02 + 2.5541887744e-02 + 7.7241162489e-02 + 3.6631353670e-02 + -1.3669831874e-01 + 8.5203588143e-02 + -1.6198912076e-02 + 1.8997361660e-01 + 2.1654786668e-02 + 7.3533735489e-02 + 6.3255349262e-02 + 1.4800332061e-01 + 2.5659341895e-02 + 1.9304405600e-01 + -5.5998765911e-03 + 7.8944824369e-02 + 2.0506769009e-03 + 8.6784994108e-02 + -1.1490374639e-01 + 1.5962240047e-01 + 2.0426160461e-02 + 5.3766112712e-02 + 1.8126836037e-01 + -8.3488684828e-02 + -5.0007627180e-02 + 9.1310676155e-02 + 8.6086884009e-02 + -8.0343259368e-02 + -1.7863653976e-02 + 4.6541859602e-02 + -1.9241862905e-01 + 2.3510980913e-03 + 1.2465740496e-02 + 1.2988239684e-01 + 2.0450404869e-02 + -1.7405030379e-04 + 3.9753487143e-02 + -9.1614479248e-02 + 1.2415565562e-01 + 2.1265979232e-01 + 9.9932803588e-03 + -1.0663383012e-01 + 1.1589654924e-01 + -4.3023114531e-02 + 1.7497406374e-02 + -3.6497811578e-02 + -1.7666944397e-01 + 1.0714285270e-02 + -9.6716938927e-03 + 1.6711153269e-02 + -9.7502269524e-02 + -2.1336068749e-02 + 1.9215887406e-02 + -5.0221695616e-02 + 2.1930898504e-01 + 7.6000634029e-02 + 1.0986899835e-03 + -8.3280327283e-02 + -6.4039866984e-02 + 1.1317318463e-01 + -2.4339040260e-02 + 1.1804038725e-02 + -4.1067738071e-02 + -5.4033135430e-02 + 1.0120672750e-01 + -1.1736420187e-01 + -1.7775565214e-02 + -2.7502615669e-02 + 1.5264627985e-01 + -1.0495922498e-01 + -1.2843157313e-01 + 9.7759385924e-02 + 7.0306863177e-02 + -7.8861246676e-02 + 1.0254937968e-01 + 1.2021340811e-01 + 6.8871023136e-02 + -3.4349230766e-03 + -2.7035181900e-02 + 6.8894445813e-02 + -7.1638133011e-02 + -1.0734545993e-03 + 3.5022557570e-02 + -3.0893663345e-02 + -7.8317874971e-03 + -1.1298687041e-01 + -1.5316346835e-02 + -6.4203268036e-02 + -1.4594248361e-01 + -7.0919824122e-02 + -1.1815693575e-01 + -8.0375301564e-02 + 5.8858231886e-02 + -5.9361367854e-02 + -2.5542540913e-02 + -9.5583228648e-02 + -2.8997460458e-02 + -3.5435041513e-02 + 6.0465739598e-02 + 6.5197504224e-02 + -7.1656941140e-02 + 1.1107843095e-01 + 1.3537361274e-01 + -2.1752366461e-02 + -2.6133915509e-02 + -9.7092649401e-02 + -1.5902307955e-01 + 8.4079286687e-02 + 9.0318024252e-02 + -6.1284263218e-02 + 1.2665118350e-01 + 9.8177229865e-02 + 1.5057703049e-01 + -1.3118206969e-01 + -4.6781869369e-03 + 8.1752332902e-02 + -1.0466329450e-01 + 4.5997258937e-02 + -2.8263593597e-03 + -1.7187628364e-02 + 1.1265099076e-01 + 6.4578202274e-03 + 1.3262936130e-01 + 7.7946370959e-02 + 1.4653038635e-01 + -1.8335313029e-02 + -1.9879870971e-01 + -9.5390046881e-02 + 3.9608296188e-02 + 5.8973989550e-03 + 3.6506947141e-02 + 7.6431834916e-02 + -9.3061833545e-02 + 8.2398147105e-02 + 5.8456057575e-02 + 1.5993042812e-02 + -4.9806981281e-02 + 3.2108019323e-02 + 3.5898627181e-02 + 1.7482546762e-01 + 1.4661248155e-03 + -1.4537916727e-01 + -1.2475849834e-01 + 1.6104216772e-02 + 1.2973971433e-02 + -8.5963875088e-02 + -3.8509788523e-02 + 9.4593792522e-03 + 4.6952231221e-02 + 7.3210688186e-02 + 5.0319709100e-02 + 5.3889913908e-02 + -6.6478525976e-02 + 8.1595103035e-03 + -3.5760981056e-02 + 2.2079105173e-01 + 9.9222731582e-02 + 6.1149048811e-02 + 2.4878231056e-01 + -9.2667385367e-02 + 1.3214074360e-01 + 7.5670143305e-02 + -4.2471925706e-02 + 3.1288818981e-02 + -8.6929719175e-02 + -3.4815061891e-02 + -1.9602465949e-01 + -5.5752544028e-02 + -9.7751896791e-02 + 5.2460474229e-03 + -8.2476387825e-02 + -2.7800151839e-03 + -5.9313048007e-02 + 1.4767058017e-02 + 1.4116982719e-02 + -7.5950742888e-03 + -4.0190501778e-02 + -9.8596736104e-03 + -1.3505299552e-01 + 1.7290715951e-01 + -2.9978499429e-02 + 2.8108774733e-02 + 1.1023267497e-01 + -1.3286761998e-02 + -4.2591461145e-04 + 4.1273788863e-02 + 2.5174752625e-02 + 2.6214293688e-02 + -7.7805700489e-02 + 8.0645183011e-04 + -1.6062200088e-02 + 1.9020267698e-02 + 1.3501288621e-01 + 1.4339150324e-01 + 4.7067526232e-02 + -1.0732859718e-01 + -7.1941816394e-02 + 6.1740557383e-02 + 7.9568513741e-02 + 7.9604866281e-02 + -7.7902347877e-03 + -4.7825086030e-02 + 9.6488849631e-02 + -1.4443613815e-02 + -8.2764689525e-03 + -4.2203751125e-02 + 2.2595969010e-02 + 8.1408815046e-02 + 2.6476843467e-02 + -4.8035585099e-02 + -1.1953766508e-01 + -8.5681277578e-02 + 7.0658494485e-02 + -6.1345051294e-02 + 4.9584885484e-02 + 7.2100792953e-02 + 1.3183676000e-01 + 1.5873199769e-01 + -1.2830116516e-02 + -9.7785559654e-02 + -7.9584347045e-02 + 2.7530436908e-01 + 4.8473512795e-02 + -7.4577930708e-02 + 3.6453525972e-02 + 7.0371765950e-02 + 2.7492404699e-02 + -8.5562026060e-02 + -1.4362121689e-01 + 7.2423878230e-02 + -9.5439742953e-03 + 1.0518249551e-01 + 1.3281280130e-01 + 2.4965078758e-02 + -6.9583454722e-03 + -5.7620616337e-02 + -2.5032579951e-02 + -5.8532802322e-02 + -2.7866485680e-02 + 2.2465328987e-02 + -5.4168640734e-02 + 7.2153134830e-02 + -8.7677217493e-02 + 1.4690427266e-01 + 9.6959649033e-02 + -2.4935880001e-02 + -4.8722497616e-02 + -1.2308276579e-01 + -4.8430344027e-02 + 1.0681046141e-01 + 5.0511981279e-02 + 4.4309011228e-02 + 1.9078829588e-01 + 1.1403636014e-01 + 2.4485146349e-02 + -9.7331446870e-02 + 1.4899653872e-01 + -1.1660678669e-01 + -2.6917987925e-02 + -1.0872202446e-01 + -9.7026902340e-02 + -1.3619311173e-02 + -1.3778794182e-01 + -1.4661405279e-01 + 8.4309702599e-04 + -1.5466152953e-01 + -1.5330359158e-01 + -1.2193739715e-01 + 1.1058234031e-01 + -2.3322549105e-02 + 1.0006440921e-03 + -4.0486266887e-03 + 2.8694976400e-02 + 1.1538098012e-01 + -5.7522340149e-02 + -3.2211057654e-02 + 1.2928411786e-01 + -3.3299818798e-02 + 1.1553333281e-01 + 5.4364683700e-03 + -1.0858186952e-01 + -6.9518478903e-02 + 4.3435637329e-02 + 1.8693535891e-02 + 4.1736204535e-02 + 1.7145691640e-01 + 8.0381612586e-02 + 5.5348672527e-03 + -9.0985929300e-02 + -1.6969941099e-02 + 2.3185670657e-02 + 2.0704625016e-01 + 1.5088662344e-01 + -2.2386232853e-02 + 1.1979123152e-01 + 8.6538348777e-02 + 4.2356409169e-02 + -3.1745739647e-02 + 3.2302484189e-02 + 4.6379617605e-03 + -1.0453110746e-02 + 1.5625326627e-01 + 4.0804608122e-02 + -9.1063694119e-03 + 5.6798440513e-02 + -1.4755316851e-03 + 6.0674007597e-02 + -8.3756792498e-02 + -3.3692763281e-02 + 8.1109632214e-03 + -6.0544290961e-02 + -1.2390683179e-01 + 9.3148893868e-02 + 1.3866221789e-01 + -1.2195473560e-01 + -5.9514671282e-02 + -9.7757443566e-02 + -3.1000000000e-01 + -2.6066666667e-01 + -2.1133333333e-01 + -1.6200000000e-01 + -1.1266666667e-01 + -6.3333333333e-02 + -1.4000000000e-02 + 3.5333333333e-02 + 8.4666666667e-02 + 1.3400000000e-01 + 1.8333333333e-01 + 2.3266666667e-01 + 2.8200000000e-01 + 3.3133333333e-01 + 3.8066666667e-01 + 4.3000000000e-01 + 5.5000000000e-01 + 5.5952380952e-01 + 5.6904761905e-01 + 5.7857142857e-01 + 5.8809523810e-01 + 5.9761904762e-01 + 6.0714285714e-01 + 6.1666666667e-01 + 6.2619047619e-01 + 6.3571428571e-01 + 6.4523809524e-01 + 6.5476190476e-01 + 6.6428571429e-01 + 6.7380952381e-01 + 6.8333333333e-01 + 6.9285714286e-01 + 7.0238095238e-01 + 7.1190476190e-01 + 7.2142857143e-01 + 7.3095238095e-01 + 7.4047619048e-01 + 7.5000000000e-01 + 7.5952380952e-01 + 7.6904761905e-01 + 7.7857142857e-01 + 7.8809523810e-01 + 7.9761904762e-01 + 8.0714285714e-01 + 8.1666666667e-01 + 8.2619047619e-01 + 8.3571428571e-01 + 8.4523809524e-01 + 8.5476190476e-01 + 8.6428571429e-01 + 8.7380952381e-01 + 8.8333333333e-01 + 8.9285714286e-01 + 9.0238095238e-01 + 9.1190476190e-01 + 9.2142857143e-01 + 9.3095238095e-01 + 9.4047619048e-01 + 9.5000000000e-01 + 9.5952380952e-01 + 9.6904761905e-01 + 9.7857142857e-01 + 9.8809523810e-01 + 9.9761904762e-01 + 1.0071428571e+00 + 1.0166666667e+00 + 1.0261904762e+00 + 1.0357142857e+00 + 1.0452380952e+00 + 1.0547619048e+00 + 1.0642857143e+00 + 1.0738095238e+00 + 1.0833333333e+00 + 1.0928571429e+00 + 1.1023809524e+00 + 1.1119047619e+00 + 1.1214285714e+00 + 1.1309523810e+00 + 1.1404761905e+00 + 1.1500000000e+00 + 1.1595238095e+00 + 1.1690476190e+00 + 1.1785714286e+00 + 1.1880952381e+00 + 1.1976190476e+00 + 1.2071428571e+00 + 1.2166666667e+00 + 1.2261904762e+00 + 1.2357142857e+00 + 1.2452380952e+00 + 1.2547619048e+00 + 1.2642857143e+00 + 1.2738095238e+00 + 1.2833333333e+00 + 1.2928571429e+00 + 1.3023809524e+00 + 1.3119047619e+00 + 1.3214285714e+00 + 1.3309523810e+00 + 1.3404761905e+00 + 1.3500000000e+00 diff --git a/tests_pytest/fixtures/nep_spin3/nep4_spin3_o3c3_uniform.nep b/tests_pytest/fixtures/nep_spin3/nep4_spin3_o3c3_uniform.nep new file mode 100644 index 000000000..2c2656fe9 --- /dev/null +++ b/tests_pytest/fixtures/nep_spin3/nep4_spin3_o3c3_uniform.nep @@ -0,0 +1,8024 @@ +nep4_spin3 2 Fe Ge +spin_mode 3 11 +spin_baseline -1.7000000000000001e-01 2.3000000000000001e-01 +spin_basis_size 8 +spin_l_max 2 +spin_compress 3 +spin_cutoff 6.0 +spin_order 3 +spin_soc 1 +spin_projection_size 36 +spin_scaler 1 +spin_dof_type Fe +spin_env_type Fe Ge +cutoff 6 5 128 128 +n_max 4 4 +basis_size 8 8 +l_max 4 2 0 +ANN 30 0 + 1.6388755319e-01 + 8.1905997734e-02 + -8.8654729207e-02 + 3.9982185385e-02 + 2.5000965942e-02 + -6.8556578742e-02 + 7.6540167574e-02 + -2.0341524191e-02 + -5.6478525649e-02 + -2.5282796343e-02 + 5.2824102302e-02 + -1.0711157176e-01 + 2.9862125168e-02 + -6.6000316125e-02 + -9.3131118623e-02 + 3.7528118131e-02 + 9.9083710213e-02 + 4.7842094200e-02 + -6.8540426616e-02 + 1.4940229730e-01 + 4.1193565854e-02 + -9.5208613628e-02 + -9.4031337398e-03 + -5.7690811541e-02 + 7.3152271904e-02 + 4.9512537480e-02 + -7.8541387881e-02 + 7.8663138523e-05 + -1.1322482852e-01 + 1.5770918823e-02 + -3.1677907144e-02 + -2.9154793843e-02 + 4.8039047570e-02 + -2.7980228430e-02 + -9.3704249676e-02 + 8.2193880432e-02 + 3.0221116617e-02 + 5.0088414015e-03 + -5.1792504108e-02 + 1.1706637388e-01 + 1.0751030694e-01 + -1.7655764277e-01 + 4.2380690663e-02 + 4.6061170476e-02 + 1.4900786500e-01 + -1.1783102412e-01 + 9.7554407824e-03 + 5.1533906630e-02 + -1.1407923736e-01 + -2.4421987411e-02 + -4.5002896075e-02 + 4.2898941203e-02 + -5.2615078381e-02 + 3.7934957832e-02 + 9.8565777948e-02 + 5.5030292887e-02 + -1.1745616317e-02 + 7.5008832393e-02 + -1.8567699559e-02 + 3.7395410005e-02 + -1.3202543452e-01 + 8.5630087708e-02 + 1.4808550206e-01 + -1.7694013772e-01 + 2.2817548819e-02 + 4.9757078553e-02 + -8.3388718980e-03 + -8.9542699762e-03 + -1.2287959719e-02 + -5.2254459963e-02 + 8.5289897107e-02 + 1.0012638982e-01 + -6.5358704685e-02 + 2.7808996626e-02 + -3.3525599343e-02 + 2.5570442853e-03 + 6.6458969399e-02 + -6.7637515871e-02 + 3.0641479657e-02 + -3.1366909819e-02 + 1.4793256336e-01 + 1.2848670437e-01 + -1.1717221794e-02 + 4.1595148349e-02 + -1.3170452299e-01 + -2.0212782351e-02 + 2.0805730548e-03 + 7.6966444943e-02 + 9.1133631115e-02 + 4.3488142460e-02 + -5.0991876340e-02 + 2.5975366174e-02 + 2.0519158717e-02 + -8.1529599630e-02 + 1.9781995814e-02 + -1.2434043693e-01 + 1.2450036161e-01 + -2.2525746265e-02 + -3.4469302374e-02 + 4.4438673381e-02 + -4.0562830568e-02 + 9.1514076617e-02 + -9.3992594491e-02 + 7.4053845968e-02 + -1.2492817043e-01 + 2.5422887302e-02 + -4.5317432246e-03 + -3.8194218802e-02 + -2.6644802030e-02 + -2.1486844556e-02 + 6.0544258923e-02 + -1.6868741638e-01 + 5.6364063883e-02 + -1.2796161731e-02 + -1.2653035364e-01 + 9.7602451109e-02 + 2.8165569895e-02 + 2.0001134044e-02 + -2.6862880626e-02 + 1.8276750113e-02 + -8.7569947392e-02 + 3.6078418944e-02 + 8.5017759130e-03 + 6.1059601632e-02 + -9.9729582904e-02 + 5.6587816990e-02 + 2.4570178611e-02 + 3.7900173073e-02 + 2.2872010228e-02 + -1.5231311203e-02 + -4.8718694411e-02 + 8.1248232426e-02 + -9.5571134031e-02 + -1.6039794175e-01 + -1.1628358147e-01 + 6.0142761336e-02 + 1.6214110841e-02 + 8.9149988601e-02 + -1.0663647173e-01 + 6.5035894016e-02 + 9.4737059422e-02 + 6.5555843172e-03 + 7.9187557202e-02 + 5.0181935754e-02 + -7.3339349508e-03 + -9.9264453387e-04 + -1.2172857460e-01 + -1.0669859007e-02 + 3.6915167738e-02 + 5.6218910973e-02 + -4.4847047186e-02 + -1.6583380210e-02 + -6.8264969379e-02 + 3.5248594893e-02 + -1.1200801491e-02 + 4.0322877863e-02 + 9.3602349823e-02 + 1.2156970891e-01 + -6.4283681017e-02 + 7.4664440491e-03 + 1.1662055416e-01 + 3.8863979620e-02 + 3.0329318738e-02 + -1.1945354993e-01 + 8.1466136977e-02 + 1.1849684530e-01 + 7.4780891700e-02 + -1.1750497308e-01 + -5.3073828810e-02 + -2.3698248499e-02 + 4.3139947366e-02 + 4.0555392936e-03 + 9.1377894669e-02 + -1.9864208419e-02 + -4.3717367416e-04 + -4.2442916788e-02 + 4.1397902380e-02 + 1.8023038296e-01 + 1.9673207945e-04 + 9.0870712844e-02 + 4.9454032336e-03 + -1.3827445494e-01 + 1.7740789007e-01 + -6.2752552808e-02 + 1.1793870829e-01 + 3.4286355534e-02 + -1.0713445892e-01 + -5.9057856542e-02 + 1.2076354051e-01 + 8.6399534659e-03 + 9.7198945466e-02 + 4.1648472916e-02 + 4.7431285863e-02 + -3.0746321391e-02 + -7.1292523702e-02 + -2.9586366088e-03 + 1.2986395038e-01 + -6.2875040662e-02 + -7.9657091064e-02 + 4.1199275780e-02 + 4.4305587255e-02 + 4.3205230781e-02 + 8.0013740897e-04 + -1.2285979914e-01 + -2.6038306499e-03 + -3.8802163592e-02 + 8.6347127854e-02 + -1.9089263312e-02 + 9.2725537506e-02 + 8.9903575017e-02 + -1.7681404891e-01 + 1.1852819642e-01 + 5.1100579174e-02 + 1.9149145372e-02 + 8.1368584016e-02 + -8.5176103967e-02 + -8.5596168169e-03 + -1.5014647916e-02 + -5.0270265970e-03 + 3.7391260263e-02 + -1.4897341265e-01 + -6.7972208811e-02 + 3.6343529945e-02 + -1.3014053688e-01 + -1.6165023855e-02 + -4.9278841878e-02 + -2.5086829790e-02 + 1.0033604632e-01 + 1.3614218906e-01 + 1.9392377735e-02 + -8.7880821828e-02 + -1.2141980157e-02 + -1.0346871700e-01 + -1.0469627903e-01 + -1.6400206877e-02 + 6.1260936951e-02 + 1.2213751014e-01 + 9.8738486183e-02 + 1.3837692877e-01 + 9.3505441197e-02 + 8.9867015606e-02 + 5.1797240857e-02 + 1.1700469200e-02 + 2.3750781048e-02 + -1.0575360812e-02 + 2.6226858018e-02 + -4.2691727452e-02 + -6.5506251172e-02 + 6.6585416880e-02 + -1.6909451164e-01 + 8.3954543387e-02 + -5.9996111110e-02 + 5.4832405434e-02 + 1.1406010270e-01 + -9.6286789553e-02 + -4.6044928585e-02 + -1.1708111563e-01 + 1.6654135571e-01 + 1.3549252643e-02 + -2.3964406144e-03 + 6.2922959997e-03 + -3.6190102217e-02 + -1.7904538302e-03 + -4.0204226413e-02 + 4.3771528320e-02 + -1.4258539855e-01 + 1.5536979973e-02 + -5.8496346040e-02 + 3.4523777928e-02 + -7.4499370126e-03 + -1.1113970758e-01 + -4.5254394111e-02 + 9.2954191037e-02 + -5.5118484925e-03 + -1.3916444068e-01 + 1.4720457704e-01 + 2.3809241106e-03 + 9.6294998570e-02 + 5.1137095816e-02 + 6.3370281308e-02 + 8.9425369330e-02 + 7.2430925433e-02 + 3.2837757346e-03 + 1.3769871909e-01 + 7.2122956063e-03 + 1.2546757764e-01 + -1.7858155018e-02 + -8.4920796668e-02 + 8.1808855950e-02 + 1.4041788989e-02 + 2.1143091367e-02 + -6.9797363132e-03 + -2.2056503482e-02 + 9.2771177157e-02 + -6.2532748636e-02 + 4.2701375379e-02 + -1.0026753500e-02 + -1.7972038898e-01 + 6.7525459324e-02 + -7.7972805000e-03 + -2.3513068255e-02 + -8.3928812006e-04 + 1.1007758312e-01 + 5.1460383734e-02 + 1.7089587127e-02 + 2.8518482995e-02 + -1.5088040400e-01 + -5.1032124800e-02 + 5.4515610087e-02 + 9.1655705953e-04 + 1.2114691242e-01 + 1.7760051882e-03 + 1.3565520237e-01 + 2.8988400008e-02 + -2.6782721045e-02 + -3.6980264382e-03 + -1.2031269642e-01 + 7.8554884806e-03 + -3.9983624887e-02 + 1.0979688642e-02 + 9.4646425765e-02 + 9.3229043715e-02 + 4.7146921583e-02 + 2.2906809854e-02 + -2.2434659600e-01 + 1.2314859515e-01 + 6.4063417681e-02 + 3.8851551037e-02 + -4.7471250768e-03 + -4.4646051447e-02 + 2.2198461545e-02 + 1.1463465068e-01 + -5.3602049790e-02 + 3.5827560621e-02 + -1.4454667118e-02 + -5.9712065232e-02 + 1.9825541278e-01 + 1.0176954250e-01 + 2.0511480457e-02 + -1.0146853722e-01 + -1.1399473404e-01 + 1.8474059858e-02 + 8.0125322174e-02 + 1.4054529073e-01 + -4.3796506320e-02 + 2.5283410650e-02 + -5.4097916489e-02 + -3.7007049280e-02 + -7.5127935990e-02 + -8.3011814482e-02 + -3.6582736679e-02 + 1.7894949118e-03 + 7.7800186286e-02 + 1.8995512674e-01 + 4.3024898271e-02 + 2.1076226246e-02 + 2.1431067156e-01 + 4.2900259904e-02 + 8.1620377429e-02 + -5.8843811852e-03 + -1.0387164230e-01 + 9.4350776324e-02 + 9.3774532417e-03 + 4.2583900102e-03 + 6.0405708924e-02 + -1.2823975315e-01 + 2.6638946176e-02 + 4.7170837023e-02 + -6.5525991192e-02 + 5.1243807459e-02 + 7.7328560452e-02 + -1.5160176736e-02 + 1.7727793410e-01 + -9.1750196830e-02 + -1.3373145597e-02 + -1.3981316086e-02 + 4.3682472630e-02 + 3.2475153044e-02 + 1.7528601410e-02 + -6.5318557158e-02 + -1.2531263236e-01 + 1.6850942572e-01 + 8.0795625159e-02 + -1.8795984546e-02 + 4.1599413877e-02 + -7.7997843328e-02 + 3.8282747390e-02 + 5.0506433768e-02 + -2.7693606006e-02 + -4.5782730121e-02 + 1.4684948235e-01 + -5.3043398185e-04 + 1.3307777223e-01 + -2.9695306778e-03 + 1.8123151397e-02 + -4.5748678351e-02 + 4.4167573145e-02 + -5.5192704329e-02 + 8.8006496957e-02 + -1.1015353729e-01 + 2.0140348406e-03 + 3.9532098158e-02 + 5.9492203428e-02 + -1.4940052899e-01 + 9.7823274028e-02 + 7.8856837672e-02 + 9.3093756640e-02 + -3.4692388545e-02 + 5.2216080634e-02 + -1.0142194667e-02 + 3.5999123279e-03 + -6.3412984947e-02 + 1.2705448138e-01 + -9.0030341795e-02 + -9.1185600964e-02 + -1.3870811394e-01 + 1.4737630558e-01 + -5.1605882686e-02 + 6.2389211732e-02 + -8.4852609187e-02 + -3.2562449947e-03 + -1.4220799900e-02 + -1.4947314205e-01 + -3.2119767191e-02 + 2.1314281025e-02 + -7.8943426716e-02 + -4.4450892235e-02 + -1.1572091643e-01 + -3.5391590118e-02 + 3.1551692383e-02 + 2.5858638485e-02 + 8.0223703723e-02 + -1.3142250457e-01 + 6.6418890026e-02 + -6.9933489903e-02 + 6.0769555866e-02 + -1.0568645039e-01 + 6.0309555817e-03 + 6.5226094713e-02 + 2.3574452035e-02 + 1.5633158286e-02 + 8.6829379462e-03 + 1.3003022375e-01 + 1.6841231046e-02 + -1.1888562698e-02 + 5.0464011975e-02 + 2.5145281454e-02 + 1.3837843308e-03 + -1.3612597132e-01 + 8.8201084810e-02 + 6.6881340084e-03 + 7.4199904944e-02 + -1.5431717545e-02 + 8.2888488909e-02 + 4.5398621329e-03 + 9.3913269252e-02 + -4.6363701984e-03 + -2.5348818291e-03 + -6.4438179726e-02 + -4.4790804245e-02 + -3.0829479867e-02 + -9.5587035144e-02 + 6.4495682664e-02 + -7.5122465631e-02 + -1.4694380262e-01 + -4.2042114386e-02 + 2.7306826660e-02 + 1.2580101193e-01 + 6.8813740059e-03 + 3.6348487184e-02 + 1.4330509518e-01 + 7.8994208068e-02 + -6.1748566923e-02 + -5.0170660670e-02 + -3.4073155543e-02 + -1.7289330360e-02 + 2.1550373321e-01 + 1.5249236145e-01 + -1.0089793315e-01 + -8.3701635109e-02 + 8.1380348623e-02 + 2.0129793397e-01 + -1.1730098367e-01 + -3.6577610334e-02 + -6.0920912267e-02 + -1.0362525339e-02 + -1.0401333752e-01 + -6.5231342758e-02 + 3.7860975185e-02 + -1.4615254185e-01 + 6.1451479261e-02 + 6.3599114359e-02 + 1.3691403600e-01 + 5.1778464427e-03 + 1.3632418568e-01 + 6.3940417908e-02 + 1.0476689619e-02 + 8.6455216896e-02 + -2.0141735880e-03 + -1.0175460852e-01 + 3.3201702335e-03 + 4.8466786077e-02 + -2.3763079992e-02 + 1.0618519758e-01 + 6.7135888546e-03 + -5.8021235527e-02 + 1.9559484796e-01 + 2.7986558216e-02 + 3.4540452538e-02 + 3.0577619942e-02 + 1.7470774043e-01 + -2.3772321780e-02 + -2.6054512981e-02 + 1.1039706759e-01 + -1.4963191325e-01 + -3.2627701730e-02 + 1.1599376113e-02 + 7.7130533340e-02 + 1.2664334896e-01 + -6.6823424260e-02 + 1.4904894407e-01 + -8.7978217872e-02 + 1.5059972976e-03 + 4.2843791948e-02 + -2.8067933029e-02 + -2.6562780287e-02 + 1.5945225262e-01 + -1.0433082025e-01 + -7.5831126232e-02 + -2.0132940743e-01 + 2.5207918508e-02 + -2.7489110707e-02 + -7.6127075894e-02 + -1.4124939634e-01 + -2.3323515342e-02 + -3.2677132410e-02 + 4.3823623655e-03 + -3.4503947690e-02 + 2.2768540906e-02 + 2.6715992959e-03 + -1.2471289921e-01 + 7.6318478906e-02 + -1.5680647762e-01 + 8.9549606190e-03 + 7.1908085242e-02 + 1.3230132286e-02 + 2.0334628781e-01 + -6.0691263248e-02 + 1.3554526087e-01 + 3.5799129088e-02 + -9.2595909823e-04 + -8.8477950338e-02 + -4.5692211710e-02 + 1.3058103769e-01 + 5.2665859814e-02 + -1.3310133091e-03 + 1.5061051785e-01 + 5.9029826183e-02 + -3.6036252385e-02 + -1.3612913502e-01 + -3.0724906948e-02 + 1.1889210647e-02 + 4.5221992716e-03 + -2.1949388111e-03 + 7.1325830622e-02 + 1.6811765052e-02 + -5.1420276775e-02 + 9.5878747217e-04 + 8.0372086862e-03 + -8.0660560102e-02 + -5.8592376649e-02 + -3.0390056039e-02 + 2.4097117106e-01 + 2.8939136214e-02 + -2.4818456965e-02 + 1.1558631311e-01 + 6.8811389097e-02 + -2.1893120495e-02 + 7.4583696674e-03 + 5.3213031178e-02 + -9.6093295815e-02 + -6.9605177404e-02 + 1.0836543100e-01 + -7.4270745376e-02 + -9.2938451740e-02 + 4.6640658076e-02 + 1.7255819502e-01 + 1.7916539188e-02 + 5.5549365233e-02 + -6.2243570730e-02 + 8.4597648076e-03 + 6.2564791044e-02 + -1.0508987585e-02 + -5.8905817014e-03 + 5.8171392802e-02 + 6.8365709110e-02 + -1.2396001290e-01 + 2.4664155341e-02 + 3.8252745949e-02 + 5.6650585063e-03 + -1.0176727102e-01 + -5.0543278976e-03 + 5.6910361705e-02 + -7.0969470684e-02 + -1.0723947530e-01 + -6.7900675426e-02 + -7.7019391712e-02 + -1.1269532177e-01 + 1.2821134615e-01 + -8.3419714935e-02 + 4.1206243846e-02 + 4.5902469968e-02 + 4.7264086529e-02 + -3.4066087545e-02 + 1.4691134879e-02 + -4.0448454289e-02 + 3.9240933878e-02 + 6.8262466420e-02 + -1.2848829426e-03 + 1.3359667692e-01 + 6.6631898281e-02 + 7.0558804880e-02 + -1.3695046306e-03 + -1.9747054647e-02 + 1.0965324765e-01 + -1.0967295723e-01 + -1.8384742601e-01 + -2.1325844292e-02 + -6.2942451630e-02 + 5.7706561131e-02 + -1.0314431292e-01 + 3.0450205694e-02 + 9.2344593768e-02 + -4.8236018639e-02 + 1.8159679642e-01 + -7.3071645492e-03 + 4.6221497863e-02 + 1.8100870839e-02 + -7.9365971690e-02 + -6.1014662757e-02 + -4.8135431349e-02 + 1.0106766698e-01 + 5.5679971628e-02 + 1.3909522971e-01 + -6.8496888429e-02 + -5.1948322671e-02 + 9.1893390178e-03 + 2.7999000068e-02 + -7.2411414903e-02 + 8.9816766903e-02 + 6.6481939635e-02 + 1.0545380110e-01 + -1.6079206191e-02 + 1.9012368704e-02 + -2.6415503524e-03 + -4.6872559697e-02 + 1.3139469961e-02 + -1.9447380663e-02 + -3.5232321766e-02 + -9.9879891747e-02 + -6.1350612532e-02 + 4.0107426795e-02 + -1.3837209695e-02 + 9.5205033759e-02 + 9.8679010194e-02 + -1.7390315142e-01 + -6.1685618623e-02 + -3.0463512001e-02 + -1.7066715957e-01 + 6.1549173885e-02 + -9.3580606681e-02 + -1.8849670145e-01 + -9.9697673649e-03 + -3.4845144911e-02 + -3.3984822696e-02 + -5.7990855039e-02 + -1.0018277707e-01 + 2.3856851133e-02 + -1.2275718825e-01 + -8.5945408395e-03 + 2.2099016283e-03 + -3.9072147976e-02 + 5.5039314532e-02 + -5.4501137957e-02 + -7.8774603209e-02 + 1.5063480079e-01 + -4.6437565565e-02 + -1.2461411231e-02 + -1.1427810961e-02 + -9.1764985491e-02 + -5.8667537499e-02 + 7.0714344881e-03 + 5.7907903637e-03 + 7.0839494768e-02 + 8.3187179611e-02 + -3.4718600343e-02 + -5.9253843734e-02 + -2.1663972546e-02 + 5.0990563568e-02 + 1.2613106430e-01 + 7.5583607343e-02 + -8.2054175254e-02 + 6.8033108245e-03 + 3.6290389195e-02 + 2.8483883539e-02 + -4.9349095032e-02 + -6.9561707808e-02 + 3.6400743274e-02 + 4.9766241508e-02 + 1.5436839681e-01 + 6.0258530011e-02 + -3.4612821160e-02 + 6.3662287379e-02 + 1.3093073817e-01 + 2.1572188562e-01 + -4.8481578422e-02 + 9.9948890429e-02 + 1.0147921873e-01 + 1.4123416733e-01 + 6.8555614531e-02 + 1.6444799317e-02 + 3.8846732182e-03 + 2.2235986694e-02 + 1.6922610788e-01 + -6.7413341335e-02 + 2.4111415045e-02 + 6.8499997291e-02 + 1.3840045016e-01 + 6.5742634362e-02 + -5.7447363895e-02 + -8.4311369110e-03 + -1.1249661782e-01 + -1.0134521050e-01 + 1.0976092918e-02 + 2.4449218158e-02 + -3.7296571858e-02 + -1.8656719977e-01 + -5.9940483479e-02 + 1.7741465992e-02 + 1.0693560275e-01 + -4.6374074222e-02 + 1.7342345508e-01 + -7.0344721878e-03 + -8.3597698206e-02 + -3.1067114756e-02 + 5.4535987454e-02 + 3.4442878003e-03 + 4.8460807607e-02 + -6.3934386364e-02 + 1.5656635383e-01 + -3.9961742685e-02 + 7.6542613134e-02 + -1.3151878344e-01 + 4.9806367315e-02 + 4.2451351548e-02 + 5.3948059728e-02 + -3.3793256580e-02 + 8.0533104739e-02 + -8.8978589151e-02 + 6.3332835539e-03 + 8.3251224169e-02 + 1.5393851924e-01 + -5.1329026100e-02 + 4.6842981593e-02 + -1.1058990490e-02 + 1.2799007900e-01 + 2.6455472098e-02 + -8.9935180218e-02 + 1.0678618921e-02 + 2.0589189042e-01 + -1.0536598302e-01 + -1.6944880419e-01 + 7.5102792554e-03 + 1.4212340657e-02 + 2.0862797238e-02 + -4.2975614656e-02 + 6.8382923314e-02 + -1.0472160593e-01 + -1.3130049356e-02 + -3.0124562222e-02 + -1.2693643447e-02 + 8.4553874533e-02 + 3.2659550555e-02 + -1.3335236723e-01 + 7.2907460479e-02 + -2.4658634535e-02 + 5.1945628382e-02 + 1.0175858646e-02 + -5.1218538807e-02 + 2.9335271944e-03 + 5.4318072340e-02 + 3.2069871568e-02 + -8.2844057373e-02 + -3.0588166882e-02 + -1.5879013396e-02 + 8.2191642565e-02 + -8.1591660966e-02 + -8.1320393012e-03 + 1.0469239370e-01 + -4.1250835912e-02 + -1.4477708179e-01 + 7.9285119732e-02 + -1.1622358897e-01 + -1.2649513797e-01 + 1.0056550958e-02 + 1.1641991639e-01 + 1.2807618630e-01 + 5.0370775442e-02 + 6.7509538360e-02 + -8.9549945222e-02 + -1.0833223519e-02 + 4.2285956331e-02 + -2.2631778034e-02 + -5.7521985416e-02 + -5.2443950124e-02 + -6.3986908743e-02 + -5.0971192355e-02 + -4.7952317623e-02 + -2.1322127780e-03 + 1.6181256414e-01 + -5.8405238398e-02 + 1.7289208485e-02 + 4.5417405507e-02 + 1.9111015055e-04 + -1.0820145032e-01 + 1.0428551078e-01 + 3.8388096634e-02 + -3.9691081162e-02 + -7.5806441986e-02 + -5.6873436714e-02 + -3.8360314460e-02 + 1.8459965222e-01 + 6.8641427812e-02 + 9.9767689019e-02 + -1.0324609952e-01 + -2.1010771358e-02 + 8.6598107004e-02 + 8.6885514274e-02 + 5.1444305836e-03 + -5.1655878636e-02 + -1.0857498189e-01 + -9.1325150527e-02 + -6.2713655062e-02 + -8.1545772199e-02 + 1.2159461328e-01 + -8.1261175773e-02 + -2.4600325525e-01 + 5.2479481562e-02 + 1.1183857479e-01 + -9.4843331836e-02 + 2.7192435511e-02 + 1.6807838163e-01 + -9.3666301496e-02 + -1.0111556909e-02 + -7.0851487051e-02 + 4.2397110127e-03 + -1.0138307927e-01 + 3.4510164681e-02 + -1.1115385630e-02 + -4.0816386953e-02 + -1.3193813925e-01 + -7.0606149989e-02 + -1.5460166790e-01 + -8.3466775096e-02 + 2.3600355305e-02 + -8.5279896039e-02 + -8.2567321226e-02 + 7.2154258549e-02 + 3.0946767099e-02 + -1.1324595739e-01 + 2.2006443294e-03 + 5.1195907238e-02 + 2.6829862590e-02 + 1.4980579997e-01 + 1.5956262704e-01 + 4.2182578568e-02 + 1.2945341451e-01 + -4.6252771872e-02 + 1.8472874217e-02 + -9.4220877954e-02 + 8.7579675862e-02 + 3.4657279563e-02 + 1.3905370790e-01 + -2.0255837706e-01 + -5.0527149853e-02 + 3.5885748185e-03 + 6.3620737283e-02 + -2.2221572173e-02 + -6.1896253072e-02 + -4.1578201922e-02 + -1.8884483014e-01 + -6.7149978115e-02 + 1.1786723384e-01 + -2.8295827964e-02 + -3.7367030258e-02 + -1.0509856947e-01 + -4.1350065265e-02 + 1.0221726822e-01 + 4.2365458477e-02 + -2.4526269401e-02 + -3.9196632789e-02 + -3.5029267467e-02 + 1.5906863482e-01 + 3.2978702255e-02 + 2.4641594979e-02 + 6.0289687443e-02 + -5.8111257350e-02 + -1.4049074186e-01 + 2.1987083687e-01 + 1.7274532392e-02 + -1.1400680991e-01 + -1.2419266543e-01 + 5.1638289756e-02 + 1.0691838189e-01 + -4.7904313395e-02 + 8.4523907194e-02 + -9.9762609288e-02 + 6.2765925448e-03 + -6.7468132676e-02 + 5.9411362908e-02 + 8.1908731443e-02 + 4.0282493558e-02 + -3.9127727754e-02 + 9.6729350153e-02 + 1.5661069328e-02 + -2.7546559246e-03 + 1.6836025035e-02 + 5.9385350921e-03 + -1.7439286069e-02 + 3.6538456056e-02 + -6.9366922161e-02 + 1.2954742770e-01 + -1.7550058348e-01 + -7.5149839331e-02 + 3.6713377991e-02 + 1.4383370517e-01 + 9.6469339547e-02 + 2.5299837763e-02 + 3.9114014583e-03 + -9.7461935943e-02 + -2.7550184183e-02 + -1.2822988290e-01 + -3.1547977571e-02 + 8.9286544795e-02 + -6.6824770849e-02 + 4.3084279774e-02 + -5.7306940537e-03 + 9.6791298998e-02 + -7.2772875249e-02 + 4.5300324075e-02 + 9.9232708674e-02 + -2.5714725691e-02 + -1.3260842242e-01 + 7.7175393480e-02 + -1.9435906745e-02 + -1.6983403817e-01 + 4.4898028520e-02 + 3.7466103443e-02 + 2.7709387711e-02 + -4.7297826356e-02 + -7.5336617481e-02 + 6.3258744451e-02 + -4.2930639728e-02 + -5.0994550759e-02 + 7.7454536041e-02 + -1.5841925640e-01 + -3.5469312023e-02 + 9.3902215013e-02 + -4.1437255527e-02 + 2.5734168207e-02 + -1.2428862821e-01 + 9.3511843132e-02 + -1.4119192200e-01 + 3.4803492121e-02 + 5.6912306613e-02 + -4.1871781467e-02 + -6.9981503966e-02 + -7.5574177974e-02 + 1.1191073427e-01 + 4.4958619866e-02 + 2.3874168357e-03 + 9.4490030254e-02 + -4.6144221048e-03 + -1.2686066538e-01 + 4.6579164008e-02 + -6.4827932724e-02 + -1.0462548634e-01 + -1.2219544221e-02 + -1.8236720177e-01 + -1.3064034874e-01 + 2.0820186203e-02 + 9.0998611260e-02 + -5.6490902153e-02 + 9.6537250048e-02 + 3.1406902883e-02 + 1.1556677509e-02 + 7.4574506207e-03 + -5.3984513300e-02 + 2.8588644364e-02 + -1.0514841954e-01 + 6.2292427924e-02 + 9.4636752796e-02 + 3.0081911916e-03 + -2.6074495829e-02 + 1.6837396715e-02 + -1.0556688309e-01 + 5.2754185219e-02 + 5.0638346365e-02 + -3.7388754840e-02 + -9.4944230935e-03 + 1.6514146279e-01 + -4.6645712614e-02 + -1.2721570845e-02 + 6.5793964224e-02 + -1.0813753653e-02 + 1.3149166183e-01 + -7.7446350549e-02 + -1.2900277811e-01 + -5.7056260527e-02 + 1.8846138708e-01 + 6.4691375127e-02 + 3.8488246876e-02 + 3.5272163717e-02 + -9.8040075262e-02 + -3.6994423684e-02 + -8.0404654959e-02 + -1.6332226205e-02 + 1.1075875053e-01 + -1.7551811173e-01 + 3.3806690411e-02 + -1.9166630714e-02 + 1.5133811585e-02 + 1.2864907322e-01 + -5.6238890543e-04 + 4.7291248924e-02 + -1.4134856298e-02 + -3.0624587381e-02 + 1.2102962045e-01 + 1.0288193153e-02 + 5.5211631715e-02 + -2.7723940877e-03 + -5.0149075553e-02 + 2.2607558724e-02 + 8.7724993537e-02 + 1.0109486400e-01 + 1.0383653570e-01 + 3.6970559581e-02 + 1.8884893226e-02 + 7.6481111400e-03 + -8.9631603007e-02 + -1.9359456483e-02 + -4.0149222274e-02 + 2.9248685927e-02 + -1.6660768041e-01 + 8.6543601774e-02 + 6.0096069625e-02 + -1.5303398234e-02 + -7.8490880731e-02 + 7.0970753548e-03 + -6.6158660955e-02 + 5.9096865932e-02 + -1.0931616815e-01 + -7.1372048166e-03 + 1.6059305818e-01 + 5.6285659983e-02 + 3.0791822945e-02 + -8.3917069522e-02 + -8.8364322081e-02 + 2.1541244653e-01 + 5.7737435854e-02 + 6.6399606111e-02 + -6.6244026698e-02 + 6.4083595655e-02 + -4.9595100635e-02 + -6.8588660628e-02 + 1.2519187153e-01 + 9.0253267296e-02 + 3.0866275351e-02 + -9.2009422461e-02 + 3.3989531454e-02 + 1.0551622297e-01 + -4.5141965807e-02 + 7.7735214181e-02 + 1.1643933183e-01 + 1.3799805991e-01 + -4.0039190660e-02 + 7.4562062135e-02 + 8.6735035937e-02 + -4.1197080668e-02 + -7.3478918075e-02 + 5.7012395262e-02 + -2.4752798047e-02 + 1.2697128378e-01 + -2.8491576032e-02 + -2.8510264089e-02 + 1.3063182017e-01 + 4.5350908870e-02 + -1.0189779064e-01 + -1.5617609593e-01 + -5.8457688679e-02 + -9.6709911378e-02 + -8.0875917755e-02 + -1.4181400740e-01 + 5.5223312563e-03 + -5.4377265913e-02 + 1.4004434201e-01 + 1.8738967480e-02 + -1.7803124315e-01 + -1.6051707435e-03 + -7.8265785458e-02 + 4.0798689020e-02 + -5.2156472926e-02 + -2.2126223180e-02 + 4.6011537276e-02 + -5.6590231996e-02 + 2.5795501921e-02 + -3.3272936868e-03 + -1.1076056370e-01 + -1.1105518630e-02 + -2.5471883577e-02 + 1.1457041672e-01 + -1.3985705590e-03 + -5.3901586252e-02 + -7.5133248766e-02 + -1.2104935590e-01 + -5.7956667683e-02 + -1.6688479464e-01 + 9.3460654669e-02 + -5.9730431571e-02 + -1.0917420129e-01 + 1.4210720881e-01 + -1.5404366088e-02 + 6.1792050798e-02 + -4.1806987812e-02 + 1.6773335920e-02 + 9.3874480780e-02 + 1.3082445593e-02 + -6.8384504851e-02 + -8.9032724595e-03 + -1.6465384667e-02 + -5.9577717799e-02 + 2.5588055450e-02 + -1.7777970368e-02 + -1.7285456248e-03 + -7.0613231630e-02 + -2.6598428393e-02 + 1.0401147927e-02 + 6.0795478018e-02 + 4.4713561018e-02 + -2.2014641531e-02 + -3.2275693749e-04 + -2.6268478366e-02 + 1.9425051814e-02 + 6.9008767258e-02 + 1.8892630637e-02 + -1.0073323286e-01 + 1.4891351195e-01 + -4.4152004304e-02 + 8.6184167344e-02 + 4.4937580616e-03 + -1.4290312503e-01 + -2.1857987707e-01 + 4.0831363777e-02 + 5.2962731233e-02 + -3.1401602144e-02 + 3.3403572655e-02 + 1.4939428088e-02 + 1.9705351927e-02 + 5.5783365223e-03 + -3.9593855266e-03 + -3.4436135577e-02 + 4.9335781418e-03 + 8.8315429652e-03 + -3.7740155456e-02 + 4.6830611134e-02 + -1.4073657418e-01 + 7.8930750380e-02 + -1.9043014990e-02 + 3.8146078873e-02 + -1.3073351559e-02 + -1.4160338009e-01 + 1.4233461876e-02 + -2.9831879029e-02 + 1.2370047370e-03 + 5.1033063376e-02 + -2.4042048082e-02 + 4.0902194261e-02 + 6.2041492292e-02 + 6.2378542981e-02 + -4.6358203701e-02 + -9.2779223166e-02 + 1.4837407525e-02 + -8.7998055386e-03 + 6.6313441465e-02 + -3.8760432267e-02 + -2.5994647186e-03 + 2.0101125780e-02 + -3.5346233596e-03 + -8.2208945193e-02 + -1.4019840750e-01 + 5.8939995584e-02 + -1.8186354635e-01 + -1.0782338787e-01 + -9.3295911167e-03 + -2.8797859256e-02 + 9.1456504738e-02 + 7.1143414726e-02 + 1.7158532442e-01 + 6.9243296225e-02 + -4.3480393656e-02 + 1.0771133602e-01 + -6.3210807148e-02 + -4.1635974819e-02 + 2.2455474740e-02 + -5.1348550570e-02 + -3.8203020251e-02 + 1.6984658182e-02 + 6.6487539042e-02 + 5.1169792190e-02 + 2.4383129642e-02 + -1.4903732412e-01 + -1.4263399881e-01 + -4.1859816306e-02 + -4.9296860712e-02 + -4.2911800973e-02 + 2.8294418790e-02 + -9.6653809809e-03 + -5.4047790601e-02 + 1.3379017034e-01 + 1.3318779358e-01 + -2.1644114986e-03 + -2.8837476226e-02 + -5.6712776904e-02 + 1.0868702702e-02 + -4.6876733518e-02 + 2.4112072453e-02 + 3.6291555817e-02 + -9.0233590960e-02 + -4.3605689195e-02 + 1.9794105295e-02 + -7.8913275362e-02 + 1.3142184757e-01 + -2.0222398042e-02 + -2.0395705472e-02 + -3.8826270803e-02 + -3.5222917569e-02 + -1.0891092521e-01 + -1.4334304951e-01 + -2.7747278079e-02 + 3.8898417566e-02 + 8.5720105517e-02 + 6.5367486088e-04 + 1.8370793490e-02 + -9.0778640772e-02 + -9.0405282783e-02 + 6.6854025082e-03 + -1.0910513715e-01 + 2.3281207759e-02 + -1.3906950758e-01 + -1.9065363784e-02 + -1.0601922440e-01 + 2.7811121003e-02 + -2.1257600672e-02 + 8.9956859948e-03 + -1.3014987376e-01 + -7.9088792768e-02 + -8.5608985994e-02 + 1.2019383742e-01 + -2.1444153206e-02 + -6.3521995134e-02 + 6.8339470583e-02 + -8.4586492944e-03 + 1.1157383578e-01 + -2.9279135754e-02 + -4.4493149545e-03 + 1.0778677847e-01 + -2.1660924817e-02 + -6.2514583592e-02 + 5.8299880058e-02 + -1.4088978710e-02 + -4.1303045755e-02 + -1.1302039630e-01 + -1.2887765107e-01 + -1.0454517000e-02 + -6.3975152326e-02 + -9.4745430303e-02 + -4.0459693789e-02 + 4.0280075537e-03 + -9.5867474150e-02 + -8.6026649408e-02 + -7.8066091009e-02 + -9.6413947947e-02 + -7.6390820918e-02 + -1.0807877110e-01 + -4.3640158144e-02 + 2.2149434525e-03 + -1.4590169448e-02 + -8.1014386408e-02 + -7.1933325488e-02 + -2.3945859397e-02 + -3.4066392168e-02 + 4.7457069673e-02 + 3.6401630087e-02 + -1.0010065291e-01 + -9.5095255827e-03 + 5.3494860969e-02 + -2.3725859265e-02 + 5.2567973497e-03 + 6.1419703185e-02 + 7.2656845889e-03 + -3.8262613519e-02 + -4.6497276993e-02 + 8.5297922452e-02 + 2.5618047400e-02 + -7.4996008116e-02 + 1.3800747260e-02 + 9.1471257441e-02 + -4.0932790384e-02 + 1.3728303003e-01 + -7.2910432372e-02 + 5.2289397571e-02 + -1.1319788979e-01 + -1.8767419476e-02 + 9.8143808540e-02 + -4.3718812588e-02 + 3.2936904469e-02 + 1.8886966853e-02 + 5.4413497880e-02 + 1.2991885774e-02 + -4.6622274159e-02 + 1.3350830256e-01 + -4.7921484407e-02 + 3.3784167298e-02 + -9.0976936275e-03 + -6.4840747431e-02 + 8.9246072705e-02 + 5.0063295000e-02 + -6.7544869549e-02 + -2.5720802707e-03 + -9.3126379251e-02 + -4.2859604015e-02 + 3.3399827909e-02 + 1.9878266591e-01 + 1.0327909180e-01 + -1.0739928183e-01 + 3.7383215820e-02 + 2.0298021618e-02 + 1.9359165390e-01 + -4.4963151996e-02 + -7.6653519771e-03 + 1.1286790796e-01 + 1.0160203826e-02 + -7.2891149733e-02 + 1.2957736051e-01 + 1.4532137097e-02 + 4.4295962012e-02 + 4.2607898120e-02 + -8.6039600939e-02 + 1.9708395759e-01 + 8.9321071769e-02 + 4.2692257276e-03 + 1.8165153152e-02 + -2.4241658583e-02 + 2.6645914388e-02 + 1.1666113181e-01 + -1.3171298055e-02 + -3.6142515360e-02 + -1.3958640651e-01 + 9.8907721655e-02 + 3.9931520519e-02 + 1.2293868497e-02 + -2.4953018688e-02 + 1.2128810209e-01 + -5.5485701388e-02 + 1.3524324300e-02 + -2.6475382186e-02 + -7.9919008415e-02 + -2.3505825169e-02 + 2.7956241782e-02 + -4.2230044003e-03 + -8.0388126171e-02 + 3.8067529591e-03 + 9.3958356294e-02 + -2.6438984762e-04 + -3.8220308706e-02 + 1.5410722019e-03 + -9.0200121251e-03 + 1.8778971088e-02 + -1.9026585353e-01 + -1.1470922073e-02 + 1.4183077901e-01 + 1.9135192867e-02 + -1.3097967084e-01 + 5.3260766502e-02 + 6.4782607103e-03 + 4.2446824773e-02 + 3.1500607892e-02 + -3.1725968739e-02 + -3.6131031443e-02 + -2.0626016590e-02 + -5.9527234361e-02 + 4.8759048660e-02 + -1.2090279638e-01 + 3.5278146253e-02 + -3.4829974406e-02 + 1.0330843000e-01 + 8.2948350845e-02 + 7.0919862891e-02 + -6.3594892546e-02 + 1.3019341579e-01 + 5.1880705049e-03 + 1.5068457150e-01 + -7.0523529422e-02 + -6.1026861149e-02 + 8.5174501569e-02 + -1.6466517665e-02 + 5.1680820019e-02 + 5.5952753961e-02 + -5.0483646858e-03 + -9.5367512742e-02 + -9.2673120751e-02 + 7.0724095532e-02 + -6.8539446535e-02 + 6.7019499375e-02 + -1.1505414519e-01 + 4.2624256342e-02 + 5.2789395604e-02 + 5.4133525111e-02 + 1.5855173467e-02 + 6.9488463950e-02 + -9.6843649479e-02 + 1.0024283450e-01 + -7.2050586223e-02 + -3.1285480338e-03 + 1.7977431945e-01 + -4.9796768864e-02 + 4.6827875757e-02 + -7.0052649479e-03 + -1.3906458039e-02 + 1.3696746706e-02 + 6.5230362475e-02 + 7.1583023877e-02 + 4.8589942650e-02 + -1.6294267915e-01 + -9.6767222402e-02 + 5.3046075781e-02 + -7.8561235140e-02 + 4.4868237835e-02 + 7.6775842974e-02 + -4.0930881585e-02 + 8.3134871942e-02 + 1.3540006160e-02 + 1.5342860629e-01 + -1.4483497483e-02 + -3.0108766992e-02 + 7.2012550011e-02 + -8.8841475049e-02 + -6.5552183328e-03 + -2.1101146754e-01 + -6.2966533641e-02 + 5.3813566099e-02 + -2.7865772342e-02 + 3.5099251872e-02 + 9.2557479709e-02 + 2.8934303031e-02 + 1.6256768882e-01 + 7.6508831551e-02 + -1.5542539714e-01 + -1.3497363842e-02 + -1.3601132582e-01 + -1.3002728353e-01 + -3.5200632795e-02 + 1.5365483813e-01 + 5.5809302607e-02 + -5.6528114786e-03 + 2.1037908432e-02 + 2.6968129475e-03 + 6.0596186874e-02 + 6.6299756548e-04 + 7.5774953038e-04 + 1.2807694704e-02 + -5.3279865583e-02 + 1.1984921338e-03 + 1.7405807964e-02 + 1.3376709542e-01 + 2.3156896500e-02 + 1.0705372864e-01 + 1.0435543711e-02 + -5.5713908599e-02 + 1.9588146958e-02 + 5.1008191427e-02 + -9.4845177885e-02 + -9.5204893312e-02 + -1.0705411205e-01 + -1.8188496677e-02 + -1.4310288558e-01 + 5.6589154128e-02 + 1.1461571797e-02 + -2.4172741766e-02 + -9.8785466962e-03 + 1.7176244603e-01 + -6.2647827604e-02 + -1.4382586339e-01 + -7.3506196727e-02 + 4.6514517319e-02 + 8.2067077054e-02 + -5.6797249021e-02 + 8.5150610974e-02 + 2.7730914542e-02 + 2.2027126088e-02 + 1.0441025877e-01 + 2.2783427672e-02 + -1.8996630446e-01 + -1.2157815703e-02 + 9.8320551673e-02 + -1.7257482813e-01 + 3.2580460044e-02 + 5.1281404142e-02 + 4.3585758312e-04 + 1.0978903531e-01 + 3.8661659984e-02 + 2.1003763398e-02 + -1.0608111146e-01 + -8.6190886162e-02 + -4.4403599566e-02 + 1.2708558331e-01 + 5.5138058594e-02 + -1.3317023374e-01 + -7.1132551044e-03 + -5.5512205605e-02 + 1.3128285677e-01 + 3.9503433855e-02 + 7.7169512857e-03 + 1.6548060590e-02 + -2.3259520316e-02 + -6.6271605019e-02 + 1.3797967723e-02 + 5.7379626190e-02 + 8.4887348322e-02 + -3.6361481870e-02 + 1.4729542173e-02 + -5.4728706761e-02 + 1.4243144615e-02 + 2.2269239820e-02 + -3.4048779185e-02 + 2.0806244990e-02 + 1.4572390819e-01 + -7.2396290422e-02 + 2.8885444697e-03 + -4.9872598547e-02 + -1.3544818680e-01 + -4.3063785052e-03 + 5.0750226244e-02 + -1.3646713480e-01 + -1.4083350324e-02 + 1.4941751685e-02 + -6.5657330352e-02 + -6.1825477146e-02 + 1.5726887628e-02 + -8.2030226440e-02 + -3.1194801213e-02 + -8.8578682425e-02 + -1.6025619911e-01 + 5.7253692201e-02 + 1.1698447099e-01 + -1.1334850462e-01 + -2.4478848603e-02 + 1.0718655063e-01 + -1.1325834200e-01 + -6.7964748996e-02 + 1.8004638669e-02 + 1.7375058748e-02 + -4.1105081794e-02 + -1.1035137443e-01 + 1.0046594949e-02 + 1.2952704661e-02 + -6.6818450225e-02 + 1.9503470053e-02 + -6.6135198005e-02 + 1.3095074457e-02 + -1.5803428371e-01 + -1.3468862630e-01 + -6.8317305159e-02 + 6.8501905813e-02 + 5.4326191085e-02 + 6.0792834373e-02 + 3.3140713387e-02 + -1.8120853835e-02 + 6.9490921140e-02 + -1.0818901705e-01 + -1.4180100613e-01 + 6.3602671669e-02 + -9.5421950484e-03 + -1.3905147091e-02 + 1.5109156118e-01 + -8.8233995413e-02 + -6.7199911130e-02 + 4.4623656196e-02 + 1.3070407442e-03 + -2.1208708406e-02 + 2.6385044260e-02 + 1.5552274916e-01 + -1.4321695102e-01 + -7.5244028120e-02 + -8.5393203714e-02 + 3.9175721901e-02 + -2.1462956553e-02 + -9.3758294043e-02 + -2.3126412827e-02 + 3.0168011446e-02 + -5.8952224236e-02 + -1.0903480501e-02 + -8.0932017846e-02 + 3.2983735545e-02 + 6.4460428244e-02 + 2.3688507225e-01 + 8.5137414851e-02 + -2.8609327427e-02 + 5.7180283354e-02 + -1.0324934330e-01 + 1.7731065886e-01 + -1.0676326386e-02 + 6.7489264729e-02 + -1.7375556572e-02 + -3.5177875956e-02 + 5.6319137035e-02 + -1.5014488491e-01 + 3.0775520795e-03 + 6.2267018872e-02 + 9.2622476925e-02 + -6.4807773533e-02 + 1.4750532471e-02 + -1.9416843921e-01 + 1.6037044749e-02 + 7.6998681736e-02 + -1.6179453897e-01 + -8.2077603671e-02 + -7.7198887843e-03 + 4.0679237185e-02 + 6.8728194482e-02 + -1.3266887254e-01 + -8.5506641053e-02 + 3.1935251448e-03 + -2.3304398595e-02 + -4.5894986054e-02 + 6.7470115467e-03 + -1.0425290826e-01 + 1.0413670440e-01 + -2.7802831681e-02 + -1.4133403508e-01 + -2.8240117333e-02 + 1.7887992432e-02 + 9.2805619325e-03 + 6.8657765060e-02 + -3.3037095444e-02 + 1.6383071566e-02 + 8.2693585131e-03 + 4.4924627913e-02 + 1.1409742537e-02 + -7.0693694681e-02 + -4.7117227620e-02 + 4.9934731316e-02 + -2.4530041840e-02 + -1.0319811120e-01 + 1.4363706052e-01 + -1.6941808647e-01 + -7.0648693068e-02 + 5.8959560318e-02 + -5.9767004386e-02 + 4.1666257213e-02 + -2.6717143915e-02 + -8.5529675785e-03 + -2.9367117690e-02 + -1.4342270946e-01 + 2.6893018252e-02 + 1.9898579904e-02 + -5.4210632661e-02 + 7.3058812997e-03 + 3.4838964183e-02 + 8.7214057758e-03 + 9.3900460954e-02 + 4.1760818558e-02 + -1.1815116875e-01 + 6.8506888331e-02 + -6.3348530073e-03 + 1.3456910995e-01 + 8.6583080918e-03 + -1.0734451986e-02 + 2.3555817396e-02 + -2.8486227202e-02 + -4.4564269723e-02 + 3.3439660240e-02 + -9.8696106940e-02 + 4.9072736783e-03 + -2.5166626562e-02 + -7.0228334529e-02 + -5.5646556488e-02 + 1.2450097332e-02 + 1.0958800340e-01 + 1.3929735621e-01 + 2.6154736778e-02 + -1.0592645189e-01 + -9.6929963076e-03 + 4.1833990082e-02 + 8.1235483994e-02 + -1.4170499181e-01 + 1.0258504428e-02 + 5.8440106433e-02 + -2.7317422793e-02 + -2.8326927146e-02 + 2.1129834887e-02 + 9.9402341047e-02 + -6.9423885103e-02 + 5.8123561501e-02 + 1.0467454160e-01 + -1.3053286766e-01 + 3.1553898334e-02 + -5.5111801695e-02 + -5.4990645650e-02 + -2.0902181225e-02 + 1.1148132781e-01 + 7.7273445800e-02 + -7.0034817119e-02 + 3.0837196011e-02 + -8.0716088526e-03 + -2.3626385260e-01 + 2.7215525841e-02 + -1.4639447009e-01 + 1.9122786877e-01 + -2.3813566114e-02 + -1.6660701851e-01 + 1.4551548814e-01 + -9.4352768332e-02 + -1.3263812756e-02 + -7.6793710015e-02 + 1.1930678570e-01 + -1.2798918466e-01 + -6.9914421028e-02 + -8.0504704923e-02 + 2.6073458098e-02 + -2.8612089912e-02 + 1.8424351973e-01 + -5.3354297366e-02 + 1.8266648018e-01 + 9.2864293117e-02 + 3.9515348633e-02 + 1.7198467605e-04 + -1.5008719149e-02 + 1.1240979196e-01 + -6.9913389644e-02 + 6.4027417355e-02 + -5.8139176242e-02 + 4.4051153847e-02 + 1.0996385104e-01 + -4.6263160337e-05 + -5.9854203910e-03 + 7.3872505260e-02 + 8.6800736659e-02 + -1.5879741254e-01 + -5.2703350271e-02 + 6.2868294147e-02 + -1.6823214479e-01 + -2.3525538994e-03 + -9.8107557691e-02 + -1.2132464067e-01 + 3.0406216105e-02 + -1.5895770074e-01 + -8.2073190557e-02 + 1.0019132100e-01 + 2.3862772113e-02 + -2.5955783728e-03 + -1.2422027093e-01 + -1.0346614599e-02 + 1.0056182404e-01 + -9.3772601922e-02 + -2.5075508903e-02 + -3.4995865717e-02 + -1.0714144652e-01 + -4.5037442386e-02 + 4.6548766138e-02 + 2.8455158489e-02 + 4.6220271786e-02 + -1.3809632480e-01 + -3.3817523622e-02 + 7.6819805488e-02 + -5.9897276914e-03 + 9.4809468579e-02 + 9.9844249720e-03 + 9.6043373876e-02 + -1.2645137806e-01 + 1.1791943324e-01 + -6.3989316716e-02 + 4.4061932222e-03 + 3.4014415548e-02 + 1.2287286197e-01 + -7.4671090055e-02 + -6.4848433420e-03 + -3.9766076021e-02 + 5.6950027460e-02 + -8.5212483871e-02 + -1.4678504185e-02 + 1.2367139497e-02 + 7.7525631607e-02 + -2.5686430400e-02 + 3.8167856174e-02 + 9.8445626232e-02 + -1.1694977714e-01 + -3.8767381471e-02 + 8.5237058631e-02 + -9.5345518149e-02 + 5.8859550334e-02 + 7.9412830747e-02 + 2.4543803075e-02 + 5.6938376985e-02 + -1.4644287077e-01 + -1.1901726779e-01 + 2.6137781975e-02 + 2.0186223805e-02 + 9.9429461578e-02 + 8.5963108571e-02 + 1.2795799358e-01 + 6.8721511586e-03 + 8.5533909309e-02 + -7.6620077838e-02 + -4.6888552148e-02 + -3.7208114357e-02 + -1.0089636024e-02 + -2.6247315024e-02 + 5.8913939933e-02 + 2.1529654800e-02 + 1.0714088293e-01 + 1.1874185105e-01 + 3.9340868737e-02 + 1.1738578406e-01 + 4.1463192927e-02 + -4.6612730885e-02 + 6.6380463643e-02 + 2.7338616158e-02 + -9.8412758353e-02 + -8.8414624988e-02 + -8.2741770273e-02 + 3.0226137399e-02 + -1.3806294862e-01 + 6.5491927060e-03 + 6.1221854202e-02 + 1.4281952119e-02 + -1.2206119945e-02 + -5.2347037894e-02 + -2.9974062534e-02 + -3.4479960139e-02 + -4.6187819740e-02 + 6.6276781728e-02 + 5.7111809034e-03 + -3.7153521908e-02 + 1.5736353267e-01 + 2.6090362336e-02 + -1.7305554089e-01 + 4.0260518279e-02 + 9.5297420470e-02 + 5.2273117736e-02 + 1.4286507964e-01 + 3.3326457362e-02 + -4.0423443613e-02 + 6.7002963603e-02 + 5.6534878507e-02 + 9.9483719949e-02 + 8.6232013422e-02 + -9.2048538336e-02 + 2.5077882739e-02 + -7.0063272112e-02 + 3.2929701584e-02 + -1.3158866878e-01 + 8.9696605968e-02 + -4.4324714616e-02 + 1.2125117858e-02 + 1.5734206991e-01 + 7.5025912510e-02 + 6.7772127807e-02 + -1.1963129561e-01 + 7.6063107703e-02 + -7.1926204430e-02 + 7.3439611987e-02 + -9.0721315621e-02 + -1.0174270247e-01 + 3.1433278117e-02 + 2.7141298520e-02 + -1.1484991102e-01 + -6.0003637392e-02 + -1.2859771149e-02 + -1.0043573146e-01 + 9.4443290456e-02 + 1.5902842911e-02 + 1.2986648660e-01 + 9.8177962440e-03 + -7.1749955219e-02 + -3.3644397104e-02 + 1.4414292206e-02 + -1.6764840519e-02 + -3.6026652068e-03 + -7.4001655057e-02 + 1.2050231803e-01 + -3.2354988334e-02 + -8.9654009278e-02 + -2.2097351075e-01 + -7.2261337956e-02 + 6.6439026702e-02 + 2.2717052834e-02 + 5.5887626534e-02 + -1.5993252247e-02 + 2.3129369025e-02 + -9.1121874813e-02 + -1.5215408296e-01 + 1.5060812737e-02 + 7.7875239260e-02 + 1.3245034940e-01 + -1.1516256526e-01 + 1.5858873682e-01 + -5.2744706636e-02 + 1.3643110298e-02 + -3.2592203774e-02 + -3.7071097692e-02 + -3.5878957983e-02 + -1.8681557898e-01 + 7.0536362117e-02 + 1.5715802623e-01 + -5.2645896798e-02 + -3.3437431232e-02 + -2.7478049688e-02 + -1.1927837173e-01 + 6.8655682373e-02 + 1.1625158574e-02 + -3.8284065071e-02 + -9.2982882367e-02 + 5.5169224684e-02 + 1.5481491309e-01 + -5.5357755647e-02 + 8.3942423125e-03 + -9.3760211485e-02 + -7.7789550090e-02 + 2.1164844249e-02 + -1.7065740767e-01 + -1.1423626044e-02 + 1.0480830994e-01 + 4.4011732360e-02 + 3.7262238508e-02 + 8.4850026644e-02 + 5.0750112572e-02 + 7.9688689195e-03 + 9.3494663206e-02 + -1.0548679000e-01 + -1.0872653674e-01 + 1.0321552298e-01 + -8.0965583417e-02 + 8.4509060551e-02 + -1.7306027750e-02 + -2.4437201856e-02 + 1.4096499990e-01 + -4.0384581821e-02 + -2.2763670040e-02 + -2.3493692079e-02 + 1.8328309713e-02 + 4.6125655631e-02 + -1.5716912404e-01 + 9.2824562519e-03 + 7.0470842874e-02 + -2.3671742465e-02 + -3.5769298314e-02 + 5.8725315767e-02 + 6.3021657613e-02 + -5.3935428917e-02 + -1.8277194023e-02 + -7.6944920382e-02 + -9.1010576427e-02 + -1.0634867883e-01 + -3.9811675445e-02 + 7.4992572248e-02 + 6.7190338453e-02 + 7.9319647627e-02 + 2.4868997536e-02 + -1.0832663434e-01 + 5.7597135948e-02 + -6.0909726095e-02 + 2.0984059363e-02 + 3.2031529563e-02 + -7.8822331994e-02 + -1.5874174283e-02 + 2.3785237779e-03 + 1.4405798220e-02 + -1.0130865801e-01 + -9.0823230104e-02 + 4.9463414411e-02 + 7.3685577692e-02 + 5.2560591295e-03 + -2.0002014800e-01 + 1.0123930519e-01 + -9.2299123867e-03 + 8.7948443496e-03 + 1.0908587650e-01 + 6.0494974161e-02 + -6.7425796076e-02 + 6.4485261163e-02 + -6.0841839247e-02 + -1.9336442851e-01 + 1.4768881857e-01 + -1.0551154411e-01 + -5.7600092021e-02 + -4.0311445496e-02 + 9.7613781186e-02 + 2.9721030159e-02 + 4.9652421807e-02 + 4.9838540048e-02 + -7.2905613550e-02 + 1.5875151122e-01 + -3.3326136858e-02 + 2.3638291951e-02 + -4.3754752288e-02 + 2.0742259129e-02 + -1.1466743797e-01 + 5.5141754268e-02 + 1.1438321673e-01 + 1.6507979435e-01 + 1.6516116866e-02 + 7.4878403568e-03 + -9.8577706518e-02 + -1.9732624888e-01 + -4.6908598319e-02 + -2.2189936349e-02 + -5.6598940452e-02 + -3.7514312554e-02 + -2.7272353890e-03 + 1.8800875169e-02 + -5.3477774526e-02 + -6.1006658965e-02 + -2.9403215079e-02 + 4.8357329110e-02 + 6.9359607554e-02 + 1.1918776273e-03 + -7.1085202890e-02 + -1.0898370762e-01 + -1.2820694084e-01 + 2.1544608753e-03 + -1.6648084465e-01 + -1.0797751528e-01 + -1.1095386185e-01 + -6.6945670361e-02 + -1.8233162849e-02 + 9.2828173665e-02 + 9.3824179378e-02 + 2.3196832723e-02 + -3.0521122871e-02 + -3.1575879827e-02 + -4.0520966694e-02 + -8.3156483595e-02 + -4.9258210174e-03 + 6.9005803008e-02 + 3.1399424244e-02 + 9.1486323192e-02 + 2.3761628456e-02 + 1.7267312738e-02 + -3.2584342188e-02 + -7.0634131183e-02 + -5.8749629684e-02 + -1.2625265134e-01 + -3.8401188168e-02 + -1.0529255899e-01 + 5.3869622345e-02 + 4.6986603379e-02 + 1.3907354813e-01 + -5.7211087688e-02 + -1.0880749445e-02 + -9.7859601534e-02 + -8.8786081760e-02 + 1.1893860073e-01 + -2.1569464363e-02 + -1.1494969718e-02 + 6.3410674840e-02 + -7.5062952182e-02 + -2.1111296732e-03 + 2.7488129519e-01 + 1.1633599296e-02 + 1.5099659402e-02 + 2.5832257645e-01 + 3.6729061693e-03 + 2.2450222631e-02 + -7.8357277188e-02 + 1.3027341525e-01 + 3.8675649877e-02 + -5.7418638072e-03 + 1.2667056499e-01 + 5.1917316633e-02 + 1.0848500473e-01 + 5.7987486550e-02 + 1.6342753332e-02 + 7.3821061280e-02 + -5.1069069431e-02 + 3.3004386694e-02 + -2.6346033641e-02 + 6.7606762947e-02 + 7.5714569287e-02 + 2.5307588209e-02 + 9.5048980438e-02 + 9.2010534198e-02 + -1.2013625446e-02 + 3.3294649785e-02 + 1.7428531673e-02 + -2.1354389333e-02 + 5.5417335118e-03 + -8.1148768154e-02 + -1.1899647754e-01 + -4.8836241270e-02 + 7.5836090527e-02 + 1.0449275003e-02 + 2.6863245902e-02 + -7.6096768093e-02 + 1.0018928107e-01 + 6.1602886187e-02 + -1.1865517809e-02 + 1.1809853047e-01 + 3.0597132328e-02 + 7.0741326222e-02 + 1.0555376008e-02 + -3.4891060298e-02 + -4.9157890362e-02 + 1.2334150049e-01 + -3.9978720150e-02 + -1.2249903578e-02 + 1.2118322199e-01 + 1.5168929248e-02 + 3.5184182315e-02 + -4.4479718958e-02 + 1.7947857975e-01 + -7.5165053525e-02 + -1.0024581919e-01 + -1.0585775202e-01 + 7.5151865699e-03 + -1.8720135283e-02 + 1.5151455655e-01 + -1.3653197409e-01 + 1.9828585136e-02 + 1.3705125649e-01 + -6.6644975597e-04 + -6.4499883938e-02 + -7.9873574095e-02 + 8.3352280315e-02 + -1.0309566018e-01 + -3.4339690853e-02 + -3.2669214652e-03 + 3.7242691903e-02 + -7.7107305368e-02 + 2.7571465536e-02 + 1.0863863543e-02 + -5.4417973095e-02 + 4.5479489994e-02 + 7.6064813091e-03 + -3.8391162723e-02 + 5.9193030010e-02 + 5.6550899469e-02 + -4.1103592811e-02 + 5.9260441298e-02 + 4.7764312957e-02 + 8.1501084493e-03 + -8.2694043082e-02 + 6.9734140896e-02 + -1.5302298359e-01 + 1.1572174222e-02 + -1.0036972373e-02 + -6.5637236252e-03 + -2.6842306081e-01 + 8.8888869402e-02 + 1.8925113576e-01 + -7.9139244660e-02 + -7.9207447170e-03 + -3.0669437212e-03 + -1.4236041130e-01 + 3.2961909324e-03 + -4.0110706558e-02 + -3.6511793606e-02 + -4.6802679156e-02 + 1.5949423933e-01 + 6.4190866932e-02 + -2.1529664333e-03 + -5.8831815467e-02 + 3.1325559244e-02 + 7.4885307531e-02 + 1.0075171081e-01 + 9.4963642772e-02 + 1.7630239231e-01 + -6.4963959031e-02 + -4.8921833317e-02 + 1.9154187266e-02 + -2.0734788466e-02 + 2.9599537688e-02 + -2.1987727087e-02 + 5.5842475572e-02 + -3.9853149516e-02 + 5.1090840741e-02 + -1.3668800051e-01 + -5.0172036935e-02 + -4.3731881908e-02 + -6.8142900305e-02 + -9.0020615321e-02 + 5.0992747149e-02 + -7.8434798899e-02 + 1.9768175384e-02 + 5.3070789608e-02 + -2.4681723221e-02 + 7.2858683641e-02 + 1.2406287976e-01 + -8.4920309238e-02 + -2.1996432283e-03 + -3.0540201626e-02 + -4.3448926917e-02 + -3.1702661245e-02 + 8.6390991791e-02 + -9.7491636030e-02 + 1.3674404113e-02 + 3.4678805725e-04 + 9.9747157740e-03 + -1.3672612602e-01 + 3.5644933317e-02 + 1.0838386726e-02 + 8.9406735140e-02 + -2.9122697160e-02 + 7.3530125040e-02 + 9.6922042551e-02 + 6.9676332229e-03 + 1.0378623597e-01 + 1.4034043027e-02 + 1.2993165417e-01 + -9.2249645241e-02 + 1.5866445671e-02 + 2.7612067939e-02 + -1.0647578607e-01 + -6.5497448396e-02 + 5.3710300048e-02 + -1.3227431465e-01 + -6.8654396766e-02 + 9.8165618642e-02 + -1.1054945706e-01 + 5.9428347255e-02 + 1.9874840435e-02 + 1.6036991486e-02 + 1.2005234885e-02 + 1.2406023490e-01 + -2.6082863289e-02 + -1.1614219783e-01 + 2.2108784271e-02 + 8.0252802666e-02 + 1.4759326964e-01 + -5.2731897207e-02 + -6.9722255437e-03 + 4.8005840679e-02 + 1.6325960095e-02 + 2.3859299695e-02 + 1.4580046409e-02 + -2.5779269754e-02 + 4.6187737299e-02 + 8.4502666943e-03 + -1.1332305645e-01 + -6.4913391215e-02 + 5.5772232624e-02 + -5.9796385396e-02 + -9.3371809153e-02 + 3.6761330021e-02 + -2.8831819972e-02 + -4.5283886468e-02 + -2.4006077919e-02 + -4.2627703281e-03 + 7.6794631926e-02 + 1.3402191800e-01 + 7.3867097649e-02 + -2.2640588839e-02 + -7.2004173796e-02 + 5.2160209631e-03 + -4.2930863512e-02 + -7.7025465481e-02 + -3.4325603901e-03 + 1.4409228480e-01 + -1.4493393684e-01 + 5.0160944087e-02 + 3.1172109442e-02 + 1.0593310674e-01 + 4.6943619551e-02 + 4.0836874758e-02 + -2.1370108575e-02 + 3.1800822240e-03 + -1.8750481055e-01 + 1.0487584246e-01 + 2.8866295116e-02 + -1.0850194775e-01 + -2.4734236494e-02 + 9.2040359087e-02 + -6.2514118049e-02 + -3.9042702713e-02 + -2.7179247269e-02 + -8.0064868894e-02 + 6.8629717138e-02 + -1.1922567860e-01 + 4.1394612589e-02 + 6.9922512070e-02 + 1.5298509417e-02 + -1.1025860921e-01 + -8.7910982402e-02 + -1.0289486359e-01 + 6.7935189438e-02 + 1.0691754950e-02 + -7.6504806548e-02 + 6.2692252192e-02 + 7.3778617188e-02 + 3.1778523072e-02 + -2.6716644848e-02 + 8.6032416165e-02 + -1.5317678011e-01 + 1.5646455619e-01 + 3.8121874742e-02 + -1.1526718456e-01 + 1.2068108450e-01 + -5.4812546630e-02 + -2.5820914253e-02 + 9.9528692973e-02 + -1.1903928092e-01 + -7.8700042980e-02 + -2.5604253128e-02 + -6.0104343671e-03 + -7.4904307229e-03 + -9.9468717958e-02 + 1.1133973489e-01 + -8.7088342317e-02 + 4.8066328260e-02 + -1.9192298121e-02 + 6.7090212268e-02 + -1.2164446044e-01 + 2.4633222524e-02 + 2.7528255357e-02 + -4.4372692813e-02 + -5.6372184934e-02 + 7.1216237249e-02 + 6.9616144050e-02 + -2.6816831449e-02 + -1.0083139556e-01 + -1.5684640679e-01 + 7.8377976792e-02 + -1.8341180540e-03 + 1.6131014320e-01 + -6.8835093801e-02 + 4.1680361628e-02 + 1.8059020235e-02 + 2.9783819711e-02 + -9.7923432124e-02 + 4.2297420222e-02 + 1.1835820200e-01 + 1.9638876983e-02 + -5.4355098127e-02 + 2.3439385844e-02 + 4.0706950914e-02 + -1.5385813764e-01 + 1.9624425552e-01 + 3.6287160494e-02 + 1.1944482921e-01 + 5.7722302525e-02 + 1.9814747941e-02 + 2.2070195003e-02 + -6.1010685555e-02 + 2.5356888015e-01 + 6.8630693897e-02 + 1.1083915845e-01 + -6.2720324081e-02 + -6.5539886733e-02 + -2.3568555771e-02 + 1.1977681307e-02 + 5.5788198089e-02 + 7.0204789204e-02 + 9.3593644595e-03 + 3.4783574719e-02 + -1.0404985175e-01 + 1.7528013518e-01 + 1.4431439366e-02 + -3.1487495194e-02 + 8.7751370964e-02 + -8.1522909783e-02 + -6.3256867189e-03 + -2.2530974803e-02 + 9.7823295628e-02 + -8.0223260661e-02 + 5.5339297311e-02 + -1.8020172085e-02 + 1.8057034766e-01 + 1.8479411140e-01 + -6.8956269822e-02 + 1.2201888424e-02 + -2.4648761558e-02 + 5.0227031978e-02 + 1.1966262957e-01 + 7.6575352557e-02 + 2.3996827622e-02 + -1.7038319191e-01 + -1.9045590147e-02 + -9.5222448930e-02 + -1.9955784353e-02 + -5.7808233282e-02 + -1.9328778066e-02 + 3.1052326452e-02 + 4.9156719171e-02 + -4.9982751011e-02 + -3.8450662594e-02 + -4.3448019421e-02 + -3.6755410301e-02 + 1.5854447921e-01 + -2.4674936713e-02 + 1.0774071948e-01 + 4.9464338738e-02 + -6.4445902825e-03 + 1.0430728466e-01 + -3.0868728448e-02 + -2.7743578250e-02 + 7.1460496482e-02 + 7.0546220317e-02 + 7.6032915267e-02 + 7.9277062839e-02 + -8.0403588299e-02 + 6.6861878337e-02 + -4.1524617974e-02 + 1.3916421412e-02 + 2.3567186504e-02 + 8.3114074990e-02 + -1.7834329740e-02 + -2.5203413487e-02 + -8.3847291179e-02 + 3.5582101635e-02 + 3.3314518050e-02 + -2.1442193196e-01 + 7.5296819983e-02 + 4.3660668641e-04 + -7.3009403897e-02 + 5.5592788640e-02 + 1.4041995664e-01 + 7.5677285704e-02 + 1.6455604971e-02 + -4.2197954022e-02 + 6.1259140318e-02 + -1.6945548146e-02 + 6.7620911609e-02 + -1.1647732188e-02 + 6.4636717938e-02 + 1.1144545966e-01 + 1.4222050785e-01 + -1.5859844431e-02 + 4.9160921461e-02 + 7.7442912251e-02 + -7.4381620890e-02 + -1.7866461496e-02 + -5.2317794172e-02 + -3.1757981266e-02 + 1.0022266645e-02 + 2.9683454222e-02 + 1.6552389855e-02 + -4.8559489113e-02 + 2.6638247608e-02 + 4.6168875188e-02 + -4.0785627167e-02 + 1.7583707430e-01 + 8.0312723013e-02 + -1.2469603534e-01 + -7.5430696969e-04 + -1.3386024747e-02 + -1.8929543684e-01 + 1.4594161012e-01 + -1.1343243779e-01 + 2.0777799111e-02 + 1.4944088053e-01 + 8.9858208566e-03 + -2.7674468388e-02 + 3.7211242190e-02 + 1.3658581167e-01 + 2.6205580093e-02 + 1.4304281009e-01 + -6.4625624878e-02 + -1.3950140980e-02 + 1.0375787004e-01 + 9.1008624202e-03 + 2.8843347081e-02 + -8.6105816102e-02 + -8.0515564687e-02 + -5.4197660058e-02 + -1.3741104922e-01 + 3.8469089722e-02 + -4.2701332760e-02 + 7.4220895812e-03 + -4.5296822214e-02 + 1.6020863839e-02 + -4.2422212531e-02 + -6.2081440785e-02 + -3.5499620093e-02 + -7.1133878328e-02 + -3.2570531122e-02 + -5.4770879706e-02 + 6.3329691103e-02 + 6.0823661889e-02 + -4.6948603699e-02 + -3.0254853242e-02 + -1.8623463230e-01 + 8.0951549290e-03 + 4.9668261739e-02 + -5.0868576822e-02 + -1.3829470429e-01 + 4.9471286405e-02 + 9.6606291699e-03 + -3.7123946854e-02 + -1.1885100076e-01 + 8.9859673988e-02 + 1.3698009947e-01 + -3.8117340898e-03 + 1.0936758340e-01 + -7.0308444667e-02 + -8.6027187067e-02 + 2.4942947528e-02 + -1.0316527481e-01 + -1.1148804233e-01 + -1.1601851128e-02 + 5.3549795929e-02 + 4.3467046523e-02 + 6.9004471795e-02 + -6.6973107315e-02 + 1.0280305485e-01 + 8.1893510247e-02 + 1.5101604051e-01 + 8.7998422907e-02 + 6.6599132430e-02 + -3.0901376303e-02 + -6.4805106578e-02 + -1.3928552865e-01 + -1.6642023709e-01 + 5.3568227109e-02 + -6.7271738491e-03 + -8.8390523911e-02 + -4.2024167080e-02 + 4.2912008680e-03 + 1.2101695550e-01 + -2.6100295803e-02 + 5.3157170025e-02 + 3.0558057258e-02 + -4.9905529757e-02 + 9.3465040231e-02 + -2.7074402176e-02 + 6.0353197026e-02 + -1.6458965974e-02 + -7.0044862828e-02 + -4.5083450487e-02 + 5.0276617980e-02 + 1.2533289574e-01 + -4.7097612776e-03 + -7.5890349905e-02 + -1.8452284029e-02 + -4.1052360315e-02 + 2.6414755473e-02 + 2.5673333650e-02 + 4.0075818688e-02 + -1.5007735512e-02 + -8.3449229820e-02 + -1.5407162994e-01 + -6.8696279330e-03 + 1.1708698096e-01 + 2.4078835366e-02 + 4.0189680743e-02 + -9.4069549368e-02 + 7.7056401892e-03 + -1.6292857093e-01 + -5.6653214702e-02 + 1.5783409231e-01 + -6.0217813866e-02 + -1.0979661250e-01 + -5.0911877657e-03 + 8.0809066051e-02 + -9.8944277494e-02 + 5.2574185842e-02 + -6.1358254256e-02 + 7.1352773897e-02 + 1.3843286768e-01 + -7.1011939795e-03 + -3.1557353119e-02 + -4.2963123127e-02 + -4.1087323183e-02 + 3.7256854468e-02 + -1.2431542196e-02 + -2.1034297389e-02 + -2.3753281174e-03 + 2.1004565746e-02 + -6.6878114055e-02 + 1.7537832739e-01 + -1.7436877980e-01 + 6.9929079470e-02 + 7.2507912907e-03 + 5.1095941697e-02 + -5.6194370303e-03 + 9.3158114863e-03 + -6.2786005108e-02 + -1.0865354376e-01 + 3.9839702137e-02 + 1.4920580322e-01 + 7.4463694980e-02 + -7.4063666616e-02 + 1.1529792181e-01 + 2.7859324691e-01 + -3.8387845420e-02 + 3.1431231216e-02 + 9.9750079040e-02 + -7.9520571155e-02 + 3.8384455737e-02 + -7.0282535936e-02 + 8.4393750477e-05 + 5.3707272487e-02 + 2.2992334310e-02 + 3.9079735447e-02 + -1.1636306713e-01 + -9.5017518278e-02 + -9.5178840242e-02 + -1.8660430606e-01 + -4.5241197962e-02 + -1.1070020959e-01 + 4.8162191092e-02 + 6.0363001051e-02 + 7.5561946250e-02 + 4.6966895883e-02 + 2.2429521900e-02 + -1.5565658934e-02 + -6.9820586193e-03 + 1.3300158016e-01 + 7.8326382879e-02 + -1.9848281819e-02 + -2.2707838804e-02 + -5.7584243068e-04 + 1.1555348889e-01 + -6.8719059802e-03 + -3.3442935771e-02 + 7.8550382292e-02 + -6.1558653225e-02 + -1.1509930145e-01 + -4.6771296289e-02 + 1.4489476484e-01 + 2.5259373355e-02 + 8.2275515720e-02 + -2.7390944716e-02 + 5.7363989774e-02 + 1.4344084256e-01 + -4.2942746862e-02 + -6.6651514330e-02 + -6.0043372372e-02 + -5.0512307238e-02 + 5.9541947921e-02 + -1.2881765591e-02 + -3.5477948240e-02 + -3.1002879307e-02 + -6.9815168749e-02 + 3.5139583205e-02 + -5.1023916371e-02 + 9.6377847881e-02 + 2.2260375818e-02 + -5.8288857547e-02 + 4.0115559959e-02 + 8.3453817110e-02 + -1.0194028529e-01 + 8.8413067762e-02 + -7.3506696651e-02 + 5.7598795843e-02 + -5.8872918257e-02 + 7.0638115510e-03 + -2.1702232132e-02 + 7.5927280828e-02 + -1.6716398207e-02 + 1.0264785176e-01 + 3.1067633499e-02 + 5.4774106488e-02 + 6.0038694238e-02 + 8.8285403893e-02 + -6.0154091745e-02 + 1.0848992365e-02 + -1.2381487117e-01 + 8.2937301265e-02 + 5.2853659921e-03 + -9.9355055530e-02 + -8.3430138606e-03 + -1.1923622353e-01 + -1.7950996436e-01 + 4.8107721537e-02 + 5.3716095921e-03 + 1.0023769194e-01 + -8.2136260087e-02 + 6.0578355298e-02 + -5.0669672866e-02 + 2.2344217792e-01 + -1.5691771726e-02 + -1.0867656360e-01 + -1.0914385874e-02 + -1.1432040824e-02 + 1.5397641580e-01 + 9.6639676526e-02 + -1.0990341378e-03 + 5.6751010964e-02 + 3.2400656557e-02 + 9.6338886719e-02 + 1.0090446236e-01 + 2.9872791168e-02 + -4.4671433333e-02 + 8.4384063341e-02 + -8.4113090218e-02 + -4.2177157458e-02 + -3.0196735542e-02 + -7.6564126039e-02 + -5.6102745864e-02 + -8.4403654009e-02 + 5.1942117726e-03 + -4.9510040837e-02 + 6.2491401423e-02 + -1.0468659103e-02 + 9.3936682510e-02 + 3.9488586868e-03 + 3.5099755636e-02 + -7.2829673799e-02 + -2.0218839229e-02 + 1.0420051399e-01 + -6.3384143955e-02 + -1.8192052506e-01 + -1.1016512260e-01 + -1.0765140861e-01 + -5.2722788282e-02 + -1.9285884313e-01 + -3.7570691829e-02 + 2.0807241107e-01 + -9.8305149822e-02 + -1.1694344225e-01 + 1.5776554236e-01 + 1.3526341077e-03 + 1.3873748165e-01 + -9.8286522978e-02 + 5.7199211065e-02 + -1.3036837592e-01 + -1.4259077603e-01 + -5.6949111532e-02 + -1.4200851448e-02 + -6.8977903427e-02 + -7.2462566339e-02 + -6.3178035367e-02 + 1.7945166084e-01 + -9.7351743596e-02 + -6.8422796211e-02 + -9.2388473074e-03 + 1.3677528019e-02 + 6.0053417050e-02 + -5.1856193380e-02 + 1.0098985843e-01 + 3.6163241001e-02 + -1.4426975917e-02 + 9.6471701337e-02 + -1.0120592783e-02 + 1.1203962694e-01 + -6.0952848986e-02 + -7.9634348279e-02 + -5.2453497407e-02 + -2.7700066119e-02 + -8.1988327252e-02 + -7.2531101560e-02 + -5.0744517679e-02 + 1.0484172595e-02 + 2.9575601661e-02 + -2.8212513350e-02 + 9.1100121150e-02 + 2.1996647137e-02 + -9.3025864328e-04 + -6.2846610288e-02 + -2.6122957278e-02 + 4.0712358836e-02 + 6.8647451568e-02 + -3.4601925766e-02 + 1.7843695074e-02 + 7.7441219273e-02 + 1.2516831840e-02 + 7.0083889381e-02 + 7.6076899473e-02 + 9.2284105286e-03 + -1.0323402512e-01 + 1.6266567326e-01 + -1.0080315243e-01 + 8.9026193874e-02 + 1.0021880673e-01 + 5.7627170393e-02 + -9.7757162866e-02 + -8.9052621383e-03 + -5.2008678156e-02 + 3.4145256216e-02 + 7.8786120551e-02 + 9.2200451158e-02 + -1.1810074663e-01 + -9.8689590154e-02 + 4.0357580901e-02 + -9.3619698810e-02 + 1.1833206631e-01 + -2.9242080941e-02 + -2.2588653356e-02 + -1.4479294677e-02 + -1.7394485735e-02 + 1.0385729650e-01 + 1.2522825090e-02 + -7.2038915807e-02 + 3.0822335219e-02 + -4.8387845483e-02 + -6.9342513263e-02 + -4.6916625779e-02 + -8.2505121329e-02 + -1.2143110253e-02 + -3.4219628066e-02 + 2.7067045251e-02 + -1.0706191059e-01 + 4.3294613592e-02 + -1.0784541937e-01 + -6.3044808133e-02 + 6.3079758447e-02 + -3.1672468592e-02 + -1.4372614322e-01 + 2.2651695625e-02 + -9.9938016880e-02 + -3.8104393862e-02 + 4.3349149410e-02 + 1.2722650393e-01 + -2.8090887739e-03 + 2.5667236980e-02 + 2.6658940774e-02 + 2.1913894721e-02 + 1.7456843279e-02 + 1.6033126238e-01 + -8.1114174174e-02 + -6.6311824740e-02 + -5.6089893192e-02 + -7.2857680672e-02 + 1.7350452642e-01 + 8.3051612518e-02 + 4.3274148162e-02 + 1.5374435552e-01 + -6.2766715838e-02 + 2.6916532200e-02 + -5.6405549075e-02 + 8.2923684820e-02 + 8.6835609050e-02 + 3.8939364799e-02 + -4.0902519274e-03 + -6.0985088172e-02 + 7.9098507454e-02 + -4.9861323376e-02 + -8.3473998042e-02 + -7.1183172976e-02 + -7.8112070352e-03 + -1.4147819775e-01 + -1.7076486758e-02 + -1.4661414271e-01 + 5.1664388354e-02 + -4.8232934695e-02 + -4.9742125886e-02 + 3.8332180857e-02 + 9.9502728208e-02 + -6.5453079241e-02 + -2.1616151593e-01 + -3.6778350081e-02 + -3.9731224671e-02 + 7.3676781497e-02 + -6.7838505350e-02 + -9.3830944490e-02 + -9.6418103625e-02 + -2.6194671115e-02 + 2.6684754740e-02 + 6.8326859334e-02 + -8.4364799393e-02 + 9.6387400040e-02 + 1.5441183287e-02 + 9.5909184856e-03 + 1.5254411958e-01 + -1.0231996159e-01 + 6.1134254034e-02 + 1.0968317175e-02 + -1.5517743943e-01 + 7.7603698616e-03 + -2.6211612464e-02 + -2.5281308952e-02 + -1.6734435954e-01 + -5.4267147463e-02 + -5.2758532672e-02 + 1.9400234212e-01 + 1.6116174956e-01 + -8.4245352771e-02 + 4.9424492403e-02 + 9.7478347663e-02 + 1.6896412085e-01 + -3.3970399723e-02 + 1.1676959586e-01 + -2.5641411117e-02 + -7.4859523970e-02 + 1.9996755084e-02 + 2.1509735144e-02 + 8.0190703748e-02 + -4.5082547397e-03 + 2.1057754321e-01 + 1.8159418016e-03 + 1.2468553051e-01 + 2.8296078873e-02 + -2.2880512937e-02 + -5.8312440457e-02 + -6.5645236053e-02 + -4.2114007691e-02 + -1.2629830863e-01 + 4.4941820402e-02 + -1.4202913033e-01 + 4.4329718801e-03 + 2.6357693933e-03 + -5.9688544850e-02 + 8.3053728246e-02 + -1.4142352705e-01 + 9.8180468589e-02 + 1.2846954533e-02 + -1.0305086578e-01 + 7.0489771040e-02 + 6.0531447982e-02 + -7.2004567914e-02 + -1.2069541495e-01 + 2.0197153575e-01 + 3.7977368106e-03 + -1.3022016874e-01 + 1.2039477838e-01 + -4.1893315853e-02 + -7.0838772161e-02 + 7.1176114222e-02 + -4.1221028650e-02 + -7.1487567861e-02 + -4.4634400421e-02 + -3.1838260273e-02 + -4.6182600810e-02 + 1.2898358667e-01 + 2.2459888328e-03 + 1.3414744571e-01 + 6.8312249048e-02 + -4.4773273325e-03 + 1.4325434011e-01 + -4.7629161763e-02 + -3.5261258941e-02 + -1.2774064289e-01 + 1.2294634567e-01 + -1.4713184938e-01 + -3.1719488129e-02 + 4.7853279516e-03 + -1.3662620404e-02 + 7.9159410651e-02 + -5.7796361162e-02 + -6.4492232486e-02 + -5.8090102497e-02 + 1.1597860991e-01 + 5.9944197606e-02 + 6.9858164663e-02 + -1.5717550602e-01 + -2.2412195053e-02 + -5.0926364270e-02 + 7.0720648436e-02 + -2.2805371478e-03 + -1.0770876537e-01 + -1.1210664363e-01 + -6.2277715934e-03 + -7.2631991323e-02 + -3.1508639098e-02 + -6.5030031012e-02 + -9.3448449778e-02 + -5.0347762531e-02 + 8.3646376659e-02 + -1.1714221313e-01 + -6.3090438321e-03 + -1.0901214004e-01 + -2.2644551821e-02 + 4.2710138900e-02 + -4.7124172206e-03 + -4.9312363567e-02 + 6.7726644113e-02 + 3.3795299233e-02 + -2.7864287970e-02 + 1.0074997971e-01 + 1.4998457993e-02 + 7.9089219652e-03 + 3.0590200103e-02 + 2.0963986594e-02 + -8.9802883200e-02 + 5.3401972643e-02 + 7.4481681791e-02 + 2.0132278295e-02 + 7.6655576090e-03 + 4.8162448193e-02 + 8.9157197558e-02 + -2.7110269297e-02 + -2.1271547999e-01 + 2.6508188921e-02 + -8.8390537552e-02 + -8.5236063441e-02 + 4.1766632175e-03 + 1.1000760819e-02 + -1.2749302556e-01 + 7.0703924240e-02 + 1.1592286549e-01 + 2.2088123541e-01 + -7.6532592326e-02 + -2.3258118387e-02 + -3.1050099048e-02 + 3.7747264720e-02 + 1.2428424162e-01 + -2.2213843721e-02 + 2.1069052752e-01 + -1.4933832365e-01 + 3.4954099250e-03 + -6.2438072054e-02 + -2.2360005628e-02 + 1.3892443207e-02 + -2.9859283970e-02 + -1.4674549178e-01 + -4.5705420465e-02 + -3.2854948022e-03 + 2.8506216793e-03 + -7.0485118801e-02 + -4.8202181301e-02 + 6.3713956159e-02 + -5.0053018633e-03 + 1.1055338401e-02 + 1.2238367385e-01 + -7.9321137030e-02 + 5.1325686112e-02 + -1.0586870764e-01 + 8.4935678631e-03 + -4.8883668768e-02 + -6.8005043381e-03 + 9.9942824481e-02 + -8.4938086204e-02 + -6.5675211031e-02 + 6.8503069306e-02 + 1.1334267509e-01 + 5.1365137332e-02 + -1.4024292543e-01 + 1.4202220295e-01 + -7.7830277128e-03 + -6.5240921730e-02 + 2.0372394187e-02 + 4.7517166954e-02 + -2.1835148103e-01 + -9.3151164437e-03 + 9.0288726096e-02 + -5.3745670383e-02 + -1.0505132040e-02 + 2.6398392137e-02 + -7.3936932367e-02 + -1.8561007786e-02 + -8.6675124509e-02 + 4.0233723142e-02 + -9.2503140865e-02 + 8.1725490010e-02 + 1.5455369661e-02 + 2.2356748821e-02 + 1.0543977537e-01 + -5.3371844991e-02 + -1.8539004958e-01 + -1.2441217767e-01 + -8.0710989643e-02 + 5.7720897270e-02 + 1.5716289646e-02 + 9.8134166215e-03 + 1.7667824706e-02 + -2.0538474102e-01 + 6.1105140728e-02 + 8.3259054084e-02 + -4.3403041593e-02 + -9.3439697057e-03 + -3.6755465433e-02 + 1.7380857453e-02 + 1.2719101866e-01 + -1.0299589999e-02 + -1.9733022733e-02 + 8.2633771331e-02 + -2.7135546271e-02 + -3.3942825013e-02 + -3.3546572378e-02 + -1.0847887670e-01 + -1.1142718874e-01 + -7.3312592664e-02 + 5.2609930480e-02 + -1.0428034339e-01 + 8.8512196295e-02 + 4.1398698863e-02 + 3.5189273168e-02 + 2.3902841532e-03 + -8.5663260369e-02 + 3.7693825057e-02 + -1.0721949446e-02 + 5.2289016226e-02 + -1.4593438337e-01 + 4.7960691668e-02 + -1.2417295249e-01 + -5.3692268010e-02 + -1.5360767465e-01 + 8.7606035111e-02 + -1.9082860327e-02 + -7.0785299659e-02 + 7.8622925766e-02 + -5.8654367954e-02 + 1.0420652360e-01 + -6.4523988583e-03 + 1.6428250390e-01 + -1.1891043399e-01 + -5.6118415438e-02 + -7.9100174211e-02 + 1.1243569127e-01 + -1.1586723805e-02 + 9.8528164081e-02 + 7.8901717910e-02 + 3.8275067451e-02 + 5.4609056252e-02 + -7.0720185115e-02 + -5.6330965121e-02 + -5.0176563583e-03 + -6.3067806565e-02 + -6.5136771465e-02 + -4.4418193229e-02 + 8.6803598731e-02 + -8.2281063882e-03 + 1.2886016193e-01 + -6.4753159337e-02 + 3.9853326338e-02 + 4.4375312997e-02 + 2.4056126627e-02 + -1.0715694711e-01 + -6.6554082621e-02 + 1.0153968055e-01 + 1.1063390011e-01 + -5.9338766156e-02 + 2.9416212621e-02 + -1.5916306158e-02 + 6.4137192399e-02 + 6.2394446212e-04 + -4.9420213404e-02 + -8.9194820608e-02 + -3.9026038217e-02 + -5.1613624452e-02 + -5.4946464368e-03 + -2.1723168048e-01 + 2.5034232413e-02 + 3.6917745061e-02 + -8.1208534297e-02 + -1.6669105873e-01 + -2.1732982280e-02 + 1.2515665795e-01 + -1.8427207783e-01 + 1.6518201968e-02 + 3.3142994931e-02 + 1.9573231993e-02 + 1.0604621587e-02 + -5.5106586492e-04 + -1.1166560752e-01 + -6.2756066470e-02 + 6.5674732345e-02 + 3.2999594274e-02 + 1.0230926035e-01 + -2.2210756219e-02 + -5.9381229776e-02 + -8.7192537703e-02 + -8.1712778062e-02 + -1.1690920770e-01 + 5.1876009651e-02 + -1.6474189682e-02 + 3.0069219252e-02 + 1.7773013854e-02 + 1.1550326445e-01 + -4.3455048819e-02 + -5.3718646372e-02 + -9.7325716571e-02 + -1.6242012404e-01 + 7.1464428080e-02 + -5.6799843934e-02 + 3.1997460478e-02 + -1.1421785914e-01 + 4.6414067210e-02 + 2.1644560953e-02 + -3.9213053441e-02 + -2.2255471219e-02 + -1.2864231685e-01 + 4.6760131657e-02 + 4.7988366856e-02 + -9.0150695851e-02 + 4.5425045757e-02 + 3.7091175321e-02 + 2.6166052663e-02 + -1.7366932919e-02 + 6.0464575602e-03 + 5.6075695453e-02 + 4.4347889790e-02 + -1.6920895067e-02 + 3.5117635129e-02 + 2.7902638625e-02 + -1.7070819360e-01 + 6.0616582756e-02 + -3.6587193617e-03 + 1.3369793783e-01 + -2.5440141323e-02 + 7.4899034017e-02 + 4.9906817326e-02 + 3.2751916136e-02 + 9.8124746352e-02 + 8.0338789946e-02 + 4.3583082670e-02 + -1.3784531108e-02 + 1.1737870784e-02 + 3.9840262357e-02 + -8.7929931296e-02 + 7.4084436191e-02 + 7.2255524090e-02 + -6.8521161175e-02 + -1.2309448423e-01 + 3.7535837348e-02 + 1.7180707139e-02 + 7.1433044605e-02 + -1.2604143560e-01 + 1.3012201533e-01 + 4.6881309857e-02 + -1.6818083594e-01 + 2.6521386829e-02 + 3.1119814740e-03 + -9.1197330247e-02 + 1.3381005817e-01 + -2.6031766296e-02 + 5.7902690503e-02 + -9.4366974809e-02 + 1.0425626412e-01 + -5.9619944639e-02 + 4.4165876879e-02 + -6.7032265825e-02 + 4.1000996267e-02 + 1.3760186844e-01 + 8.8242378230e-02 + -4.3672646619e-03 + -1.9088300573e-02 + 1.8258024094e-02 + 1.7433109444e-02 + 3.7228312552e-03 + 4.0810127522e-02 + -3.4275483980e-02 + 1.4839984235e-01 + 5.3114584415e-02 + 1.1732283435e-02 + -8.5608015992e-02 + 2.9368457780e-02 + -7.9825196799e-03 + -6.8966745090e-02 + 6.2776337417e-02 + 1.0764877992e-01 + -2.6233823835e-02 + -2.2192173599e-02 + -3.9293816566e-02 + -1.9593814980e-02 + -2.0430512058e-02 + 1.2978273322e-01 + -7.7509151387e-02 + -8.4930508020e-02 + -1.8698825361e-02 + -3.6568425557e-02 + 1.6871246811e-02 + -2.0052438246e-02 + -6.6280347450e-02 + -4.4619270907e-02 + 3.4285108066e-02 + -2.9586950755e-02 + -3.7931627065e-02 + 3.0223848919e-02 + 3.3593315056e-02 + 1.3737486598e-01 + -7.3157267877e-02 + -5.6220761769e-02 + -4.5938789544e-02 + 5.9927419008e-02 + 6.0240222498e-04 + -5.6736959035e-02 + -1.6854575150e-01 + -2.0119845447e-02 + -3.7446118689e-02 + -3.5470249223e-02 + 3.5971498635e-02 + -6.8671515276e-02 + 1.1169328750e-02 + 2.5941547818e-01 + -3.0360336309e-02 + -2.7728333098e-02 + 1.1797008045e-01 + 1.8349371625e-02 + -6.0469977809e-03 + 6.3956384458e-02 + 9.5064669090e-02 + 4.6972123366e-02 + -6.1123182276e-03 + -2.5918905256e-02 + -3.9082916371e-02 + -1.4255836539e-01 + -7.3212081109e-03 + -1.5130262526e-02 + 1.8528053119e-02 + 7.4412586664e-02 + 2.1025959853e-01 + -6.7253606514e-02 + -3.1589490804e-02 + -9.0272974932e-02 + -9.6544338458e-02 + -1.1442736446e-01 + -8.6618709473e-02 + 2.0091451510e-01 + -1.9520796003e-02 + 1.6115320872e-01 + -1.8744464017e-01 + -8.0551670398e-02 + 1.0375335029e-02 + -4.8311574308e-03 + 1.8822243177e-02 + 2.0210960991e-02 + -5.4924855225e-02 + -5.8788745465e-02 + 2.2800674157e-02 + 1.1100081225e-01 + -7.1367252815e-02 + -4.5363347156e-02 + 6.9336402713e-02 + 8.2886582253e-02 + 1.2725455293e-01 + -4.0398845900e-02 + 5.6077051629e-04 + 5.4045783444e-02 + 1.0912995777e-02 + 3.8500922980e-02 + -1.8406605547e-02 + 8.0163359934e-02 + -3.3569664124e-02 + -4.9972562890e-02 + -2.1357515029e-02 + 6.0499554222e-02 + -5.7451759242e-02 + 6.3776083287e-02 + -1.7126454788e-02 + -8.1298574386e-02 + 5.4000566010e-02 + 5.1234254740e-02 + 1.2591291513e-01 + -4.8963161115e-02 + 6.6964827566e-02 + 1.0592593465e-02 + 4.7890102931e-02 + 1.1767723092e-01 + 2.1035411229e-01 + 1.0054771117e-01 + 1.9401674848e-02 + -1.9584515562e-02 + -4.4393899294e-02 + -1.0942235597e-02 + -1.3455486889e-01 + -3.4669982447e-02 + -1.1759069573e-02 + -1.7572690252e-02 + 3.2287792789e-02 + -2.3858278346e-03 + 5.8618824847e-02 + -7.4368615229e-02 + -1.8349356328e-01 + -6.8851699375e-02 + 2.9033665652e-02 + 2.6568045027e-02 + 1.1792950657e-01 + 3.9506183479e-02 + -1.4653435463e-01 + 1.5991203759e-02 + -3.9426661717e-02 + 7.8870775609e-03 + 1.6700441329e-02 + -7.6464307562e-02 + 2.2768832802e-02 + -7.0640342375e-02 + 3.0119137580e-02 + 2.7028650322e-02 + -5.7323266654e-02 + -4.5018692818e-02 + 3.0874049855e-02 + 1.0402949687e-01 + 7.4146282670e-02 + 3.7694312113e-02 + -8.4312280314e-02 + -1.8616468179e-01 + -2.3626499095e-01 + -2.8303121056e-02 + 1.3058746109e-02 + 1.2055909837e-01 + 8.3900102079e-03 + 2.2422390380e-02 + 1.0078319187e-01 + 9.7079634052e-02 + -1.2533552368e-01 + 4.1001931440e-02 + 1.4339845694e-02 + -1.6064523227e-01 + 3.9072001165e-02 + -3.0741623188e-02 + -6.9818167961e-02 + -2.3264177667e-02 + 3.9396103549e-03 + -6.6604036156e-02 + -1.5328611353e-01 + 2.0659648503e-01 + -3.9393759894e-02 + 1.8376840247e-02 + 1.4090925013e-02 + -5.0764827110e-02 + -3.4466132011e-02 + 2.9064027950e-02 + -5.8869429541e-02 + 7.0740362833e-02 + -1.1042615570e-01 + -4.1319850371e-02 + -2.1082417981e-02 + -1.7949858873e-02 + -8.9542622643e-02 + -2.5844534008e-03 + 1.3932209215e-01 + -2.8003598847e-03 + -8.1670864426e-02 + 2.6883943212e-02 + -1.8354703978e-02 + 7.3433018201e-02 + -5.5169153161e-02 + 4.4846362149e-02 + -1.3869457626e-01 + 8.4052931323e-03 + 1.2760377406e-01 + -9.7195152512e-02 + -1.0118307873e-01 + -2.4414376398e-02 + 3.3219021081e-02 + -1.4372620360e-01 + -2.0696749870e-01 + 1.7275876684e-02 + -1.2768896642e-02 + 2.2515639855e-02 + 8.1587417629e-02 + 6.6221884690e-03 + -3.6521049948e-02 + -9.3215775274e-02 + 1.0933229064e-01 + 4.0750243051e-02 + 1.1963619950e-01 + 1.0384101121e-02 + 9.0340719124e-03 + -8.5166989862e-02 + 4.4408272047e-02 + 8.5758437527e-02 + -6.0235442526e-02 + -4.0752826419e-02 + 6.3648995974e-03 + -1.8827034995e-02 + -1.0861798622e-02 + -1.0233062545e-01 + 1.6281875777e-02 + -7.4878550362e-02 + -1.0017718287e-01 + -8.0739667671e-02 + 2.4878987024e-02 + 4.6124471447e-02 + -1.2820990108e-02 + -5.9409893052e-02 + -1.1430099726e-01 + -1.2439326528e-01 + 8.3113280216e-02 + 4.5209332433e-02 + 1.1669239019e-03 + -9.6421020776e-03 + -4.4222065392e-02 + -9.8190494465e-03 + -9.3557306896e-02 + -4.2559165789e-02 + -1.3742955902e-02 + -3.4838158357e-02 + 6.0511136075e-02 + 2.4827924293e-02 + -2.6305704664e-02 + 6.5539944514e-02 + 4.4063573200e-02 + 1.3132040123e-01 + -4.6517940120e-05 + -7.4368637485e-02 + -2.6146392152e-02 + -2.9564362729e-02 + 3.6690198654e-02 + 7.7125169705e-02 + 4.0412569952e-02 + 4.1347935901e-02 + -9.1980028220e-02 + -5.2386370707e-02 + 3.1899975692e-02 + -6.4680982303e-02 + -1.0708155437e-02 + -2.0416791091e-01 + 7.7354098727e-02 + 4.5168300833e-03 + 3.8346163138e-02 + 1.2236040148e-01 + 7.7915989643e-03 + -8.5551366161e-02 + 7.5866024055e-02 + 2.1597765292e-03 + -7.0280148373e-02 + 1.6135821076e-01 + -4.2351199747e-02 + 6.7800103467e-03 + -6.8438346722e-03 + 1.4493983154e-01 + 3.5425619546e-02 + -9.8057234432e-02 + 3.6547632952e-02 + 2.1822724562e-02 + 3.1866833209e-03 + 7.4376629423e-02 + 5.9881272861e-02 + -4.4251464579e-02 + 1.3732462914e-02 + 1.3033082085e-01 + -1.5767327174e-01 + 2.0796540924e-02 + 3.4436672194e-02 + -1.3061119316e-02 + 8.1493186905e-02 + -5.3175629103e-02 + -5.2407328726e-02 + 1.6491959213e-02 + -8.2915377139e-02 + 1.2556501629e-03 + 9.7744475944e-02 + -2.3237902556e-01 + 1.4370133347e-01 + 1.1454555684e-01 + -6.3330111705e-02 + -4.8101159788e-02 + -5.0717344948e-02 + 9.7791105611e-02 + 6.8352253496e-02 + 1.4143146465e-01 + -1.2678322160e-02 + -9.4286960948e-02 + 2.5703948948e-02 + -4.8325005562e-02 + 2.0091720746e-02 + -4.6411904843e-02 + -3.3058694374e-02 + -2.6885591645e-02 + 1.2444972011e-02 + 4.3065482833e-02 + -2.5480791943e-02 + 5.3887304126e-03 + 7.6061387024e-02 + -1.0065561526e-02 + 9.7820066122e-02 + -5.3854104853e-02 + -5.0511143340e-02 + -2.4454531268e-01 + 5.6327751791e-02 + 2.7837621905e-02 + -2.4940247489e-02 + -2.0143515164e-03 + -8.7616400458e-02 + 6.8661882053e-02 + 6.3645212246e-02 + 1.5104783820e-02 + 2.0196809138e-02 + -2.1909826786e-02 + 1.7626631848e-01 + 6.1359066001e-02 + -5.1704230104e-02 + 9.0534585729e-02 + -8.2870769705e-02 + -8.6459105829e-02 + 7.6827351392e-03 + -1.1267931804e-01 + 5.2866699045e-02 + -9.6983995582e-02 + -1.1829716188e-01 + -1.1004519751e-02 + 1.9752950108e-02 + 6.8376123364e-02 + 4.9444701622e-02 + 7.5275174897e-02 + -4.3412404195e-02 + 7.5553481294e-02 + 8.2607529758e-02 + -4.7860273879e-02 + 2.4629809636e-02 + 4.5920979643e-02 + 1.1476340678e-01 + -1.2266119102e-02 + -8.1219046827e-02 + -8.4697607735e-02 + -2.4599308111e-02 + -3.5408730837e-02 + 1.4964996709e-01 + 2.6505317728e-03 + -4.0339280656e-02 + 1.2810686928e-01 + -9.9062465121e-02 + -1.4779508950e-02 + 1.6010593618e-01 + -9.1548831643e-03 + 5.0443503683e-02 + -6.4500624518e-02 + -2.1941201380e-02 + -9.3482330754e-02 + 1.1920561677e-01 + -7.8323146548e-02 + -1.5296077130e-01 + -5.0875009932e-02 + 3.7364575782e-02 + 8.3424301639e-02 + 3.0130839700e-02 + 3.0965227334e-02 + -9.9587992945e-02 + -1.3296862630e-01 + -7.1963447418e-02 + 7.5084546905e-03 + -5.3040285447e-02 + -1.9016046162e-01 + -5.3671965441e-02 + -2.2257499037e-02 + 2.5154769333e-02 + -4.3967839561e-02 + -7.0258854717e-02 + -6.8076406963e-02 + -1.3490259069e-01 + 1.3356561121e-02 + 2.8327151401e-02 + -5.3080288114e-02 + 1.0811505719e-01 + 9.9059285957e-02 + 2.7995094588e-02 + -1.1075034684e-01 + -7.3959996417e-02 + -9.5514831304e-02 + 3.1631664341e-02 + -5.2421806659e-02 + -4.4189785821e-02 + 6.5744348154e-02 + 1.1015057632e-01 + 2.8902500598e-02 + 6.0431542062e-02 + -5.8251228714e-02 + -1.3154075936e-01 + 1.2611353236e-01 + 1.2892499635e-02 + -1.3675847919e-01 + 8.1006018888e-02 + -3.0128718522e-04 + -3.2157580733e-02 + -1.7332962860e-01 + -6.4149786903e-02 + 2.7667487434e-02 + 9.7910752488e-02 + -7.8461561145e-02 + -1.5760381814e-02 + 1.1953781597e-02 + 3.1593073532e-02 + -2.9420401220e-02 + 1.7054512033e-02 + 9.3581161584e-03 + -1.8067508053e-01 + -1.0121532879e-01 + -9.6391215027e-02 + 9.3971327917e-02 + 1.6044013687e-01 + 1.7760668875e-02 + -1.9417497401e-02 + -9.9878404443e-03 + 6.0907262287e-02 + -1.4292151932e-01 + -8.1096533198e-02 + -2.8878851805e-02 + -6.9549370755e-02 + 1.0282456509e-01 + -1.4098808722e-01 + 7.3068701724e-03 + -1.2703406314e-02 + -1.9578885720e-02 + 3.3759713598e-02 + 9.4842629655e-03 + 1.2418595190e-01 + -4.8830871566e-02 + 1.1578695394e-01 + -1.0345243838e-01 + 1.3430408214e-01 + -5.3161205146e-02 + 6.7281491682e-02 + 8.2681784885e-02 + 3.3705559457e-02 + -7.7597835788e-02 + -1.2981085585e-02 + 1.2895342053e-02 + 7.3415882935e-02 + -1.3165802967e-01 + -6.6264871745e-02 + 9.3939780375e-02 + 4.3242538580e-02 + 1.8077336630e-02 + 1.9720119756e-02 + -4.6617846026e-02 + 4.9489952229e-02 + -1.0586930751e-01 + -8.2155763490e-02 + -1.0860610190e-02 + -7.5907239549e-02 + 1.8369767486e-01 + 1.2818310796e-01 + -1.9905967226e-01 + 3.5489343637e-02 + -2.9259816861e-02 + 4.7057230997e-02 + 6.4711930265e-02 + 4.3854059497e-02 + -8.1225029556e-02 + -1.5796255909e-01 + -1.3771562380e-01 + 4.5129097697e-02 + 7.6367529197e-02 + 4.2079843429e-02 + -4.1323443914e-02 + -6.7959237333e-02 + 4.0343177507e-02 + 9.8950986928e-02 + 5.5329905906e-02 + 1.0587410546e-02 + 4.5658016262e-02 + 5.2057315304e-02 + 5.1088966116e-02 + -1.2552066756e-01 + -3.7440835648e-02 + -2.8941223624e-02 + -6.9647886834e-03 + -1.9094128205e-02 + -1.2207280707e-01 + 5.6559001430e-02 + -5.9510772171e-02 + 5.8569358922e-02 + -2.2994719809e-02 + 1.6625031599e-01 + 1.2850807879e-01 + -4.7236628567e-02 + 3.1948833203e-02 + -6.7277524673e-02 + 1.7704177926e-01 + -3.1714163644e-02 + -2.6753368655e-02 + -1.3894986078e-01 + -6.1587795411e-02 + -5.9789993440e-02 + -1.3532025664e-02 + -2.5353948878e-02 + 1.1879794026e-01 + -3.3517711293e-02 + 1.8869188216e-01 + 1.0035134324e-01 + -4.3752195196e-03 + 1.5001075717e-04 + -7.0314126292e-02 + -7.8501711793e-02 + 4.4135885558e-02 + 3.3655168980e-02 + 8.7668701748e-02 + 4.4762791266e-02 + 3.8789790916e-02 + -3.5936958014e-02 + -7.0014206367e-02 + -7.7248759172e-02 + 9.0351315357e-02 + -7.2467920688e-03 + 1.3378589773e-01 + 1.7098273851e-02 + 5.1642058715e-02 + -5.8086041947e-02 + -4.1468177223e-02 + 2.7839839984e-02 + -2.6206432108e-02 + 4.4967550425e-02 + -4.6586005204e-02 + 1.5055248193e-02 + 9.1137858001e-02 + -7.1302084714e-02 + 5.8902855068e-02 + 6.4056429667e-02 + -2.9150960142e-02 + -2.8818796211e-02 + 7.9795110233e-02 + 5.2170796760e-02 + -8.8713346717e-02 + 5.8544596892e-02 + 3.9610890812e-03 + -7.4031104154e-02 + 4.1126596651e-02 + 7.9397811354e-02 + 6.7415935596e-02 + -6.2842736730e-02 + -8.4054202525e-02 + -1.1242527275e-01 + 5.9402502522e-02 + -1.6107913449e-01 + -2.3999791206e-03 + -5.4824718119e-02 + -8.0425270417e-02 + 3.4411110069e-03 + -4.7045929281e-02 + -3.1163916952e-02 + -4.9945461698e-02 + 1.5518069680e-02 + 1.4684108308e-01 + -7.8733027985e-02 + -9.3947822860e-02 + -2.3982640297e-02 + -7.5471020420e-02 + 2.0599505042e-02 + 4.1240874981e-02 + -5.3470693794e-03 + -3.1650444296e-02 + 5.0265495603e-02 + 6.6444152130e-02 + -2.3009824035e-02 + 6.1152199421e-02 + -1.8390837324e-01 + 1.5897360715e-01 + 5.6343902190e-02 + -2.3876709671e-02 + -7.6914863843e-02 + -7.8756015620e-02 + -1.1192421849e-01 + 1.2751275956e-01 + 5.7421509714e-02 + 2.6884930485e-02 + 7.0912436386e-02 + 1.0166292994e-01 + -5.9043261197e-02 + 2.6580527190e-03 + -4.1023494022e-03 + -7.4101775070e-02 + 6.0158947478e-02 + 1.5138569549e-02 + 1.1686716891e-01 + 1.1919753946e-01 + 5.4237513528e-02 + 7.8676860831e-02 + -1.4231309466e-01 + -7.4374662340e-02 + 2.2882404902e-02 + 6.2831565285e-03 + 1.1354010249e-01 + -1.5239092010e-02 + 2.3677980448e-02 + -1.3912654721e-03 + -2.0444407690e-02 + -3.0590013484e-03 + -6.1666569281e-02 + 9.9718891408e-02 + 3.7400774229e-02 + 5.7939667660e-02 + -3.4923316644e-02 + 1.3865748307e-02 + 1.2762924649e-01 + 1.6198103618e-01 + 3.5708064529e-02 + -1.5954836161e-02 + 1.5005328518e-01 + -1.9436107590e-02 + -6.1981271258e-02 + 4.0510723295e-02 + 7.6202252948e-02 + -8.7432453133e-03 + -4.5511202265e-02 + 1.5014905461e-01 + -4.8921135546e-02 + -6.6561933877e-02 + 1.7712386362e-03 + 3.5585128245e-02 + -3.4575570077e-02 + 5.2650726923e-02 + 5.2514407522e-02 + 2.0666661995e-02 + 5.3195665902e-03 + -4.6537050210e-02 + 3.1102070213e-02 + -5.3886348436e-02 + -2.8777427087e-02 + -1.2008026567e-01 + -3.9855176119e-02 + -7.0008224951e-02 + -1.6544604147e-02 + -2.2883681133e-02 + -7.4605573931e-02 + -2.9261753296e-02 + 7.1529082469e-02 + -3.2936611774e-02 + -1.5920657801e-02 + 4.0589599903e-02 + -1.5857881789e-02 + -5.9206611213e-03 + 3.5036385027e-02 + 8.5710011504e-02 + 3.9195281641e-03 + 5.0159684387e-02 + -1.2363147875e-01 + -7.9528113609e-03 + -4.3759804117e-02 + 2.2196971671e-02 + -1.3307937199e-02 + -4.3955330044e-02 + -5.0302826832e-03 + -2.2470240298e-03 + 3.3132110895e-02 + 4.3558296022e-02 + -1.4747129150e-02 + -8.1585434894e-02 + 2.3731318559e-03 + 1.6956837366e-01 + 4.7429115884e-02 + -7.0365056842e-02 + 2.6369270862e-02 + -9.0897832205e-03 + 3.5299048089e-02 + -6.3218414895e-02 + -2.2324818369e-02 + 7.3861460262e-02 + 3.1914912638e-02 + -1.8305559421e-02 + -1.1886968618e-03 + 6.8847727012e-02 + 1.0469132138e-01 + -1.0193418222e-01 + -7.4511761236e-02 + 3.1316077908e-02 + -5.0310566041e-02 + 3.5055039572e-02 + 6.1477072139e-02 + -5.6050539913e-02 + 2.3515658029e-01 + 6.9357514790e-02 + 4.8661384580e-02 + 7.8188433454e-02 + -1.2813669114e-02 + -2.1046013883e-02 + 1.4743114342e-01 + 1.7652893498e-02 + 2.8694240991e-02 + 5.8316812828e-02 + -6.2065295560e-02 + -1.2297057553e-03 + -6.8209664734e-03 + -1.7988839177e-03 + 1.1817245535e-01 + 9.3233363364e-02 + -6.8193484397e-02 + -6.3577667191e-02 + -3.7535990432e-03 + 4.1582517086e-02 + 6.0159530292e-02 + -1.5516278042e-02 + 6.8590332543e-02 + 1.5471266552e-02 + 1.2604006574e-01 + -1.6651866159e-02 + -6.0124738349e-02 + -2.1279880102e-02 + -3.0939288651e-02 + 3.7110333967e-02 + 1.3050835860e-02 + 9.1325056222e-02 + -5.8925608705e-02 + 3.1719069596e-02 + -1.6662209936e-02 + 5.7891881186e-02 + 1.6386039492e-01 + 9.2652275912e-02 + -4.7662114733e-02 + 5.1559697635e-02 + -6.9381210671e-02 + 1.3834249978e-01 + -7.8505959010e-02 + 6.3984393405e-03 + 6.1941974975e-02 + -9.7303269358e-02 + 1.3690059118e-02 + 2.1558965003e-01 + 1.0114171691e-01 + -6.0761998708e-02 + 8.1928105784e-02 + -2.5352511885e-02 + -8.5852105447e-02 + 1.7242188847e-02 + 7.8844742367e-03 + 1.1463510357e-02 + -3.9693799232e-03 + -5.9521467422e-02 + 7.3747049120e-02 + -2.8345964948e-02 + -7.4769382614e-02 + -3.9124366794e-02 + 7.5942503668e-02 + -5.0267494727e-04 + -8.3708287627e-02 + -1.4625015858e-01 + 4.3923811993e-02 + 8.2406716690e-02 + -1.0240478429e-01 + -6.4403797586e-02 + -1.0848838864e-02 + -5.0896869406e-02 + 7.8634527904e-02 + 1.0297435525e-01 + -1.3755736575e-01 + -1.2669399326e-01 + -1.3221632268e-02 + 5.4519957099e-02 + -1.1816589562e-02 + -2.1422584493e-02 + -2.7343793856e-02 + -4.5940757204e-02 + -6.9992946298e-02 + -6.0542364588e-02 + -7.4037912165e-02 + -1.2553249887e-04 + -2.9304174060e-02 + 9.0129514812e-03 + 4.6616556056e-02 + 1.3146103330e-02 + 2.5480452029e-03 + 1.4445329317e-01 + 7.3005926016e-02 + 7.2805926958e-02 + -3.0796294442e-02 + 4.7808492400e-02 + -6.3918700268e-02 + -5.9097526604e-02 + -1.0190721993e-02 + 1.1668924450e-01 + -1.1663306059e-01 + 4.1541072100e-02 + -1.4658788286e-01 + -3.2177434960e-02 + -9.0480016376e-02 + 5.0255507085e-02 + -1.2477416860e-01 + 2.1040050365e-02 + -4.9738735253e-02 + -1.0053376502e-01 + -1.6682151155e-01 + -7.1814503145e-02 + -6.7637311164e-02 + 5.1247469465e-03 + 6.0470011871e-03 + -8.1383290524e-02 + -6.2075777407e-02 + -5.3873103233e-02 + -6.5126185621e-02 + -1.7061981333e-02 + 3.1947752050e-02 + -5.7419685947e-02 + 7.0913708800e-02 + 1.3503594796e-01 + -6.3432529047e-05 + 5.4331961909e-02 + 3.5696028071e-02 + -6.2739078754e-02 + 8.5334420237e-02 + -5.0473881261e-02 + -7.7163837633e-03 + 7.8789648720e-02 + 1.4925629891e-01 + -2.8863063513e-02 + 1.7649222417e-02 + -2.2259294252e-02 + -2.7653390404e-02 + -5.9200301358e-02 + -3.1039661975e-02 + 1.7906045507e-03 + 1.5567032694e-01 + 6.1094047317e-02 + 4.1592044142e-02 + 2.0539421080e-01 + 3.7272705622e-02 + 1.5241196200e-02 + 7.6161152324e-02 + -1.4606971746e-01 + 7.5605350126e-02 + -1.7885925992e-02 + 1.5259828389e-02 + -1.1734702838e-01 + -9.3758475960e-02 + -1.1406237486e-01 + -9.2852534827e-02 + -1.1092916915e-01 + 1.3260408198e-02 + 1.3537844134e-02 + -1.9312174019e-01 + 5.6027112971e-02 + 6.6514161390e-02 + 6.2009081566e-02 + -2.0498192090e-02 + -2.7177129433e-02 + -5.6064598410e-03 + 1.6270316289e-01 + 6.3471108198e-02 + 5.7282583688e-03 + -7.8656591027e-02 + -1.1516235286e-01 + 7.6096838878e-02 + -6.4514709633e-03 + -7.6287338093e-02 + -4.1914229627e-03 + -1.0345470667e-02 + -3.9760456565e-02 + 7.9333630167e-03 + 1.8382834765e-02 + 1.7873490070e-01 + 1.0671903819e-01 + -7.8990475040e-02 + 6.3143955160e-02 + -7.3133661185e-02 + 4.9909610117e-02 + 5.7117733869e-02 + 5.5013406900e-02 + 1.2246209529e-01 + 6.8845129994e-02 + -5.3706069456e-02 + 5.2558563536e-02 + -6.5585914917e-02 + -4.7380839593e-02 + 4.2209584076e-02 + -3.2116822059e-02 + -7.3441558588e-02 + -1.9350410356e-01 + -3.9695142681e-03 + -1.1446626511e-01 + -1.9779551490e-02 + -1.6586492095e-01 + 1.3738707720e-01 + 3.1568465127e-02 + 3.7026636308e-02 + 6.9404616081e-02 + -1.7515264976e-02 + -2.1753837668e-02 + -3.7650234022e-02 + -1.4807767903e-01 + -9.2205583121e-02 + 6.5663169271e-02 + -5.8291855877e-02 + -2.9347221254e-03 + 1.0304333260e-01 + -3.1578396770e-02 + 2.8348844702e-02 + -2.2720054293e-02 + 2.1510595368e-02 + -3.4184101392e-03 + -7.0119733425e-02 + 2.8613432300e-02 + -1.0030750046e-01 + 3.0029571381e-02 + 4.4349339350e-02 + -3.9879620559e-03 + 8.4062301766e-02 + 3.1459820936e-03 + -1.0254996003e-01 + 2.5471137313e-03 + -9.7376065748e-02 + 2.0382006367e-01 + -8.2201747211e-02 + -3.5969452032e-03 + 9.9270511180e-02 + -2.8368074109e-02 + -6.9289551604e-02 + -3.3563270047e-02 + 3.1113681832e-02 + 1.4114796182e-01 + 1.1889673853e-01 + 6.9008839732e-03 + -7.9587161929e-02 + 4.2543916818e-02 + -6.3360674271e-02 + 3.4195233165e-02 + 1.5099262779e-01 + -7.1124003659e-02 + -2.6031873440e-02 + -2.1824610716e-02 + -2.2674692564e-02 + 5.3501216384e-03 + -2.4692107104e-03 + 1.2881806114e-01 + 1.1829638448e-01 + 1.2402683957e-01 + 2.1139626432e-02 + 6.6803501739e-02 + 9.7734469780e-02 + -4.3117147063e-02 + -3.0870703752e-02 + -4.4908352406e-03 + 4.7579575971e-02 + -1.0957360442e-01 + -7.5885001370e-02 + 1.4849427635e-01 + -3.7338531672e-02 + 6.7920751183e-02 + 1.9266999893e-02 + -3.0053656796e-02 + 3.3378142458e-02 + 4.4452742525e-02 + 7.9876596806e-02 + 2.5319230911e-02 + 1.9513922708e-02 + -8.1505650647e-02 + 2.3815814628e-02 + -1.1405040285e-01 + 1.5725709265e-01 + 4.2678664941e-02 + 2.1358573218e-02 + -2.2519264614e-02 + 1.4310231359e-01 + 6.6678796247e-02 + -1.1696235015e-02 + -1.3215204980e-01 + -1.8607046382e-01 + -6.6441394851e-02 + -1.4399580629e-01 + 1.3405447155e-01 + -4.6294686766e-02 + -2.8439684197e-02 + 3.4272796616e-03 + 7.4128426664e-02 + 1.0015014477e-01 + -1.5309260226e-02 + 4.9080929224e-02 + 3.7725354835e-02 + -3.2387479613e-02 + 5.9008836719e-02 + 6.6709421659e-03 + 1.6792631054e-02 + -6.1923865719e-02 + 4.6736511925e-02 + -5.1277346871e-02 + -2.9058581109e-02 + 7.9742091251e-02 + 5.7148016382e-02 + 2.9182530712e-02 + -3.5573247300e-02 + 1.4792054968e-01 + 1.7857113987e-01 + 2.2898787455e-02 + 8.1636451365e-02 + 7.9617771875e-02 + 8.9064831247e-02 + 1.2055861144e-01 + -2.9672594535e-03 + 7.9990292343e-02 + 4.2423248879e-03 + -3.4852372515e-02 + -3.2070458653e-02 + 8.1006103083e-03 + 8.7275398587e-02 + -5.5769107829e-02 + -1.6828352404e-03 + -1.2619299117e-01 + -4.7263313441e-02 + 2.9148700145e-03 + -3.7547836936e-02 + -4.0033593085e-02 + -3.8907722270e-02 + 1.3258261700e-01 + 5.0743715086e-02 + -1.6470602982e-02 + 8.4378650034e-03 + -7.5594649731e-02 + 1.3711300441e-01 + -2.6840290350e-02 + 1.2293323182e-02 + -1.7197218453e-01 + -1.2783852510e-02 + 8.9033194918e-02 + 8.1493744340e-02 + 8.1644954546e-02 + 8.7352438683e-03 + -1.4125707544e-02 + 3.3608024962e-02 + 1.1244082662e-04 + 2.1191370288e-02 + -3.3585333801e-02 + 1.0106603962e-01 + -7.9368855171e-02 + -2.8953077319e-02 + -6.6303077756e-02 + -3.5259810217e-02 + 1.5439393618e-02 + -3.7304025807e-02 + 5.3168998382e-02 + 1.1069469618e-02 + 4.4447351447e-02 + 1.0139376666e-01 + -1.4217276298e-01 + -2.4883182982e-02 + -1.8079015518e-01 + -3.2764715656e-02 + -6.7974486465e-02 + 9.6008681586e-02 + -2.6889000288e-02 + 1.1804615735e-01 + -8.8908745375e-02 + 2.1169805691e-02 + 1.3777026319e-01 + 4.5908930644e-02 + -1.1101569459e-02 + 4.7960665541e-02 + 1.3072571784e-01 + 2.1463633951e-02 + -2.1366315510e-01 + 7.8670671133e-02 + 3.0274686791e-02 + 1.2659763546e-03 + 7.9397133517e-02 + -5.7608158633e-03 + 1.3104505989e-02 + -1.1004611505e-01 + -1.0183586853e-01 + 1.2709272339e-01 + -2.3135281413e-01 + -9.9005802553e-03 + -3.2233878754e-02 + 2.0655479874e-01 + -8.5233966933e-02 + -8.1054145100e-02 + -4.0052200049e-02 + 2.8360678771e-02 + -7.2971132662e-02 + 8.5026539741e-03 + 8.3307887819e-02 + 1.2786048736e-01 + -3.0307543137e-02 + 9.5882356575e-02 + 3.2288402529e-02 + -5.8055445921e-02 + 1.9748677000e-03 + 9.9599036322e-02 + -9.9349980221e-02 + -2.8235414715e-02 + 8.8948482462e-02 + -2.6987900830e-02 + 7.9903126770e-02 + -4.6905941502e-03 + 9.3906729626e-02 + -2.0830263496e-02 + 2.9176591694e-02 + -2.6019881501e-02 + -8.0349790359e-02 + 1.1155412246e-01 + 6.5350742749e-02 + 1.2261939919e-01 + 1.0332770698e-01 + 1.6702594834e-01 + -3.7836571708e-02 + -3.6686681163e-02 + 6.5328593685e-03 + -7.2655575114e-02 + -4.9192720006e-02 + -5.1291945685e-02 + -3.2566645987e-02 + -1.5336946545e-01 + -1.2119532669e-01 + 1.6068632451e-01 + 1.0789874894e-01 + 7.0216831104e-02 + -8.0179536517e-02 + -6.4808869484e-03 + 8.3757825268e-02 + 1.0853503362e-01 + 4.4541392562e-02 + 6.3718390849e-02 + 3.2689371387e-02 + 3.6876376141e-02 + 1.4043474129e-01 + 1.2028194911e-01 + 1.3378513365e-02 + 4.4226127903e-02 + 1.6904822825e-01 + -9.2873289696e-02 + 1.1730320915e-01 + 1.4522611447e-01 + 1.6911956340e-01 + 4.8034945767e-02 + -7.5246733133e-02 + 9.7095413492e-02 + -2.1486712559e-02 + 1.4735755471e-02 + 5.4650405849e-03 + -5.6614866433e-02 + 7.7692094988e-02 + 7.7407314961e-02 + 9.2104888336e-02 + -9.2073558253e-02 + 3.5835747375e-04 + 5.3046771615e-02 + -1.2191675626e-01 + 8.2023799845e-02 + -8.0279581961e-02 + -1.6582072580e-01 + -1.3747043420e-02 + 4.0680273397e-02 + -1.2100286247e-01 + 1.0565325905e-02 + 7.7655400927e-02 + -4.7320315806e-02 + 1.7001862034e-01 + -1.2389935189e-02 + 1.0936425321e-01 + -7.7828912777e-02 + 2.5926941025e-02 + 6.5121085722e-02 + -1.5769969242e-01 + -1.9006877971e-01 + 4.6534558911e-02 + 2.2706007266e-02 + 1.4260779372e-01 + 6.3688909043e-02 + -6.1601116099e-02 + 6.6228460557e-02 + -1.0326427100e-02 + -7.8969877641e-02 + 1.7468864258e-02 + -5.2954453777e-02 + 7.2201670999e-03 + -5.5115355977e-02 + -5.3126491366e-02 + 2.2787496859e-03 + 5.3284337129e-02 + 6.4988175106e-02 + -2.3578952592e-02 + 4.5987458965e-02 + 5.2797585810e-02 + -2.9494610614e-03 + 4.5457141487e-02 + 5.3190881782e-02 + -5.6791325787e-02 + -1.5166475733e-01 + -2.4201486518e-02 + 1.8354020247e-02 + -3.2637118433e-02 + -2.6199612936e-02 + -4.4591508922e-02 + 4.6854126568e-02 + 1.0559761248e-01 + -4.7026811828e-02 + -1.4018160017e-02 + -1.2740007733e-01 + -7.0232938978e-02 + -7.4536711729e-02 + -1.1729533766e-01 + 1.1045670925e-01 + -5.4291901382e-02 + -7.3938000997e-03 + 3.7917628601e-02 + 1.1653478044e-01 + -4.8475082903e-02 + 3.7051577013e-02 + 1.0385124517e-01 + -7.5917674370e-02 + -3.6790172864e-02 + -1.3797299307e-01 + -7.5488391144e-02 + 6.9161581172e-02 + 3.1693038711e-02 + 7.1303873776e-05 + -2.3968449190e-02 + -1.5066413091e-03 + -3.3039599668e-02 + 3.9641604721e-02 + 1.2557586463e-02 + -2.0767152965e-02 + -2.7267264159e-02 + 9.6602422247e-03 + 1.6600210210e-02 + -5.0833905049e-02 + 3.4197792952e-02 + -2.4456900928e-02 + -8.8923471674e-03 + -1.3650395405e-02 + -4.0523474544e-02 + 8.1045562826e-02 + 6.2683851063e-02 + 1.4009993378e-02 + -4.6299623771e-03 + -6.7173988900e-03 + 1.0409272054e-01 + -8.1672476215e-02 + -1.9228470080e-02 + -1.7066570272e-02 + 1.6223373311e-01 + 4.0755866129e-02 + 6.4926388415e-02 + -6.7730395191e-02 + -2.7627742895e-03 + -8.9003836382e-02 + -1.0001376252e-01 + 2.3996796239e-02 + 4.7235961942e-02 + -7.9442754297e-02 + -1.1884660212e-01 + -4.3307118623e-02 + -3.0226229479e-02 + 3.5250320454e-02 + 2.3185468957e-01 + 6.4355224371e-03 + -6.3737431821e-02 + 1.3780374153e-01 + 1.4018591300e-01 + -9.4489465061e-02 + -9.8418266738e-02 + 3.8774395793e-02 + -1.6137521852e-01 + 1.4141430729e-01 + 1.2234053613e-01 + -1.1571656551e-01 + -1.2469365068e-01 + -3.3076002755e-03 + 7.7463328314e-02 + 7.9731935198e-02 + -3.5550186848e-02 + 6.1280446338e-02 + 1.1385298287e-02 + 1.2716277505e-01 + -8.3927242915e-02 + 2.4544683907e-02 + -1.7270590672e-01 + 1.2711228434e-01 + -7.0928253990e-02 + 2.7554964021e-02 + 2.4062668027e-02 + 1.2482349142e-01 + 1.5086961781e-01 + -3.2401427753e-02 + 2.7604452755e-02 + 1.4916924947e-01 + -3.2017198751e-02 + -6.5786294592e-02 + -1.9137337164e-02 + -1.6989467438e-02 + -8.8031564422e-04 + 2.5293281710e-02 + -4.3447156992e-02 + 6.2602673542e-02 + -9.9852142617e-03 + 1.6699096157e-01 + -4.0546941422e-02 + 4.2217889335e-02 + -1.4733364048e-04 + -5.1052764951e-03 + -6.2375728941e-02 + 5.3193006652e-02 + -1.1735426202e-01 + -2.0950132291e-02 + -4.0660024915e-02 + -1.3332630849e-03 + 6.5838067546e-02 + -9.7297604923e-02 + 1.6258720561e-01 + 8.7031825844e-02 + -6.5761920804e-04 + 2.6216706042e-02 + 1.5442303212e-02 + -5.2362202835e-02 + -1.8765893878e-02 + 8.3824999020e-03 + 3.8401415305e-02 + 1.2242257098e-01 + 1.2599570423e-01 + -7.6769245324e-02 + -1.9569514410e-03 + 1.8723222214e-01 + 1.0534802849e-02 + 9.4900529823e-02 + -3.0462265560e-02 + -3.8536930683e-02 + -1.7147130856e-01 + -1.3000115184e-01 + 6.6160567787e-02 + 1.9379825312e-01 + -9.8580792075e-02 + 3.0019023725e-02 + 2.7316430227e-02 + 3.4772190496e-03 + 3.2489880044e-02 + -6.1085726094e-02 + -1.1070622329e-01 + -2.8849232186e-02 + -3.1945374700e-02 + 4.7039245781e-02 + 2.6181632626e-02 + 1.0427565464e-01 + -5.2596864378e-03 + 4.4481772318e-02 + -1.2876089068e-02 + -7.7424542139e-02 + -1.2158126636e-01 + 6.3790833681e-02 + 4.2592664490e-02 + 7.3966156306e-02 + -2.1301284071e-03 + 4.1563701328e-02 + 7.2025309387e-02 + -2.8303255127e-02 + 4.7044684008e-02 + -5.7744687588e-02 + 8.8679469860e-02 + -4.7446678842e-02 + 6.1351586934e-03 + -8.1792541156e-02 + 7.2963387300e-02 + -3.4053908967e-02 + 2.2134471728e-02 + 6.4655920105e-02 + 4.1923112394e-03 + 3.1831597898e-02 + 6.2762667019e-02 + -2.4000584639e-02 + 6.3095349849e-02 + -8.3105531046e-02 + 5.4188339603e-03 + -2.3844448893e-01 + 1.8973561256e-02 + -7.1378128391e-02 + -2.9958865430e-01 + 1.1702623820e-03 + 8.0606563256e-02 + -1.6319037364e-02 + 5.3935402730e-03 + -2.6954885339e-02 + 4.7404881782e-02 + 1.3170025149e-01 + -3.3967488601e-02 + -7.3907556518e-02 + -3.6407070793e-02 + 4.0506446899e-02 + 4.0214038377e-02 + 4.6791250435e-02 + -7.0406806120e-04 + 1.9180242667e-02 + 2.4071216130e-02 + -7.6273328293e-02 + -7.8671560570e-02 + 2.0051302700e-02 + 1.0972786630e-01 + -3.1947567679e-02 + 6.5948625531e-02 + 1.4626626332e-01 + 1.1623812158e-01 + 6.4266951139e-02 + -4.7776837509e-02 + -1.0368104835e-01 + -6.5086780229e-03 + 1.4743473754e-01 + 1.2514940631e-01 + 5.3835061133e-02 + -2.1660198187e-02 + 7.5969191708e-02 + 1.0764889542e-02 + 5.5725760151e-02 + 6.9910894949e-02 + -3.8048652903e-03 + 3.9665164305e-02 + -1.7752472795e-02 + -9.9921488485e-02 + 1.5598642637e-02 + 9.2752166902e-02 + -2.8027096528e-02 + -4.1923832157e-02 + -1.5440703282e-02 + -1.3691589331e-02 + 5.9728138425e-02 + -1.5167080372e-01 + -6.9788843404e-02 + -1.2683390526e-01 + 8.9597676756e-02 + -1.2753681062e-01 + -1.5105738254e-01 + -7.9869696748e-02 + 2.9621868827e-02 + -6.2645293492e-02 + -1.8254063903e-01 + 1.8255087626e-01 + -9.5134456173e-02 + 5.1191807365e-02 + -9.6960728238e-02 + 4.2793761375e-04 + 7.5117237882e-02 + 4.8278167238e-02 + -4.6371112616e-02 + -1.0394805436e-02 + 7.1240413259e-02 + 2.2758740794e-02 + -5.2561434473e-02 + 5.6157873085e-02 + -1.3866589392e-01 + 1.4214252463e-02 + 8.4442339126e-02 + -1.2102749397e-01 + 4.8848890264e-02 + -1.1210435302e-01 + -1.4449837164e-01 + -2.9943673491e-02 + -1.7055924524e-02 + 1.0564708835e-01 + 2.4362963935e-02 + -2.0702176366e-02 + -8.4508643334e-02 + 5.4905145175e-02 + 1.6322077145e-02 + -7.4518078859e-02 + 4.2517637889e-04 + -1.5393698412e-02 + -1.7251282509e-02 + 1.8207276905e-03 + 5.6884448714e-02 + -1.1245464326e-01 + -9.5801624459e-02 + 6.4362160301e-02 + -7.9211239747e-02 + 7.5541791105e-02 + 1.2687114939e-01 + -5.3526137177e-02 + 8.2560617640e-02 + 2.8340112234e-02 + -1.4478301521e-01 + 1.3008791911e-01 + 1.2973018936e-01 + -1.3003256736e-02 + 6.1113933243e-02 + -1.0519191566e-02 + 1.5235217504e-01 + -4.3930211162e-02 + 2.2594059027e-02 + 1.1762147329e-01 + -8.3856124823e-02 + -6.7803495839e-02 + 8.2775099115e-02 + 4.8532727403e-02 + -2.6815132849e-01 + -8.0743882787e-04 + 1.2716562960e-02 + 2.6091908311e-02 + 4.7527852392e-02 + 1.7664124686e-02 + -2.5134510747e-02 + 1.7588924184e-02 + 5.4733510959e-03 + 8.3072541415e-02 + 6.0129116112e-02 + 8.1640704398e-02 + 6.0991792142e-02 + 9.4408928776e-02 + 1.3005610707e-01 + -3.4508384470e-02 + -9.5476120393e-02 + -4.3161342662e-02 + -1.9515439460e-01 + -2.6476539089e-02 + -3.2749516874e-02 + -1.1344136982e-01 + -8.7767838538e-02 + -1.3532552214e-01 + 5.7496798937e-02 + 7.2317957624e-03 + -2.2179041410e-02 + -5.6134975856e-02 + 1.2025200452e-02 + -1.0818043213e-02 + 8.8447170859e-02 + -2.0552991007e-02 + -1.2132175891e-01 + -4.4134428676e-02 + 1.4208342851e-01 + 9.2332776646e-02 + 8.2489542584e-04 + -2.6267221606e-02 + -6.9484402036e-02 + -1.0258496029e-01 + 4.4567141597e-02 + 5.7463229522e-02 + 9.9129856804e-02 + 2.9364978741e-02 + 1.0579661279e-01 + -2.1821906892e-02 + -6.8647376214e-02 + 1.5607251521e-02 + 7.5208012584e-02 + 1.2148887780e-01 + 1.0966954478e-01 + -1.4534179077e-02 + 4.0788160658e-03 + -1.2339986967e-01 + 2.7940658420e-03 + 3.0998117471e-02 + 3.6874950732e-02 + 4.6239611933e-02 + 5.3977411958e-02 + -4.2931981799e-02 + -1.0312510610e-01 + -1.0084908895e-01 + -9.7415718897e-02 + -8.8093075800e-02 + 4.9614385370e-02 + -1.7570432083e-02 + 3.1146892338e-02 + -6.6122622620e-03 + 1.1419031714e-01 + -1.2442753072e-01 + 1.9860682378e-01 + 3.7529538349e-02 + 3.5734860310e-03 + 5.3780682685e-02 + -3.5745786128e-02 + 7.5926795340e-02 + -4.3784576685e-02 + 1.5904125769e-02 + -3.5479019269e-02 + -1.6131425897e-02 + 5.5844745877e-02 + -1.1854907523e-01 + -2.4129255484e-02 + 3.5002048927e-02 + 1.6190823568e-01 + -4.7605375870e-02 + -9.9701267833e-02 + -2.1607330549e-02 + 1.5999875690e-01 + -5.0948956391e-02 + -2.0099240096e-02 + 1.5869039108e-02 + 2.0803683722e-01 + 3.9767302603e-02 + 7.3974377776e-03 + 7.2499632370e-02 + -2.4018814553e-02 + -6.2468923670e-02 + -7.3660570463e-03 + 6.1928410515e-02 + -9.9250352226e-03 + -5.2165242773e-02 + 6.5438170941e-03 + -1.1902554611e-02 + 1.6174552362e-01 + -1.0027859049e-01 + 9.6188562258e-02 + -7.1471862657e-02 + -5.3539169941e-03 + -3.7975025309e-02 + -7.7677847602e-02 + -1.5605980266e-01 + -1.2559539183e-01 + 3.2119789442e-02 + 1.9532439622e-01 + 3.9360156703e-02 + 1.3737401890e-01 + -1.8611622636e-01 + 1.7925306693e-01 + 1.4691376501e-02 + 9.8607241504e-03 + 1.1539035444e-02 + 1.2471348859e-01 + 1.9211452587e-02 + -5.5551591192e-02 + -1.4442067535e-01 + 1.4296609796e-02 + 1.1648498352e-01 + -2.4251995648e-02 + 5.5378583234e-02 + 1.3146707118e-01 + -1.5688802303e-01 + 6.8229912821e-02 + 1.1664838780e-01 + 2.3313892843e-02 + 9.0616057874e-02 + 1.2718200370e-02 + -1.7032003614e-02 + 3.5947242987e-02 + -1.4743463141e-02 + 6.0372940517e-02 + 5.9381196177e-02 + 2.9692294861e-02 + -2.7634310895e-02 + 1.5965663328e-02 + -7.8909043585e-02 + -7.1110411097e-02 + -7.1113348663e-02 + -5.0389853483e-02 + -1.7981489924e-02 + -1.1344235625e-01 + -1.3745869180e-02 + -1.0227076344e-01 + 3.8803013747e-02 + 1.3120908420e-02 + -6.2514892550e-02 + 8.5356788441e-02 + 2.7413187524e-02 + -1.7353975053e-02 + 7.6256949558e-02 + 4.8523723733e-02 + 6.6599333723e-02 + -7.1920755325e-02 + 7.7172941254e-02 + 7.9914827201e-02 + 5.4234671053e-02 + -9.6662749748e-03 + 3.1071752108e-02 + -1.6051668620e-01 + 4.5058032938e-02 + -7.3085964101e-02 + -7.5745384775e-02 + 2.3882492482e-02 + 6.3901537064e-02 + 2.4684391940e-02 + 3.4621173213e-02 + -3.9492300611e-02 + 8.3641347380e-03 + -1.4636637336e-01 + 1.4858195053e-01 + 2.4933380467e-02 + 1.6631818534e-01 + -6.4345938051e-02 + 1.0657689074e-03 + 6.1728861009e-02 + 2.2576597629e-02 + -2.1700888754e-02 + -1.8948960042e-02 + -9.0436502675e-02 + 4.8433518192e-02 + -1.5333429354e-01 + -1.0382089927e-02 + 2.6116742157e-02 + 6.9707194404e-03 + 1.1319243932e-01 + -3.0775371453e-02 + 4.3435119578e-02 + 2.1995128938e-02 + -4.0718927672e-02 + 5.4587950854e-02 + -4.1036171480e-02 + -1.3247414579e-01 + -3.3865437753e-03 + -6.6649207464e-02 + 6.9288822784e-03 + -3.8611675014e-02 + -1.4826775605e-01 + -1.6540048393e-02 + -1.9173772566e-01 + 1.4592959237e-04 + 2.4761358378e-02 + 2.0144014386e-03 + -4.4337137033e-03 + -1.9435562660e-02 + -2.9544340052e-02 + -7.9816132322e-02 + -5.1062987418e-02 + -9.8439072597e-03 + -3.2886283470e-02 + 6.5882342358e-03 + 2.4344467686e-03 + -1.5554759346e-01 + 4.3693431829e-02 + -5.1717393524e-03 + 2.3906317992e-02 + -7.6164001472e-02 + 1.6711957134e-02 + -9.1277972143e-03 + -1.2273631133e-02 + 4.1989535502e-02 + 8.0176990727e-03 + 7.4084242287e-02 + -2.6150602013e-02 + -8.9978454454e-02 + 4.6748826217e-02 + -3.6566382145e-02 + -4.6636753225e-02 + -4.4359179346e-02 + 4.5455280788e-04 + 1.1847348249e-01 + 7.9301983670e-02 + 4.2155989614e-02 + -3.9844542796e-02 + -6.6296182564e-02 + -1.0031759433e-01 + -1.9112946123e-01 + 7.6525720394e-02 + -5.3131325643e-02 + -8.4347756753e-02 + -2.2598810804e-01 + 6.0316886291e-02 + -6.3206057362e-02 + 3.3478526064e-02 + -7.2505289292e-03 + 6.5498739163e-03 + -5.8664856469e-03 + 1.9571489746e-03 + 5.9442072592e-02 + -3.1016897643e-02 + -7.8430075522e-02 + -8.1544405145e-02 + -1.3106386512e-01 + 4.0110624316e-02 + 1.9290587776e-02 + 1.3113121140e-01 + -1.3054645887e-01 + 3.2987082789e-02 + 1.1142196717e-01 + -5.6389868196e-02 + 1.0139111432e-01 + -2.3542678774e-02 + -7.4545886340e-02 + 6.5071462784e-03 + -3.4901636092e-02 + -3.4932168729e-02 + -8.3611563260e-02 + 3.2824309340e-02 + -9.5455294032e-02 + -1.2069499880e-01 + 6.4147334655e-02 + 6.2771286691e-02 + -7.2839622594e-03 + -1.9844535462e-02 + -8.8266212073e-02 + 6.7696262820e-02 + 2.7091370935e-02 + 1.2392696954e-02 + 5.2637895602e-02 + -7.6501168837e-03 + 3.2000271530e-02 + -5.1483232862e-02 + -5.3429322977e-02 + -3.2225627401e-02 + 3.1985430490e-02 + -1.0957389791e-01 + -5.3837211816e-02 + 4.8696180283e-03 + -1.2551936822e-01 + -6.0252970743e-02 + 9.2915032496e-02 + -7.8689755843e-02 + 4.8300132827e-02 + -4.0357659874e-02 + -8.7203025018e-02 + -7.4004458370e-02 + -3.0575661845e-02 + 1.6696110401e-01 + -6.6102406931e-02 + -6.1315011403e-02 + -7.7302712415e-02 + 4.7386523337e-02 + 7.5490830074e-02 + 9.9513035319e-03 + 2.5235786579e-02 + 6.5396122542e-02 + 1.3433435866e-01 + -4.0518900219e-02 + 3.5023999029e-02 + -8.5957038316e-02 + 4.1709244145e-03 + 1.9721381286e-02 + 2.7080735224e-02 + -3.3247767440e-02 + -8.9475299399e-02 + 4.7278887457e-02 + -1.0756192434e-01 + -7.2483720236e-03 + -7.4623119152e-02 + 1.0701014129e-02 + 8.9337272458e-03 + -1.3181470493e-01 + 8.0840226443e-02 + -2.7087158242e-02 + 1.8853990288e-02 + -3.5205967038e-02 + 2.0642263395e-02 + -1.1365647720e-01 + 7.5509089199e-03 + 1.2820050318e-01 + 1.9377350343e-02 + 4.7265543585e-02 + -4.9347285682e-02 + 8.0670293171e-02 + 2.1332723729e-02 + 5.4403976880e-03 + -4.8641197005e-02 + 2.3962641146e-02 + 1.9180127613e-02 + -1.1035233993e-01 + 7.5390789480e-02 + -1.0532697368e-01 + -7.1728864111e-02 + -3.1525860197e-03 + -4.8884136738e-02 + -3.5722856532e-02 + 2.5718988448e-03 + 5.4414430700e-02 + -1.7538744691e-02 + 8.5442532569e-02 + 1.7827058137e-01 + 6.2719082672e-02 + -4.8637885600e-02 + 1.8213282908e-01 + -7.1251098245e-02 + 3.9416050521e-02 + 5.2761542295e-02 + 1.2161698000e-02 + 4.0127189490e-02 + 3.2745605446e-02 + 1.1108805418e-01 + -5.7371173863e-02 + -9.1233156728e-02 + 9.8124223884e-03 + -8.9007684351e-02 + -2.0127491569e-02 + -8.5418516385e-02 + 5.9184871726e-02 + -7.8363692961e-02 + 8.5274152556e-02 + 2.1335358236e-02 + 2.0894702115e-03 + -2.2736018341e-04 + -5.9877794845e-02 + -6.2572948495e-02 + -1.0917600162e-01 + 4.4223799419e-02 + 1.5734422555e-01 + -1.6277235850e-02 + 3.3362088937e-02 + 9.4651983338e-03 + 7.1953784501e-02 + -4.1875811198e-02 + 5.4867955764e-02 + -1.5559538466e-02 + 1.3943743189e-02 + 5.3433452114e-03 + -1.8678071888e-02 + 1.3356845024e-01 + 6.4615021299e-02 + 3.7102886995e-02 + 5.3073518737e-02 + -8.7727760524e-02 + 6.5655615157e-03 + 1.8254466398e-02 + -1.9858576062e-02 + -3.2909717615e-02 + -5.3312217701e-02 + -3.6277382934e-02 + -4.1353482096e-02 + 5.9142702179e-03 + -5.5349902656e-02 + 1.5309043478e-02 + -1.5459531481e-02 + -7.8457054866e-02 + -6.4872794781e-02 + 2.6160300029e-02 + 3.0457851655e-02 + -1.0972074965e-01 + -1.7957962919e-02 + -6.2718887706e-02 + -1.1857336027e-01 + 9.4837406828e-02 + 8.3325780409e-02 + -7.2276571890e-02 + 7.9074940034e-02 + -3.9599395933e-02 + 8.7137336067e-02 + 9.2465996395e-02 + 5.2890178833e-02 + -1.3838778861e-01 + -2.2814288643e-02 + 8.1958238654e-02 + -1.9756522289e-03 + -1.5450671137e-01 + -5.8284251590e-02 + 4.6505791176e-04 + 1.0917972829e-01 + 3.5377496229e-04 + 1.0233832557e-01 + 5.4048962565e-02 + 9.0916996128e-02 + 8.1436607415e-02 + 4.1161246860e-02 + -4.5005493104e-02 + -1.7536838132e-01 + 1.0466105925e-01 + -1.1404324599e-01 + 4.3689277949e-03 + -5.9762374178e-02 + 1.4119880005e-01 + 3.0799398599e-02 + -3.6379326004e-02 + -1.9322159787e-03 + 1.8812434175e-02 + 7.4954783240e-02 + 1.7368072021e-01 + -2.8293365314e-02 + -2.6438525716e-03 + 1.1356829439e-01 + -2.1434915048e-02 + -8.3511387324e-02 + 1.2526018062e-01 + -6.1205368276e-02 + 4.5102643978e-02 + 4.0578481618e-02 + 6.1431020766e-02 + -3.3043017812e-01 + 8.6185812117e-02 + -7.2764429105e-02 + -2.9399483247e-02 + -4.3762812098e-02 + 2.3440076516e-02 + -1.0314036501e-01 + -7.2850046819e-02 + -1.7676978236e-02 + -6.5142247073e-02 + 5.5438027560e-03 + 1.5596118198e-01 + 1.2931995577e-01 + 1.4979873158e-01 + -7.9647766611e-02 + -3.9015852931e-03 + 4.3712879322e-02 + -8.2910277594e-02 + -1.4330585503e-01 + -1.8066349357e-02 + 1.0100858141e-01 + 3.1252162843e-02 + 2.8630383093e-02 + -4.7674518642e-02 + 2.3265811956e-02 + 4.8671288549e-04 + -5.9420012976e-02 + 1.3471172414e-01 + 6.5006166143e-02 + 2.2573728375e-03 + -2.5699059429e-02 + -6.4749765533e-02 + 9.1143861082e-03 + -5.6547674805e-02 + 9.8690346079e-02 + 5.6862884663e-02 + 5.5931057584e-02 + -1.3129615442e-02 + 1.2358865466e-01 + 1.6951163269e-01 + 1.4019002234e-02 + -6.3319475293e-02 + -1.3423261410e-01 + 9.4438753839e-02 + -2.8022756672e-02 + 5.2121531479e-02 + 2.9601234321e-02 + -3.4484456960e-02 + 1.2761079880e-01 + 7.0732553246e-02 + -1.0787644674e-01 + -9.4005833161e-02 + 6.3711211135e-03 + 7.7492081908e-02 + -7.8753582115e-02 + 6.8399769114e-02 + -8.3678333017e-02 + 6.7832028541e-02 + -8.8874889564e-02 + -8.7210351483e-02 + 8.1657989653e-02 + -6.6186484856e-02 + 1.5258139090e-01 + 7.7768586624e-02 + -1.1216697975e-01 + -5.3906638635e-02 + 5.8314852109e-03 + 7.1031542219e-03 + 4.6860626555e-02 + -5.7113790503e-02 + 2.6339818025e-02 + 7.4324356171e-02 + 4.5733442289e-02 + -7.1703495242e-02 + -1.2401440990e-02 + -6.4512959272e-02 + 1.2417049589e-01 + -8.7006855616e-02 + 9.8936334996e-02 + 1.2156727404e-02 + -4.3177616543e-02 + 1.8623843813e-02 + 5.9499615671e-02 + -5.6795639648e-02 + 6.6630926099e-03 + -3.3765716264e-02 + 5.8242795738e-02 + 4.2510408664e-03 + -1.8953131059e-01 + -4.3750537828e-02 + 1.4275232369e-01 + 1.3355016825e-01 + -2.4034276632e-02 + -2.8587674545e-02 + -5.1856464271e-02 + 3.8475765894e-03 + 4.2032508852e-02 + -6.8140408680e-02 + 5.1404444295e-02 + 3.7639621685e-03 + -2.7495504555e-02 + 3.2975544451e-02 + 7.1503425487e-02 + 1.0717405843e-01 + 7.1411579190e-03 + 1.7903979466e-02 + -2.4849911692e-02 + 8.6155996361e-02 + 1.1605106771e-01 + 9.1426332850e-03 + 3.4740749871e-02 + -7.9408891575e-02 + 2.1670207410e-02 + 5.9953857100e-02 + -2.8759796843e-03 + 8.7331370904e-02 + 1.8671242807e-01 + -2.8902210076e-02 + 7.9934068499e-02 + 2.0726355135e-02 + 5.7622382718e-02 + -2.1787923973e-02 + 2.4931411258e-02 + 3.0225475470e-02 + -5.7740732104e-02 + 1.3312067996e-01 + -4.6115601110e-02 + -7.3698749232e-02 + 1.7574589942e-01 + 3.8634952332e-02 + 4.1971906999e-02 + -2.0406289715e-02 + -1.9137773684e-02 + 1.2161720745e-01 + 5.6414640001e-02 + 5.7539783252e-02 + 3.0178453388e-02 + 8.9327699839e-02 + 5.5440325212e-02 + 5.6531771061e-02 + 6.0503009225e-02 + 3.1767722347e-02 + -5.5570716943e-02 + -1.2097965065e-03 + 4.0808237078e-02 + -1.0680016276e-01 + 2.4880290097e-02 + 3.4066411208e-02 + 3.8774203266e-02 + 8.8245472713e-02 + -1.0001049562e-01 + -6.1775315114e-02 + 2.7343867623e-02 + -1.1548212657e-01 + -6.7026681019e-02 + 1.1277256743e-02 + 2.4967343140e-02 + 1.6524574967e-01 + 6.2315863356e-02 + 6.2728954944e-02 + -4.4430024742e-02 + -2.7569014931e-02 + -2.6236869155e-02 + -7.4648964366e-02 + -1.2271540394e-01 + 2.0590852334e-02 + 1.2600529570e-01 + 2.7034927505e-02 + -1.0223410563e-01 + 1.0033754582e-01 + 3.2410202344e-02 + 8.0013561066e-02 + 7.7081206997e-02 + 6.8672917433e-02 + -9.0929013085e-02 + -6.6462896635e-02 + 7.0028731513e-02 + 4.1926477062e-02 + -2.7843817811e-03 + 1.1492784002e-01 + -1.3330057295e-01 + -7.7442063725e-02 + 1.7078772442e-01 + -1.6444645362e-01 + -3.6895259594e-02 + -1.7092637174e-02 + -1.1592226897e-02 + -6.1563248437e-03 + -1.4268320581e-03 + 1.8600925524e-02 + 1.3795081665e-02 + 4.6586693583e-02 + -1.1374516686e-02 + -8.6658782275e-02 + 1.0682060806e-01 + -2.5196725894e-02 + 4.4351515691e-02 + 4.0298272766e-02 + 6.2212486818e-02 + -6.8577037791e-02 + 7.5146127048e-02 + -9.2629355239e-02 + 7.5765985641e-02 + -4.3388049123e-02 + 8.8991921540e-02 + -3.6237540317e-02 + -1.9490742166e-03 + 1.3095834153e-01 + -2.6139013552e-02 + -3.9610623238e-02 + -1.2629568658e-01 + 1.1838471055e-01 + -4.6920335608e-02 + -2.3682050225e-01 + 1.1947066339e-01 + -1.0784982921e-01 + 1.4056899768e-01 + -3.4390659876e-04 + -2.0596756970e-02 + -6.9075219257e-02 + 5.8634783264e-02 + 8.2247402987e-03 + 7.3157285561e-02 + -1.0723534056e-01 + -1.2078919949e-01 + 8.7759593205e-03 + -1.8319990410e-02 + 1.9597979646e-01 + 7.2620890681e-02 + 3.0272229691e-02 + -5.3052626770e-02 + -4.9733870908e-02 + -3.0865860894e-03 + -8.0943996534e-02 + 1.6791530741e-02 + -1.6489661705e-02 + 8.0600448411e-02 + 3.3558177432e-03 + 2.3166386861e-02 + -6.7789414466e-02 + -1.3953243623e-01 + 4.9248046295e-02 + -1.3260773803e-01 + 2.1154841802e-02 + 6.4801288956e-02 + -1.1707666404e-01 + -4.0171273191e-02 + 3.9119451603e-02 + -1.6073808217e-01 + 5.7547374235e-02 + -2.2441717018e-02 + -2.9296130845e-02 + 2.6332006713e-02 + -4.0539368532e-02 + -4.4322248348e-02 + -1.5250906989e-01 + -3.7835002164e-02 + -2.2632512497e-03 + -3.6608227905e-02 + -1.0190924811e-01 + -2.1268254299e-02 + 5.3991617562e-02 + -4.2111666776e-02 + 1.1475491010e-01 + 9.3880038754e-02 + -5.7440296426e-02 + 7.2979192573e-02 + 1.9638774769e-01 + 9.2873173308e-03 + 3.2068138085e-02 + -8.4704972266e-02 + 1.6473345500e-02 + 3.8231804217e-02 + 1.1631841352e-01 + -5.0737864684e-03 + -1.7694066973e-01 + 1.1718608820e-01 + -4.4821229171e-02 + 3.5443444787e-03 + -5.9969133127e-02 + 5.8760754847e-02 + -1.9784752759e-01 + 2.7668382909e-02 + -8.8561808857e-02 + -1.2227755819e-01 + -1.1062700077e-01 + 2.7445416960e-02 + 1.5774241962e-02 + 7.7551829909e-02 + 1.0749336817e-02 + -1.5524224729e-01 + -6.6134561698e-03 + -9.4785703015e-02 + -1.1408995599e-02 + 3.6325364595e-02 + -2.3298014873e-02 + 1.3965501814e-01 + -8.9864951891e-02 + -1.2476750608e-02 + -6.9525515204e-02 + -2.0201700278e-03 + -1.1548445555e-02 + 7.9305954389e-03 + -5.6864893259e-02 + 7.1292964602e-04 + -9.9718126305e-02 + 1.4267805735e-01 + -6.1795509543e-02 + 7.5099563320e-02 + -7.0663431660e-02 + 1.1008479676e-01 + -1.8490957931e-01 + 1.6388200018e-01 + -9.1847686127e-02 + 4.2718539213e-02 + -1.2231814637e-01 + -1.2090248792e-01 + -1.7523874502e-01 + 4.7004080098e-03 + -1.3769598696e-01 + 3.1772486017e-02 + -1.5235849448e-02 + -1.2736675625e-01 + 1.0648388875e-01 + 3.7131033184e-02 + -2.6216919306e-02 + 1.2078560072e-01 + 8.5639809634e-03 + 4.9157626633e-02 + 2.8753236753e-02 + 4.6353958568e-02 + -5.5011500834e-02 + 2.8066823885e-02 + -6.0178878196e-03 + -6.5431569406e-02 + 7.2173604151e-02 + 7.8875963420e-02 + -8.6316264153e-02 + 1.6743992446e-01 + 6.4906953369e-02 + -1.1383750356e-01 + 9.0993985670e-02 + -8.8824558926e-02 + 5.0705656488e-02 + -3.2887560760e-02 + -4.2181810860e-03 + 1.1337655183e-01 + -9.0609136166e-02 + 5.8689118392e-02 + -5.3185743606e-02 + 2.5635702076e-01 + -1.5237085718e-02 + 4.6753196683e-02 + -8.6048836676e-02 + 3.9636943054e-03 + 1.4105459115e-01 + 2.7155677829e-02 + -4.6085459356e-02 + 1.0256990694e-01 + 7.4007000536e-02 + -6.9363032414e-02 + -1.7081963715e-01 + -1.3500350261e-01 + -1.0000300443e-01 + 2.5363893616e-02 + -6.9035058315e-02 + -1.0082568362e-03 + -1.1235618866e-01 + 6.6365414155e-02 + -4.1297151588e-02 + 7.7298512335e-02 + -1.1160354590e-01 + 2.9568815127e-02 + 4.7739118985e-02 + 1.6778819720e-01 + -8.3044635231e-02 + 4.8099909485e-02 + 1.3099863811e-01 + -9.8066064076e-02 + -7.6826369813e-02 + -5.8172314958e-02 + -6.2525541890e-02 + -1.7374689095e-01 + -4.5721302761e-02 + -7.0214983493e-02 + -3.8950023688e-02 + 6.5990608274e-02 + -1.1679795710e-01 + -2.5974776612e-03 + 3.0023625157e-02 + 1.6030977638e-02 + 4.7813995667e-02 + 2.3374219736e-02 + -6.4168311492e-02 + 6.6902772469e-02 + -5.9278037484e-03 + -1.7583360447e-01 + 2.5330434265e-03 + 9.6006134472e-02 + 1.0624361271e-01 + -2.5251815023e-02 + 3.3933602289e-02 + -7.0924796553e-02 + -1.3664933700e-01 + 3.2262860205e-02 + 1.2678598050e-02 + 8.7236100436e-02 + -1.7451611517e-02 + 2.8598629270e-03 + -1.2739822392e-01 + -6.1232688856e-02 + 6.9337857493e-02 + 4.6946952196e-02 + 2.2608692568e-02 + -1.1517479765e-01 + 5.8941781176e-02 + 1.2252424503e-01 + 1.5834125219e-01 + 2.8512611809e-02 + 2.2219707989e-02 + -6.1018042732e-02 + -3.9181205037e-02 + 5.8232854299e-02 + 5.9626420016e-02 + 7.3421578703e-02 + 3.8376356125e-02 + 4.8651333922e-02 + -6.4189096360e-02 + 5.1157548168e-02 + 4.3421416597e-02 + -5.3626270606e-04 + -1.0985571408e-03 + 3.1153640618e-02 + -7.7757731014e-03 + -1.5647721465e-01 + -9.7348452168e-02 + -2.3192022825e-01 + -8.5034086850e-02 + 8.8653894647e-02 + 1.0021415914e-01 + -1.2319663503e-02 + 1.0811776361e-01 + -4.9937958342e-02 + -2.6490006714e-02 + 9.1902542386e-02 + -9.5848964899e-02 + -6.6866560769e-03 + -8.4405719073e-02 + 3.4898952473e-02 + 2.2873406030e-01 + 2.0588085870e-01 + 6.2437038677e-02 + 1.4788697730e-01 + 8.3533932482e-02 + 8.3020846619e-02 + -4.5385925344e-02 + -8.0284111938e-02 + 4.7858540641e-02 + 3.4867121324e-02 + -2.5556505161e-02 + 4.7544991632e-02 + -9.4357282953e-02 + -5.0982399939e-02 + -2.8297538471e-02 + 1.4215016282e-02 + 7.8966127771e-02 + 1.4510525399e-02 + 5.2994631696e-02 + -2.7212669009e-02 + -9.1364782883e-04 + -2.4578711318e-02 + 9.7346156257e-02 + -2.3838505062e-03 + -1.7780311919e-01 + -3.6878577564e-03 + -1.0015627416e-01 + -1.2538166947e-01 + -1.1590996204e-01 + -8.6721098295e-02 + -2.2397466122e-02 + 4.8457424738e-02 + -6.4382233405e-02 + -1.1286846287e-01 + -2.1902053353e-02 + -2.9426752461e-03 + -6.4704884435e-02 + -3.0907335080e-02 + 8.0132340680e-02 + -9.8683882072e-02 + -1.3433495929e-01 + 2.1658406605e-03 + -1.2219984655e-02 + 2.0113531533e-02 + 7.3589266013e-02 + -1.5985897713e-02 + -1.5446857087e-01 + 4.6142035787e-02 + 4.9107419044e-02 + -1.6294061340e-02 + -6.8941220965e-02 + 4.8427397947e-03 + -1.3835656480e-02 + -2.5191686390e-02 + 1.1444275445e-01 + -2.8699751136e-02 + 3.6184935424e-02 + 9.8334379362e-02 + 6.0034241282e-02 + -6.7747890162e-02 + 1.1859226664e-01 + 1.7550369027e-01 + 1.8192013654e-01 + -4.1695184674e-02 + -1.3292372451e-01 + -1.4687077642e-01 + -1.8337001253e-01 + -4.4888941922e-02 + -1.0469726164e-01 + 3.3802275811e-02 + 8.1935160417e-03 + 9.5395847142e-02 + 7.6175590675e-02 + 2.1071980485e-02 + -2.6410504472e-02 + 1.1848020118e-02 + 2.4102780004e-02 + -5.0904807611e-02 + -4.6720906593e-02 + 2.0072665539e-01 + 1.0695985281e-01 + -6.6907631322e-02 + -3.9285240787e-02 + -2.9501183919e-02 + -2.9666421788e-02 + 8.7463077175e-02 + 8.8591813920e-03 + -2.6711769590e-02 + 1.9142445681e-02 + -1.6046034869e-02 + 1.6360089010e-01 + -3.3368780084e-02 + 1.5578123681e-01 + -8.3707034695e-04 + 1.5322146648e-01 + 1.9340903700e-02 + 2.3332233878e-02 + 3.9351565088e-02 + 3.8382274867e-02 + -9.2197239352e-03 + -7.6924033557e-02 + -8.8825214047e-02 + 7.2689507467e-02 + 6.4058706841e-02 + -2.4676830493e-02 + 9.5909693519e-02 + -4.7920395339e-02 + 1.8488349941e-02 + 6.8618443632e-02 + 1.1083553715e-01 + 2.5176948182e-02 + 2.3265922263e-02 + -1.3864038757e-01 + -3.6302828861e-02 + 1.4363937059e-01 + -5.0240787997e-02 + 5.5062153473e-02 + -4.2118918576e-02 + 3.6193619041e-02 + -3.4922652366e-02 + -2.6823603466e-02 + -8.5390359831e-02 + 4.0050170481e-03 + 1.4731620308e-02 + 6.2668831332e-02 + 2.5834461527e-02 + 7.0798612274e-02 + 8.7217332449e-02 + -1.2865858041e-01 + -1.3727344336e-01 + -8.0953633009e-02 + 1.5933726658e-01 + -1.3620294040e-01 + 3.9963863608e-02 + 1.5672068937e-02 + 4.9974266755e-02 + -5.7491415612e-02 + 1.1787264976e-02 + 5.5953102281e-02 + 1.2057363019e-01 + -8.2490544607e-02 + 9.8869186221e-03 + -8.0482399349e-02 + -3.6354148129e-02 + -1.8449652889e-01 + -9.2399537960e-02 + 3.5018143503e-02 + -7.5765934033e-02 + -1.2358301674e-02 + 1.3728880090e-02 + 9.5636916700e-02 + 4.4484258904e-03 + -5.4182129537e-02 + -6.9149329594e-02 + 4.2938836663e-02 + -6.5917029824e-02 + 3.3396093696e-02 + -2.0056162036e-02 + -1.1853157342e-02 + -2.0797723454e-02 + -2.0659623904e-01 + 3.5333374584e-02 + -7.6447121680e-02 + 2.0028927807e-03 + -5.3074497312e-02 + 2.2212763888e-02 + 1.0382744601e-01 + -7.7054888279e-02 + -4.8857474057e-02 + 6.9334755399e-02 + 2.9772341348e-02 + 1.6618654225e-01 + 7.3082131649e-02 + 3.4932816441e-02 + 9.2112310206e-02 + 1.0584694250e-01 + -1.4711083576e-02 + -6.4210087134e-02 + -1.0873243864e-01 + -1.4123970198e-02 + 4.3736219546e-02 + 1.0817726153e-01 + -1.8585172486e-02 + -5.4302159289e-03 + 2.3317361006e-02 + -3.4270020784e-02 + -6.3141739224e-02 + -6.3187942033e-02 + -9.4325117683e-02 + 6.7567217316e-02 + 1.3898078193e-01 + -4.6652917045e-03 + -6.4630103127e-02 + 8.1820749238e-02 + -2.5660190560e-02 + -2.0403815858e-02 + -1.2483031463e-01 + 8.2147430676e-02 + -1.3510778736e-01 + 1.3191107742e-01 + -1.1807047392e-01 + 2.3794636752e-02 + -4.1033813489e-04 + 2.8168118851e-02 + 7.0014065480e-02 + 7.9622328503e-02 + 1.0438701775e-02 + -1.4912443811e-02 + -7.0623841314e-02 + 1.3541476830e-02 + -4.2633505779e-02 + 9.8334643287e-02 + -1.1846545263e-01 + 1.2611960151e-01 + -3.5650065395e-02 + -3.7491649580e-02 + 1.5971460719e-02 + -6.8360938169e-02 + -4.5420570462e-02 + -1.1322499334e-02 + 5.9707665589e-02 + -1.2479449766e-01 + 2.1392994239e-02 + 7.1214449661e-02 + 1.2285341238e-01 + -5.0613356499e-02 + 4.6411165642e-02 + 4.1874143955e-02 + -1.1913633944e-01 + -2.5173619671e-02 + -4.6845866466e-02 + -5.1255890871e-02 + -6.3481411277e-02 + -1.3531442286e-01 + -4.1427028909e-02 + 1.2670628501e-01 + 1.0610978786e-01 + 1.0307820065e-01 + -1.4439282689e-01 + -6.9400535054e-02 + -2.5169353753e-03 + 1.7497324086e-01 + -1.0732036233e-01 + -1.3247239827e-01 + -2.6403373073e-02 + 3.7130983984e-02 + 2.3246218534e-02 + 8.3774421699e-02 + 6.4671061166e-03 + 1.7693794937e-03 + -1.2169598217e-02 + -7.8474799788e-03 + -3.6360610493e-02 + -5.6943538141e-02 + 6.2397599499e-02 + -5.5691034720e-02 + 2.9182900964e-02 + -8.7587397477e-03 + -3.4808271016e-02 + 3.5838385327e-02 + 9.7025686168e-02 + 5.0537592889e-03 + -6.8895119916e-04 + 3.1008900592e-02 + 1.3688074012e-01 + -1.2160730097e-01 + 3.8830920899e-02 + -1.6791841180e-02 + 8.2252167422e-02 + -1.3093667364e-01 + -3.9694150434e-02 + 2.0382150930e-02 + 1.7675743486e-03 + -3.3358298235e-02 + 3.0739924397e-02 + 1.6080449570e-01 + -2.4541501686e-02 + 4.4142338497e-02 + -1.4645681551e-01 + 4.1959176445e-02 + -8.0345224265e-02 + 9.5856373181e-03 + 6.8077400667e-02 + 4.1458759042e-02 + -3.4984735880e-03 + -1.2423447585e-01 + 5.4556805488e-02 + 1.2550468479e-01 + 3.5808396432e-02 + -3.6362868088e-02 + 1.7306864087e-02 + 6.4999509672e-03 + -9.2695831898e-02 + -1.3441299281e-02 + 5.7555208611e-02 + -6.4840310468e-02 + -2.2115674730e-02 + 6.3625121939e-02 + 5.5933514111e-02 + 4.4741386017e-02 + 3.2293613639e-02 + -3.6843542376e-02 + -1.0216670027e-01 + -1.0443716080e-01 + -2.9532374059e-02 + -1.2888374559e-02 + 7.6717434799e-02 + -2.8244120584e-02 + 7.0320997247e-02 + 6.3826557330e-02 + -1.4608909851e-02 + -4.8241150177e-02 + -5.8983109044e-02 + -4.9283722315e-02 + 4.2464051788e-02 + 1.0946448046e-03 + 3.7528139271e-02 + 4.0758440767e-02 + -8.0023749581e-02 + 2.5209660280e-02 + -5.5112846290e-02 + 3.1008039449e-02 + 7.2176536780e-02 + -1.2407189083e-01 + -1.8314682264e-02 + 7.2443555772e-02 + -1.2516710240e-01 + 6.4592533642e-02 + -8.1280769693e-02 + 2.0420688856e-01 + -1.7349680812e-01 + 8.7878703740e-02 + 8.4749459089e-02 + -5.9507552437e-02 + -2.5534274861e-02 + 2.7199814520e-01 + -5.4893810766e-02 + 2.4224976695e-02 + 6.9253292137e-02 + 1.1259438604e-03 + -2.6570758966e-01 + 3.8213759719e-02 + 1.0132577595e-01 + 1.4810074707e-01 + 4.9830195601e-02 + 4.2970893181e-02 + -2.9888482469e-02 + -1.3213447842e-01 + 1.1780107987e-02 + -1.9627312823e-01 + -7.1751152252e-02 + -1.4040203599e-01 + -4.2489007895e-03 + 1.7439841821e-02 + -5.6156866641e-02 + -9.8153683087e-03 + 5.5744071902e-02 + 3.1366306948e-02 + 9.1380512075e-02 + -7.4014085899e-02 + 3.7683969517e-02 + -8.5812487973e-02 + 1.5023309943e-01 + 6.3524226159e-02 + -4.2913625162e-02 + -1.0956072873e-01 + 3.8269894863e-02 + 7.2416708744e-02 + 2.7395000755e-02 + -1.1317486088e-01 + -3.6805858353e-02 + 3.3361052551e-02 + -6.8155680665e-02 + -7.1272055313e-02 + -7.7879115378e-02 + -1.0128190350e-01 + 4.0129692781e-02 + -3.4174999274e-02 + -2.6807072744e-02 + -5.5817989762e-02 + -9.1149149061e-02 + -1.1900282623e-01 + 1.0765070383e-02 + -6.0824813992e-02 + 5.7683809234e-02 + -2.4818706423e-02 + -1.9969663041e-02 + 8.2023585608e-02 + 2.7507862274e-02 + -1.0994353782e-01 + 1.4480862328e-01 + 6.4048202808e-02 + 2.4892103691e-01 + 4.0895550488e-02 + -4.0270582974e-02 + 7.6064608171e-02 + -1.2447991014e-01 + 7.4336236023e-02 + 1.0920392728e-01 + -1.1238868436e-01 + -1.2961057435e-01 + -1.3873602657e-01 + 1.1682258019e-02 + 2.9129932880e-02 + -1.7026736164e-02 + -1.3327816598e-01 + 1.6063062277e-01 + -8.3757727531e-02 + 7.9731581196e-02 + 9.5520303506e-02 + 6.0991708558e-02 + 4.8130700169e-02 + 7.5206735857e-02 + -1.2999957521e-01 + 4.3849294715e-02 + -5.3788411669e-02 + -2.1800559296e-02 + 5.2571872575e-02 + -1.3243633883e-01 + -2.3177121025e-02 + 2.3850431782e-02 + 1.2155824661e-01 + 1.2986860069e-01 + 9.9622007022e-02 + -8.8926237474e-02 + -4.3430200791e-02 + -1.1374609575e-01 + -1.1218082146e-01 + 2.3911573157e-02 + -6.3965150282e-02 + 4.0743211427e-02 + -6.6706084848e-03 + -4.4043965596e-02 + 7.1070216678e-02 + 3.5302261085e-02 + 4.7388609724e-02 + -4.5864267445e-02 + -1.5721127848e-02 + -5.8020626486e-02 + 2.4694214985e-02 + -1.8523018221e-02 + 1.3723166014e-01 + 6.9760828378e-02 + 1.8929548053e-02 + 7.1361633212e-02 + -8.0857072493e-02 + -2.0579037917e-02 + -1.4209017831e-01 + -1.0238205654e-01 + -9.2532741626e-03 + 9.7079300919e-02 + 1.7730783961e-02 + 3.1745388132e-02 + -6.5730083016e-02 + -1.0973446943e-03 + -5.9061040172e-02 + -3.0595565480e-02 + -6.0509178775e-02 + -8.9734430309e-02 + -5.2055499098e-02 + 2.5068112985e-02 + 3.5400479578e-03 + 1.4633732663e-01 + 5.9795281637e-02 + -3.3525464665e-03 + 1.0897400593e-02 + 9.7442039981e-03 + -4.5989161610e-02 + -1.0859763644e-01 + -9.5202339351e-02 + -9.8552819060e-02 + 5.7172679406e-02 + 1.4137827201e-01 + 1.3133968818e-01 + 3.2686401045e-02 + 4.9210853225e-02 + 1.0375871296e-03 + -6.2964280905e-02 + 1.3494012220e-01 + -6.1239782746e-02 + -3.3109477377e-02 + -4.1977782453e-02 + 1.0679495277e-01 + -3.9279813121e-03 + -7.1644259419e-02 + 1.4173357853e-02 + -1.0153945128e-01 + 2.4407001991e-02 + -1.1928571150e-01 + 3.5772900639e-03 + -5.7027242726e-02 + 8.4001994947e-02 + -2.7679161871e-02 + 5.8784953008e-02 + 8.2418489819e-02 + 3.0341661328e-02 + 8.5450513080e-03 + 8.3056853983e-02 + -3.5065086713e-03 + -1.7296759130e-02 + 8.2121146515e-02 + -6.1994833444e-02 + 2.4192026562e-02 + 5.2970201573e-02 + -7.5837893107e-02 + -1.5785688029e-01 + 4.5096664189e-04 + 4.3033700671e-02 + -1.3628058060e-01 + 7.3976629384e-02 + 9.4071973940e-02 + 1.3863051184e-01 + 1.0967353186e-01 + 6.7460037788e-03 + -4.9286232445e-02 + -3.6501267284e-03 + -3.7376847150e-02 + 1.1692657156e-01 + 4.4727601324e-02 + -1.0505236679e-01 + 9.7769716249e-02 + -3.5668250190e-02 + 4.0142963535e-02 + 1.3858642609e-02 + 3.5147740175e-02 + -1.5757423534e-01 + 5.4724452177e-02 + 4.0845001830e-02 + 9.6776852091e-03 + -1.1341466084e-01 + 6.7587591160e-02 + -1.0814369792e-01 + 3.0298886289e-02 + 9.2974670157e-02 + -3.0239655226e-03 + -3.6188938581e-02 + -8.1368912283e-02 + 8.8051298683e-02 + 7.2089261599e-02 + 2.7463266918e-03 + -2.5602297243e-02 + -1.3347393844e-01 + 1.1185047901e-01 + -1.9558044720e-02 + -3.1599443273e-02 + 2.3700642143e-01 + 2.9037197035e-02 + -5.6223251521e-03 + 2.1269138327e-02 + -2.7082629441e-02 + -3.7143451039e-02 + 1.3531900255e-02 + 3.3790935051e-03 + 2.4015336536e-01 + 6.1080352090e-02 + 5.4601108527e-02 + 1.1837399769e-01 + -2.6493561044e-02 + 8.2917355143e-02 + -1.0022310778e-01 + 4.0413067145e-03 + -1.2147989024e-02 + 2.1901994049e-02 + -3.3282363576e-02 + 2.4943929548e-02 + 6.2083165716e-02 + 9.3998895220e-02 + -3.5037322648e-03 + 7.5902002311e-02 + 1.0793993495e-02 + -2.4625581138e-02 + -2.4181704160e-02 + -5.1825461366e-02 + 2.1474239871e-01 + -6.0130710385e-02 + -2.0301796170e-02 + 7.4284634968e-02 + 1.3289561493e-01 + -9.3096573089e-02 + 3.4238993971e-03 + -1.4226928356e-02 + -2.0217081099e-02 + -1.2605863982e-01 + -4.3662931298e-04 + 4.8422792948e-02 + 1.8739762760e-01 + -1.2351269244e-02 + -4.3678501414e-02 + 4.6122107718e-02 + 6.5268640469e-02 + -1.4028285226e-02 + 5.6548488805e-02 + 6.4042785934e-02 + 1.2132121688e-01 + 1.0088152291e-02 + -9.6593146227e-02 + -1.7072583042e-02 + -5.0924413180e-03 + 2.7567550352e-02 + -5.7877650893e-02 + 1.5666225684e-03 + -6.4204874656e-02 + 1.3149515500e-01 + 2.7544451441e-02 + -4.4364619750e-02 + 3.1451120068e-02 + 3.8723355205e-02 + 6.0295670670e-02 + 5.6289434567e-02 + -1.1442317058e-01 + -2.3699884954e-02 + 6.1847019538e-08 + 1.4667939185e-01 + -1.5242899175e-01 + 1.1377885131e-01 + -7.9735381804e-02 + -1.6986628839e-02 + -8.6509044312e-02 + -3.1854764194e-02 + 8.6879655511e-02 + -6.4027399793e-02 + -6.7842029196e-02 + 5.9802644488e-04 + -9.0448335421e-02 + 1.3558719005e-03 + -5.8836527886e-02 + -7.6366581234e-02 + 1.8545564365e-02 + -1.2378457123e-01 + 2.7381732288e-02 + 2.6487232466e-02 + -6.8159650987e-02 + 3.8612454032e-03 + -3.3317061867e-03 + -1.5066884443e-01 + -9.0452118787e-04 + 1.1979917810e-01 + 1.3129589297e-01 + -1.7829978632e-02 + 1.9782258173e-01 + -9.3542387257e-02 + 9.7509653368e-02 + 3.4079959235e-02 + 5.0180050005e-02 + -9.8687874128e-02 + -5.9305688281e-02 + -1.0332285617e-01 + 2.3070373345e-02 + 3.5315292298e-02 + -7.9005757845e-02 + -9.0739101708e-02 + -1.0010483188e-01 + 1.2531983514e-01 + 7.1919922943e-02 + -3.6149374657e-02 + -1.6654917101e-01 + -7.7506457397e-03 + 1.3429438202e-01 + 5.1863731290e-02 + -4.4498251868e-02 + 6.7786109668e-02 + -5.4994387626e-02 + 1.7088059216e-03 + 1.1369680219e-02 + 1.7013809907e-02 + -4.7076995317e-02 + 5.4755938781e-02 + 2.1583359310e-02 + 1.6930924828e-01 + 4.4311271715e-03 + 7.9425714450e-02 + 1.2030390008e-01 + 1.5688404029e-01 + -1.4229901483e-01 + 6.3034493864e-03 + 2.6099234519e-02 + 2.8554685301e-02 + 2.4736530643e-02 + 1.3841203728e-01 + -5.0801861325e-02 + 1.0862672988e-01 + -4.0734283043e-03 + -5.8339854460e-02 + -2.0767616327e-02 + -1.1950645504e-02 + -1.7657075139e-01 + -2.1084923320e-02 + -5.6731805272e-02 + 5.6550988269e-02 + -2.0675553135e-01 + -2.3056642216e-02 + -1.2115205746e-01 + 8.9194615001e-02 + -2.0407789838e-02 + 1.9394940163e-02 + 9.5000646946e-02 + -9.5024494924e-02 + -1.1818442354e-01 + 1.1109593719e-01 + -7.0574553132e-02 + -9.9409744578e-02 + -1.2930410261e-01 + 9.4004511609e-02 + 9.5272317804e-02 + -1.0466553040e-01 + -1.1610783841e-01 + -6.1946364881e-02 + 4.9187850001e-02 + -1.2837849618e-01 + 1.4495730392e-01 + -3.3239696599e-02 + 1.3103479744e-01 + 2.0514315048e-02 + -2.9060320134e-02 + 5.3641302504e-02 + -2.7869860613e-02 + 4.9228019518e-03 + -8.6995876557e-02 + -2.6454077704e-02 + -1.4185411346e-02 + 5.1876527708e-02 + 6.9915228377e-03 + 8.3766687774e-02 + -1.2304305233e-01 + -8.4467802500e-02 + -1.0942295139e-01 + 3.1463827029e-02 + -1.2468023852e-01 + -3.5243579026e-02 + 5.0475612367e-02 + -8.4336784797e-03 + 3.4098358820e-02 + 3.6135386079e-02 + -2.2904208259e-01 + -2.8646555726e-03 + 5.4768978127e-02 + -1.2314818196e-01 + 1.7997672888e-02 + -1.8224571568e-03 + 4.3504085933e-02 + 6.2007159908e-02 + -1.2621725686e-01 + -8.2645255854e-02 + 6.4050754268e-02 + -1.1409147625e-01 + 2.3461577437e-02 + -1.4665142553e-01 + -3.2700704061e-02 + 7.3769399041e-02 + -2.1287181772e-01 + -1.1229613383e-01 + -6.2836668426e-02 + -6.9192150059e-02 + -1.7953400966e-02 + 5.4038368477e-02 + 9.5093080265e-02 + 7.1557388663e-02 + -1.2590953043e-01 + -1.7125281351e-02 + -3.7103291014e-02 + 6.5207633840e-02 + 6.0735661583e-02 + 6.0775172818e-02 + 2.2960046941e-01 + 1.2789332947e-01 + -9.9483054702e-02 + 5.9369939698e-02 + 5.4963472440e-03 + -7.3360931756e-02 + -8.8973719250e-02 + -2.8522424203e-02 + -8.5051372214e-02 + 1.0093062132e-02 + -1.1834300331e-02 + -1.5691597457e-02 + 1.9287977288e-02 + -6.9687977005e-02 + -5.2466038483e-02 + -1.0546970434e-01 + -1.1428832971e-02 + 6.0877274359e-02 + 1.9001290381e-02 + 6.0868612046e-02 + 6.8377011479e-02 + -3.7465907926e-03 + 2.0190575399e-01 + 8.4467063545e-02 + 9.7771932355e-02 + 7.7023663870e-02 + 4.2145507872e-02 + -3.6209256840e-02 + -6.5033960711e-02 + 1.5023880019e-02 + 5.7795016194e-02 + 6.6849321397e-02 + 7.5518066882e-02 + 1.0528202687e-01 + -2.3206755261e-01 + -1.8332272769e-01 + -2.3066081218e-02 + -7.4856200237e-02 + 8.2457693443e-02 + -3.2936564230e-03 + 4.2716730073e-02 + -6.1261525902e-02 + 5.8842286171e-02 + -4.2943331167e-02 + 5.1644359903e-02 + -7.9056106716e-02 + 2.8032262746e-02 + 1.7938850922e-02 + -2.1575809500e-02 + -1.7011540209e-01 + 8.8975786989e-02 + -8.1537331442e-02 + 2.5019622064e-02 + -3.5277186854e-02 + 1.2860305212e-01 + -5.9040879950e-02 + -4.2904693401e-02 + -5.3266408712e-02 + 1.1894625592e-01 + -6.6649113339e-02 + 5.0768653081e-03 + -4.5890266089e-02 + 4.0489210460e-02 + 6.0477834594e-02 + 1.4246824173e-01 + -3.8980418833e-02 + 1.3845625231e-01 + -1.1500536543e-01 + -5.6862060036e-02 + -1.1278058818e-01 + -7.2755611522e-03 + -1.5729872141e-01 + 1.0133489334e-02 + 3.4232375004e-02 + 2.0536094180e-02 + 2.1850251595e-02 + 2.1741629547e-02 + -3.5707388318e-02 + 6.8255565514e-02 + -6.1681298006e-02 + 6.7659003208e-02 + -5.8185033134e-03 + -3.6203516007e-02 + 2.0074539841e-02 + -1.1022371740e-01 + 1.4247620434e-01 + -8.1742579506e-02 + -6.4346780657e-02 + -7.5410744557e-02 + -1.6148613355e-02 + -1.5837904147e-01 + 5.4428216572e-02 + -1.9085262418e-02 + 2.4683032134e-03 + 7.2921417953e-02 + -1.9132604147e-01 + 3.6910648866e-02 + 1.4068134852e-02 + -6.5893306777e-02 + -2.0967501135e-02 + 1.5055734781e-02 + 5.3232208685e-02 + 8.4538231942e-02 + -1.7408369439e-02 + 7.6153783675e-02 + 5.0293866282e-02 + -4.5144203460e-02 + 1.5944950482e-01 + 9.0116517901e-02 + 4.6981718961e-02 + 4.5052379283e-03 + -3.6818295067e-02 + -1.0641341043e-01 + -4.6700526505e-02 + 5.0513310560e-02 + 2.7295470135e-02 + -1.1382595127e-02 + 4.4505444992e-02 + 6.8852945098e-02 + -3.5301095010e-02 + -8.0036754111e-02 + -5.2243233509e-02 + -1.3560527502e-02 + 4.1359511680e-02 + 2.4212245939e-02 + -2.3467822904e-02 + 7.0379451449e-02 + 2.2149414955e-02 + 7.5546831902e-02 + -2.3952640455e-02 + 3.2928935928e-02 + 3.8925364925e-02 + -6.2613611871e-02 + -1.6673415494e-02 + 3.1791567933e-02 + 8.3741030299e-02 + -6.7561570871e-02 + 2.9443981073e-02 + 7.5701495045e-03 + -1.2389582219e-02 + -8.5847145648e-02 + -1.7521151169e-02 + 6.1074390844e-02 + -3.5548072420e-02 + -1.0958323760e-02 + 9.4793073262e-02 + 7.8734678432e-02 + 8.3231186898e-03 + -1.1129065602e-01 + -7.9125853759e-03 + -5.5864186763e-02 + -6.8662165374e-02 + 9.2835059470e-02 + 1.0844053113e-01 + -2.9628139014e-02 + -1.2937620791e-01 + -9.4628682951e-02 + 1.3860396834e-01 + 2.9329847191e-02 + -7.2206657679e-02 + 1.0066569364e-01 + -1.2060920868e-02 + 2.0596177042e-01 + -9.6191592558e-02 + 2.1300235153e-02 + 1.7011652694e-02 + 1.6303913256e-01 + 9.3666720639e-02 + -1.9712172634e-02 + -6.7175061970e-03 + -4.8864060714e-02 + -8.0499033104e-02 + -1.4465929135e-01 + 6.0218047517e-03 + 2.5262610233e-02 + -1.1141486431e-01 + -5.6422502516e-02 + 1.7110705811e-04 + -3.6185394368e-02 + 3.6657218355e-02 + -4.9940878471e-02 + -8.1612666067e-02 + 3.0167343010e-02 + -2.8220453532e-02 + 1.5152153740e-02 + 1.1679933583e-01 + -2.7337851832e-02 + -1.0383277934e-01 + -1.1759793186e-01 + 1.0857000406e-01 + 2.1855862688e-01 + -6.9347796094e-02 + -4.3925696339e-03 + -1.3348230082e-02 + 5.4383300733e-02 + 9.0940268537e-03 + -1.7295875928e-01 + 1.9208617034e-02 + -1.1867995197e-01 + -1.7500664728e-03 + -2.2466873171e-02 + 6.5260121735e-02 + -9.9147325556e-02 + 1.4630813817e-01 + 5.3868176765e-02 + 5.9077157545e-02 + 7.5147774260e-02 + 6.0161571324e-02 + -7.2844069005e-02 + 1.0314858191e-01 + 8.8000792833e-02 + 5.5348285592e-03 + -3.4108926572e-02 + 1.1587207082e-02 + 4.9541968869e-02 + -8.4128171954e-02 + 1.2139594922e-01 + 8.0545635837e-02 + 6.0916689827e-02 + 4.4932429177e-02 + 8.9507005012e-02 + -3.3609913203e-02 + -2.6181410922e-02 + 3.9815884044e-02 + -1.0220507972e-01 + 1.2735181879e-02 + -6.2805407796e-02 + 1.3256286835e-02 + 1.1566404888e-03 + 1.3094007055e-02 + 1.2622377803e-01 + 8.1531125775e-02 + -1.7522468084e-02 + -1.5423925785e-03 + -2.8883529460e-02 + 6.6809925498e-03 + -4.9167303208e-02 + -5.9155635471e-02 + -6.7123918271e-02 + -2.5961579875e-02 + -3.1918723167e-02 + -1.5652972556e-02 + -1.6035626328e-02 + 3.0846157538e-02 + 2.6486283250e-01 + 1.0233178744e-01 + -1.0465976797e-01 + -3.9036936266e-03 + 4.5123042196e-02 + -1.5374943714e-01 + -8.1620566401e-02 + -2.7980110394e-02 + 7.7228493519e-02 + -8.8057236270e-02 + 1.1773732110e-01 + 8.0195457926e-02 + 5.6450904561e-02 + -2.1375129139e-02 + -9.2541453001e-02 + -8.8879607722e-02 + 1.8142798611e-02 + -3.9509356136e-02 + 1.7370890369e-02 + 2.9233843127e-02 + -8.5944808121e-03 + -1.3825149366e-01 + 3.5902847732e-02 + -5.4046825410e-02 + -2.4760915781e-02 + 4.6469295834e-02 + 1.1106730878e-01 + 1.2675021432e-01 + -8.3813928055e-03 + 2.0432867347e-02 + -4.9679203332e-02 + -8.7803842600e-02 + -4.0936198526e-02 + 1.1808646770e-01 + -2.3463427515e-02 + -5.5929531275e-03 + -5.3724942121e-02 + -4.8414261858e-02 + -9.3790055940e-02 + 3.1179509932e-02 + -6.9973229969e-02 + -3.7872167341e-02 + -2.2013390569e-02 + -5.3065037703e-03 + -7.9567852756e-02 + 1.3633853301e-01 + -3.7786621984e-03 + -3.3462113898e-02 + 7.7594398712e-02 + -6.9153163239e-02 + 3.8918420905e-02 + -1.8075444605e-03 + 1.5482301709e-01 + 7.3207608702e-02 + -2.3043129133e-02 + -7.8271464172e-02 + 7.5037096636e-02 + 2.5554821837e-02 + 1.1055247813e-01 + 3.5162766416e-02 + 1.4050552220e-01 + -1.8584703368e-01 + 5.9809339524e-02 + 1.5228490592e-02 + -3.6428196383e-03 + 4.4147291030e-02 + -7.8279145448e-02 + -1.1135032531e-01 + -1.1540554073e-01 + 5.8592771491e-02 + -7.8093149199e-02 + 4.3999939991e-03 + -1.3710646607e-01 + -1.0791592760e-01 + 1.0924409343e-02 + 2.0395093821e-02 + 4.1146357314e-02 + 3.5534954974e-02 + -7.1593627527e-03 + 1.5474571913e-02 + -9.3130686941e-03 + 1.0165338777e-03 + 1.0778545545e-01 + 1.8486751600e-02 + 6.0161415175e-02 + -1.9378235268e-02 + 6.5190599270e-02 + 1.0435945873e-02 + 1.1291551973e-01 + -4.9996501851e-02 + 1.5843009559e-01 + -8.1716236359e-02 + -5.1336898180e-02 + -1.4132746006e-02 + 1.3335395994e-01 + -3.3502644108e-02 + -7.7251496090e-03 + 1.1452696518e-01 + -6.3787835062e-02 + -5.6207525190e-02 + 1.0917911348e-01 + -1.3208662407e-01 + 1.4045992078e-01 + 1.2632883307e-01 + -2.7737955897e-02 + 2.2702653729e-01 + -1.0644845111e-01 + 3.9343787398e-02 + -6.9848695833e-02 + 6.7821039368e-02 + 8.3831449201e-02 + 1.0210296337e-02 + 5.2964338114e-02 + -4.3919392582e-02 + -7.7052902432e-02 + -1.1389039192e-01 + -7.8451964267e-02 + -1.7831056569e-01 + 2.0400616324e-02 + -3.2018669702e-02 + 5.9860290049e-02 + 2.5445971322e-02 + 1.5312111154e-02 + -4.1500121352e-02 + -3.4060707075e-02 + -3.4907134071e-02 + 4.0788370904e-02 + 2.5119015503e-02 + 1.1013122139e-01 + 4.1577732837e-02 + 5.5396959230e-02 + -2.0490366298e-02 + -7.6625105938e-02 + 4.1790657063e-03 + -7.1005854462e-02 + -2.2571020654e-02 + 2.5216381182e-02 + 3.8019115571e-02 + 1.4757897474e-01 + -2.4723999447e-02 + -7.7461511714e-02 + -1.8057427260e-02 + -7.7289525464e-03 + -1.9241801308e-02 + -5.1435328311e-02 + -1.3551155930e-01 + -5.3994329262e-02 + -2.4384383724e-02 + 6.6320528856e-02 + 3.4898926494e-02 + 2.0284608356e-01 + -8.1957162779e-04 + -1.3669362143e-01 + -9.0772871888e-02 + -8.2804544432e-02 + -1.5382484105e-02 + -1.6914945389e-01 + -1.0717172425e-01 + -3.1131019963e-02 + 5.7757359567e-02 + 1.0876016762e-01 + 1.8255063453e-01 + -1.4569700708e-02 + -1.8513586468e-01 + -6.2857366382e-03 + 7.0463054514e-02 + -1.1904365730e-01 + -5.5003591415e-02 + -5.5342949452e-02 + 8.2327585174e-02 + -1.3794757719e-01 + -6.4101862239e-02 + -3.3244250477e-02 + 4.0055462734e-02 + 1.1121048126e-02 + 1.1998947052e-02 + -3.6534430440e-02 + -1.2884425877e-01 + 2.0144002268e-02 + -8.5248934156e-02 + -1.1033986591e-02 + -6.7926792646e-02 + -5.8920038014e-02 + 1.0844293673e-01 + 3.7271849366e-02 + -1.2251416560e-03 + 3.1299141321e-02 + 6.0483988136e-02 + -1.0635763355e-01 + 9.3916650733e-02 + 8.8442061142e-02 + 1.6374003935e-03 + 1.6812573651e-01 + 8.2564868165e-02 + 1.3645126482e-01 + 1.7674913143e-01 + 6.7786242214e-02 + 8.5878810609e-02 + -2.4449069233e-02 + 7.3643255743e-02 + -7.6815114313e-02 + 6.3471810498e-02 + -1.5036889449e-01 + -2.9197567397e-03 + -5.0939813866e-02 + 1.1834848427e-02 + 5.8597446180e-02 + -1.2344350603e-01 + 1.4728136427e-02 + 5.4168180138e-03 + -1.0097474817e-01 + -4.9926715124e-03 + 6.2120679064e-02 + -6.9423099628e-03 + 4.3233561508e-02 + -1.8851422035e-02 + 7.3369945745e-02 + 6.9965497202e-02 + -1.1590498087e-01 + -8.4281163887e-02 + -3.9124761887e-02 + -6.4410803569e-02 + -1.8134816311e-01 + 1.2025345349e-01 + 1.7243235024e-02 + -7.4065136200e-02 + 2.2433773108e-02 + 2.5911301259e-02 + -3.1698238030e-02 + -3.1710826199e-02 + -8.9683664609e-02 + -1.0125459937e-02 + 2.0300430584e-02 + 1.4033457165e-02 + 8.0541372391e-02 + -1.1514897826e-02 + -5.6972010519e-02 + 2.2316744481e-02 + 3.2006791499e-02 + 1.3897042853e-01 + 9.3803639287e-02 + -2.8832523093e-02 + -1.2273895476e-01 + -1.3497820261e-01 + 2.0183181618e-02 + 1.4745136064e-02 + -5.2186337727e-02 + -1.5250812853e-01 + 4.9466919520e-02 + -5.2181178569e-02 + -3.6949429056e-02 + -3.4122342979e-01 + -7.7328204723e-02 + 4.8482948475e-02 + 6.1798235625e-02 + -8.0524605736e-03 + -8.1579177029e-02 + -1.2765335468e-01 + 5.6599820690e-02 + -1.2785274284e-01 + -3.1531120719e-02 + 1.0815336393e-01 + 5.2836275253e-02 + -8.5926867365e-02 + -8.5964722219e-02 + 1.0150593923e-01 + 5.1901572117e-02 + -6.5986151174e-02 + -1.0284936132e-01 + -7.8916268112e-02 + 6.8086643631e-02 + -6.1589693024e-02 + 1.9781405300e-02 + 1.0573957113e-02 + 2.4736587969e-03 + 4.6045856192e-02 + -1.0116536786e-01 + 2.8190732715e-02 + 1.5349693458e-02 + -9.2852525708e-02 + 1.1082502294e-01 + 7.7245685719e-02 + -6.0056749484e-02 + -9.0879544367e-02 + -1.7184562964e-01 + -7.0303166858e-02 + -4.3085760847e-02 + -8.8414106964e-03 + -1.4107537099e-01 + 8.1785046883e-03 + -1.7146579574e-02 + 1.0386312255e-01 + 6.7557144819e-02 + -6.3801163815e-02 + 7.9969083673e-02 + 7.7312564526e-02 + -1.0282393908e-01 + -9.0193137787e-02 + -2.9502838426e-02 + 4.3234359396e-03 + 1.4522949226e-01 + -7.6830888876e-02 + -8.4860343622e-03 + 1.1594430088e-02 + -1.4612928375e-02 + 6.0795809218e-02 + 8.2092625648e-02 + -6.2895916633e-02 + -2.8793020092e-02 + -8.4656004843e-02 + -3.0289034652e-02 + -6.0483178249e-03 + -2.7775878447e-02 + 2.7218879492e-02 + 5.6581265842e-02 + 6.2866723821e-02 + 1.1662995470e-02 + 1.2332157733e-01 + -6.8330541649e-02 + -8.2182595325e-02 + 2.4256002176e-02 + -1.6806304285e-02 + -4.5943502232e-03 + 1.0404829389e-01 + -3.7899902392e-02 + -6.3707906464e-02 + 8.7102500269e-02 + -1.7634151024e-02 + 6.5702671417e-02 + -1.2309663306e-01 + -9.3289854246e-02 + -4.5257665230e-02 + -2.4476117417e-02 + 1.4259147824e-02 + -7.2806695004e-02 + -3.1535247808e-02 + -8.2299019212e-03 + -1.4846716547e-01 + 1.5938234327e-02 + 1.1455494227e-01 + 1.7123567084e-01 + 9.5750578571e-02 + 1.7316674606e-02 + -5.5565085445e-02 + 1.1320160740e-01 + 4.4610477658e-02 + 4.0329504937e-03 + 1.4670749539e-01 + -3.0150786886e-02 + -7.8618421216e-03 + -3.0851144082e-02 + -5.5530778371e-02 + 6.5690823881e-02 + 7.8908216902e-02 + 1.8900247740e-02 + 2.7030003997e-03 + 5.5158055536e-02 + 7.8405977750e-02 + 2.8075204248e-02 + -6.4726172933e-02 + 5.0502389395e-02 + 5.7277730129e-02 + 1.3472462396e-01 + 7.5829916923e-02 + 4.8907998996e-02 + -9.1790440314e-03 + 1.3379133626e-01 + 2.1449816653e-02 + 5.3050277583e-02 + 1.6234679017e-01 + -4.5075156891e-02 + 6.6009979801e-02 + -6.5985375634e-03 + -5.2385053527e-03 + -1.4527756790e-01 + -9.3190888045e-05 + -2.9522788143e-03 + 9.2756031092e-02 + 3.4949763616e-02 + -5.1750432685e-02 + -6.2744171039e-02 + -2.4543368315e-02 + 1.6506401523e-02 + 3.4808956696e-02 + -6.4282029900e-02 + 1.6677728986e-01 + -9.6887327483e-02 + -4.9086771853e-02 + 1.4825710476e-01 + -1.7458279169e-02 + -1.6834829404e-01 + 1.4457095386e-02 + -2.0860831071e-03 + -2.2422421168e-02 + -2.2178492111e-02 + 8.9677719318e-02 + 7.8606404607e-03 + 7.1799970566e-02 + -1.6201106981e-01 + 9.3017314214e-02 + 8.9522738030e-02 + 2.8555930190e-02 + -1.0614678344e-01 + 6.1024805892e-02 + -4.1521391243e-02 + 3.8150607257e-02 + 7.1174479608e-02 + -3.6949749110e-02 + 7.0602543654e-02 + 9.6095995037e-02 + 3.4361439785e-02 + 5.4416072927e-02 + 5.9057027972e-02 + -2.7012685883e-02 + 1.6550249095e-02 + 2.1494322035e-02 + 1.1673986625e-01 + -1.3163249214e-01 + 5.3010399959e-02 + 4.1101004837e-02 + 6.0846701119e-02 + -1.4901136979e-01 + 7.6426112982e-02 + 1.1938922665e-03 + -8.9982891285e-02 + -5.6114707634e-02 + -2.2611507548e-02 + -4.0319210264e-02 + 8.5952024646e-02 + 1.2123947774e-02 + 2.0741272545e-02 + 1.6084318958e-02 + 1.4055640043e-02 + 1.4640129736e-01 + -5.4212875820e-02 + 2.9248077425e-02 + -1.4252037870e-01 + 4.4919080873e-02 + 3.1057518467e-02 + 6.0181056368e-02 + 6.7535919798e-04 + -9.0702808146e-02 + -1.3068469035e-02 + -7.7220135406e-02 + 4.5092937286e-02 + -1.9393254596e-02 + 1.0715426298e-01 + 1.3710164117e-02 + 6.7096210160e-02 + -5.1269801252e-02 + -1.1695344680e-01 + -1.1767311281e-01 + -1.3327597180e-02 + 1.0760832610e-01 + -4.1562052871e-02 + 4.7670857213e-02 + 7.8365245328e-02 + -2.2130159021e-02 + 1.6107013624e-01 + -1.4011672521e-01 + 5.8721511621e-02 + -8.4517607738e-02 + 3.1700350909e-02 + -4.7255771961e-02 + -9.6613794814e-02 + 3.4419477752e-02 + 5.6970494635e-03 + 9.8314864182e-02 + 1.3852807056e-02 + 5.5416042038e-04 + 2.8848831882e-02 + -4.4452567384e-02 + 1.0186746147e-02 + -6.0611346576e-02 + -1.0138304365e-02 + 7.2122647921e-02 + 1.9394347283e-02 + -3.0267767313e-02 + 5.4510956961e-02 + 8.4097342888e-02 + 9.8255228338e-02 + 1.1937070901e-02 + 1.2715369842e-01 + -1.1898626901e-01 + 1.4101995974e-02 + 2.1617286722e-02 + -3.4168583747e-02 + 1.0727458680e-01 + 8.1633492629e-02 + 8.8449250401e-02 + -7.6164363604e-02 + 1.0975228194e-01 + 3.2029541365e-02 + 6.1320277154e-03 + 2.7459936864e-02 + -1.7253333766e-02 + -7.5568336621e-02 + -5.7082887376e-02 + 8.1147106752e-02 + -1.1783672397e-01 + -5.8966651171e-02 + -1.6707197961e-02 + 2.0106380715e-02 + -4.3383987172e-03 + 6.2164682046e-03 + 4.6974266941e-02 + -1.7926136076e-01 + -8.9877408666e-03 + -3.1794407884e-02 + -3.3045345427e-03 + 1.0669350301e-01 + -9.7450429412e-02 + 1.4741669799e-02 + 1.2562890513e-01 + -1.8691997874e-02 + -3.9234650158e-02 + 3.3289675976e-03 + 3.4791867666e-02 + -2.3962637325e-02 + 4.4760153639e-02 + 7.5412438722e-02 + -9.5101425286e-02 + -6.1670068782e-02 + -5.8323344952e-02 + 1.5989507293e-02 + 3.5221168280e-02 + 3.0380033936e-02 + -6.7916775751e-02 + -2.0687249277e-02 + -1.0573823552e-01 + -3.4062054276e-03 + -1.0827739236e-01 + 1.3166524383e-02 + 1.2366959667e-01 + -1.0420332923e-01 + -1.8900264968e-02 + 1.3662516670e-01 + 4.7069077878e-02 + 1.1121301685e-01 + -3.6442131697e-02 + -1.0434266269e-01 + -1.1818345123e-03 + 6.7684633338e-02 + -4.7753913036e-02 + 8.2319647476e-02 + -8.4795088159e-02 + -9.2385374366e-02 + -5.1662387870e-02 + 4.5831248653e-02 + 1.9802708952e-02 + 1.0971985175e-02 + -1.5238435160e-01 + 1.8954273568e-01 + 4.5638697940e-03 + -1.8755527192e-01 + 1.5878510186e-01 + -1.3584719265e-01 + -3.4262590684e-02 + -8.5564775489e-02 + -4.3224535460e-02 + -4.6464664687e-02 + -1.3755861046e-03 + -2.1786404665e-02 + 1.2176403856e-01 + -6.0481965365e-02 + -5.0424552300e-02 + -7.4679973032e-02 + -7.1981445570e-02 + 1.0049236554e-01 + -1.7082816388e-01 + -1.5305193323e-01 + -1.5376341741e-02 + -7.6314481496e-04 + -1.2608682311e-01 + 7.6989212537e-02 + -8.2621038307e-02 + 3.1675240816e-02 + 8.0705211816e-02 + -3.8869993458e-02 + 1.5125213402e-02 + -6.3236283716e-02 + -6.0174387223e-02 + -2.7000594650e-02 + 8.3468337055e-02 + -3.2108938991e-02 + 1.3012058789e-02 + -1.5433010139e-01 + -5.3137332273e-02 + -3.1122488847e-02 + -1.2612806559e-01 + -3.5114360536e-02 + -1.1079154818e-01 + -2.5125877973e-02 + 2.3605934901e-02 + 2.1603646037e-01 + 1.7550655445e-02 + -1.8511138494e-01 + -1.5391749048e-01 + 2.8912876679e-02 + 1.0722246593e-01 + -1.5363318517e-01 + -9.2002086458e-02 + 6.7340893229e-02 + 7.3630433793e-02 + 1.0418951296e-01 + 2.3680053491e-02 + 7.5895284367e-02 + -7.4626052764e-02 + 4.7302668456e-02 + -2.2549440280e-02 + 3.8451252261e-02 + 7.7351712380e-02 + 3.3541942001e-02 + 8.5643264862e-03 + -8.8500507405e-02 + -7.1600459142e-02 + -6.1700295596e-03 + 3.4177706049e-02 + 1.8211145472e-01 + -1.6451023683e-02 + 2.7966992593e-02 + 2.5508355367e-01 + 2.2120289522e-02 + 1.5756690699e-01 + -5.6982997636e-02 + 1.1117177079e-01 + 3.9131539698e-02 + 4.4929255664e-02 + 1.3185400207e-01 + -1.4864483812e-02 + -7.2691985268e-02 + 2.1046017563e-03 + 1.5710326858e-02 + -4.0430101845e-02 + 1.3254441368e-02 + -7.2937346430e-02 + -3.9699800394e-02 + -8.1293007877e-02 + -1.9888061960e-03 + 2.0606189578e-02 + -1.0374313676e-01 + 7.3840309740e-02 + -6.5839050681e-02 + 1.8580969489e-02 + -2.9682065774e-02 + -2.7721197611e-02 + -8.8270058763e-03 + 1.3043953223e-01 + 1.2029160186e-01 + 3.6021934679e-02 + 1.1699634477e-01 + -2.9072931215e-02 + 8.4125865479e-03 + 5.2352150821e-02 + 9.6311882676e-02 + -9.3588623561e-02 + 4.8536163060e-02 + 7.8113389548e-02 + 8.6408589713e-02 + -1.8051446656e-02 + 3.7865442604e-02 + 7.0047033949e-02 + -1.7206977891e-02 + -2.2937966259e-02 + 7.1257746198e-03 + -2.4165762406e-04 + -3.6217898177e-02 + 4.4566575402e-02 + 4.3476318726e-02 + 5.2738755384e-02 + 1.0414438700e-02 + 1.1170195976e-01 + -1.9408732679e-01 + 2.1397992320e-02 + -3.6766381756e-03 + -1.0182041408e-01 + 2.0128181638e-01 + 8.9971911700e-02 + 7.6321200819e-03 + -9.8590840154e-02 + -6.8564470869e-02 + -1.5816529637e-01 + 4.9399837935e-02 + -5.6987480342e-02 + -6.7340355598e-02 + 5.8628993109e-03 + 2.8060084657e-02 + 6.2226864421e-02 + 6.5385962110e-02 + -1.1474499424e-01 + 3.5828734257e-02 + 2.8025861104e-02 + 5.7184615539e-02 + -9.9152980303e-02 + -4.5676877541e-03 + 6.2010344404e-02 + -8.1119038848e-02 + 1.6010654082e-01 + 4.9035205975e-02 + -1.9825584983e-02 + 9.2955089981e-02 + -9.0510907742e-02 + 1.3588702965e-01 + 1.0744776444e-01 + 4.0158299965e-03 + -4.9007712194e-02 + -1.4135610628e-01 + 8.3099861340e-02 + 4.0156692786e-02 + -2.6451319494e-02 + 1.4746730075e-01 + -3.0699380887e-02 + 4.1717965109e-02 + -9.7203926821e-02 + 1.2004051088e-01 + 1.1766998787e-01 + 6.1492783132e-02 + 9.2916489926e-02 + -5.4200151655e-02 + -6.3299395630e-02 + 4.3048125594e-02 + 7.2893633787e-02 + 2.1221453624e-02 + -7.2601520309e-02 + 2.0804135159e-03 + -6.5362349758e-03 + -5.2897276821e-02 + 4.8350640204e-02 + -2.9869464809e-02 + 1.6491745126e-02 + 4.2819531677e-02 + -1.1569738069e-01 + 1.4463175482e-02 + 1.5930144449e-02 + -3.6345649773e-02 + -6.9534503223e-02 + -2.5489797541e-02 + 2.9134042824e-02 + -5.2046052327e-02 + 2.1015213530e-02 + 6.3108189186e-02 + -6.1562676428e-02 + 3.1829804465e-02 + 2.6840141168e-02 + -4.4969549017e-02 + -5.1810030541e-03 + -1.0342706986e-01 + 9.0345413094e-02 + -1.0107482403e-01 + 8.1981632634e-02 + 2.1952675850e-02 + 8.9551732131e-03 + -1.7122384812e-01 + 1.0510199940e-01 + -5.3702187198e-02 + 3.3089492484e-02 + 6.6582187984e-02 + 8.3576919569e-02 + -5.9858922864e-02 + -5.9177377285e-02 + 3.6915129752e-03 + -6.9737498850e-02 + 6.9413823318e-02 + 1.7492518510e-01 + 1.2133113791e-02 + -5.8349155298e-02 + 4.1959275424e-02 + -2.8886402410e-03 + -1.3729537747e-02 + -1.2842435416e-01 + 1.1353854880e-01 + -4.9701235182e-02 + 1.5002622519e-01 + -7.0009347477e-02 + -1.4031701836e-02 + 1.8979122771e-01 + -1.4881109351e-01 + 4.8190970538e-02 + 8.6408164548e-02 + 2.0862892098e-02 + 2.8699978567e-02 + 1.4747028444e-02 + -9.2143592081e-02 + -2.3729572448e-02 + -1.9548677236e-02 + 1.2238873589e-02 + 4.4775354498e-02 + -1.1657398378e-02 + -1.1344096112e-01 + -3.2847196067e-02 + -3.5435513855e-02 + -1.0096222037e-01 + 5.2709770731e-02 + 1.2170120638e-01 + -1.0750524592e-01 + 1.2473110076e-01 + -4.6061542795e-02 + -8.8171420278e-02 + -4.1852741567e-02 + -1.6345296267e-01 + 3.0492914787e-02 + 8.6537966788e-04 + -8.2854822368e-02 + -1.4074651959e-02 + 1.1672246018e-01 + 1.7455363555e-02 + -9.2243712680e-02 + -1.1268685309e-01 + 1.5351161364e-02 + -8.1583896020e-02 + -3.3456592442e-02 + 6.8897438323e-03 + 6.3453409265e-02 + -1.1933741091e-02 + -3.7228973853e-02 + -9.0218984176e-02 + -4.7515588477e-02 + -9.2593333301e-02 + 8.0650856247e-02 + -1.6137418488e-02 + 5.4244709007e-02 + 1.1118033293e-01 + 1.4246648619e-01 + -3.4392826711e-02 + -2.0361912108e-02 + -6.6460957044e-02 + -1.5289139879e-01 + -5.9210088881e-02 + 6.4155670531e-02 + 3.6469714700e-02 + -3.0277434017e-04 + -5.1181608115e-02 + 2.9710283139e-02 + 1.1975136222e-01 + 2.4218879818e-02 + 6.0432459273e-02 + -1.5364620536e-03 + 4.0313492961e-02 + 4.6138252424e-02 + -5.7738005936e-02 + 1.7585041039e-01 + -8.0146633083e-02 + 3.4790398254e-02 + 4.5707589655e-02 + 2.2793010746e-02 + -7.3048845418e-02 + 1.6098844703e-02 + 1.2278213630e-01 + -3.4412232856e-02 + 5.2779547661e-02 + -1.6050242475e-01 + -1.5540844584e-01 + -6.6788268324e-02 + -5.9827465616e-02 + -9.7587543215e-02 + 3.0553479730e-03 + 1.1810998230e-02 + 8.5158415031e-02 + 1.9029091383e-01 + -1.3413258821e-01 + 2.8528887786e-02 + -1.8699202129e-02 + -1.2769987031e-02 + -1.3274385906e-01 + -8.4823946215e-02 + 7.9708684527e-03 + 4.9303537033e-02 + 9.5126285264e-02 + 8.0939636233e-02 + -3.7055832978e-02 + -7.3552361187e-02 + -1.4141415507e-01 + 2.7201763390e-01 + 1.1298305428e-02 + -1.4164742522e-01 + 8.9309471394e-02 + 7.5914782199e-03 + 4.1145069186e-02 + -8.6945849492e-02 + 1.7717528564e-01 + -6.0269698683e-02 + -3.1004476137e-02 + 2.3014073538e-02 + 2.9699357417e-02 + -6.2805931075e-02 + 1.8059269479e-01 + -2.3008870063e-02 + 1.9008444976e-02 + 5.5089069965e-02 + 9.3347950283e-02 + -1.4260591419e-02 + -9.1566869339e-04 + -1.3578433659e-02 + 6.5903155893e-02 + 2.5999861151e-03 + 5.4709729485e-02 + 2.9591112352e-02 + -3.3034599116e-03 + -4.5715154906e-02 + -1.0592880902e-02 + 4.0646618247e-02 + -2.7627209864e-02 + 2.5085645513e-02 + -4.5212569695e-02 + -6.3153718927e-02 + 1.9031464859e-01 + -3.6034369308e-02 + -1.3837458131e-01 + -2.2634833399e-02 + -1.5197562316e-02 + -3.5444979253e-02 + -6.4407651029e-02 + -8.8223816781e-02 + 2.9349182108e-02 + 1.1487791031e-02 + -1.0123661175e-01 + -3.7432097490e-02 + -5.2585857041e-02 + 6.4509812457e-02 + 1.9488966585e-01 + 4.0870168220e-02 + 5.7798341902e-02 + -6.9349951592e-02 + -3.6833013141e-02 + 5.8100079948e-02 + 3.9207591449e-03 + 7.2142474947e-02 + -5.0667523757e-02 + 8.3696975545e-04 + 3.8595049101e-02 + -4.3551030625e-02 + -7.8608866044e-02 + -2.1233805065e-02 + 2.3709861995e-02 + 3.8631722679e-02 + 8.8131552009e-02 + 1.3142632709e-01 + -4.7549801431e-02 + -1.2126025078e-02 + -5.4018488027e-02 + -7.8817227079e-02 + 5.9955562321e-02 + 9.8784978482e-03 + -3.1433068633e-02 + 5.6538560716e-03 + -3.4266923503e-02 + -3.0504921983e-02 + 5.4241092595e-02 + 7.9028030425e-02 + 9.4090827082e-02 + -7.3965620902e-02 + -9.8915456537e-02 + -7.5395507778e-02 + 1.2746262266e-01 + 3.3176568067e-02 + 1.3800976369e-01 + -2.0891848478e-02 + 1.2643718182e-02 + 4.1015139502e-02 + -8.4374012884e-02 + -4.9088401465e-02 + -2.0638834844e-02 + -3.4082393310e-02 + 4.3387163846e-02 + -1.8401990798e-02 + -5.5216488707e-02 + 5.9807194151e-02 + 6.1799875537e-02 + 9.2937046047e-02 + -8.6823099760e-02 + -3.7370325739e-02 + -3.7184390623e-02 + 1.1166348655e-01 + 9.4443327954e-02 + 3.5069978826e-02 + 1.0963657680e-01 + 7.4818597988e-03 + 2.8595033057e-02 + 7.3439494324e-02 + 6.1608951294e-02 + -1.0600869974e-02 + -1.1132969451e-01 + 9.4529914946e-02 + -9.8183606644e-02 + -1.6507678062e-02 + -2.1501569671e-03 + 1.5341083689e-01 + 4.4182956728e-02 + 4.3171626572e-02 + -4.5471383386e-02 + -4.3272556496e-02 + -7.8746063027e-04 + 6.5456356200e-02 + 8.8809835839e-02 + 7.1057053396e-02 + 6.7300542533e-02 + 3.6995786089e-03 + 1.3737176478e-01 + 3.1701509507e-02 + -8.5467881763e-02 + 6.4319266419e-02 + -2.0788753086e-02 + 1.6581369626e-01 + 5.8015441698e-02 + 1.3556540728e-01 + -1.0866476881e-01 + 1.7370495078e-03 + -6.8608727600e-02 + -1.0385412280e-01 + 8.4352314236e-02 + 2.6784632931e-02 + -3.6445026471e-02 + -5.9326777130e-02 + 1.3023835089e-02 + 4.0891864024e-02 + -5.2177311573e-02 + -1.0782488799e-03 + -8.3530250999e-02 + 9.2189030296e-02 + -9.9676294065e-03 + 5.7216127214e-02 + 3.3994165286e-02 + -8.4339173750e-02 + 1.4391605615e-02 + 1.6247577585e-01 + -1.2785766026e-01 + -3.8180777955e-02 + 1.1479274464e-01 + 5.7783784013e-02 + 4.1086301888e-02 + -1.6507806714e-02 + -1.1806923243e-01 + 1.0955584349e-02 + 2.0397013523e-02 + -1.0700743560e-01 + 7.3659878860e-02 + 1.3478681032e-01 + -8.4466744003e-03 + -8.7565078556e-02 + 8.6065188468e-02 + 2.6333017534e-02 + 1.3702661089e-02 + -9.1236350914e-02 + 9.6414491389e-02 + 1.0098479741e-02 + 1.9936839268e-02 + 9.7128862598e-02 + 1.1126164672e-01 + -3.4416948405e-02 + -8.5537373914e-02 + 1.2907899474e-01 + 6.5413467073e-02 + -2.1562008669e-02 + 4.0887300587e-02 + -4.0032594669e-02 + 6.0072032122e-02 + 7.1758733689e-02 + 9.4959027981e-02 + -4.4643907341e-02 + -1.1926542341e-02 + 5.1506431655e-02 + -3.8632519382e-02 + 2.5972148169e-02 + 3.4881069820e-02 + 2.0070220549e-02 + -5.5213863572e-02 + -2.7766200404e-02 + 1.2180704553e-02 + -4.1747871634e-03 + -4.6243584089e-02 + 5.8517533572e-02 + -2.0589724086e-02 + -2.3877451965e-02 + -3.3444372410e-02 + -8.8021070816e-03 + -9.1397639356e-02 + 4.1191518016e-03 + 2.3128844123e-01 + 1.3023357566e-01 + 1.6371660201e-01 + -2.9077476117e-01 + -3.0660825166e-02 + -5.4045537271e-02 + -3.8032711138e-02 + -4.9892321405e-02 + -1.1030218008e-01 + -1.7380707882e-02 + 3.4258220644e-02 + -2.4196381864e-02 + 7.8341236149e-02 + -5.0694399732e-03 + -9.4775913303e-02 + -6.2105399847e-02 + 2.0472371488e-01 + 6.6196051684e-02 + -2.6638791022e-02 + 1.2834489690e-02 + 1.0706087909e-02 + -5.4995139345e-02 + -5.8213191544e-02 + -3.6813987190e-03 + 6.3266449726e-03 + -9.9708429873e-02 + -1.7711743364e-01 + -1.1830381068e-01 + 1.8590579250e-01 + -5.3574207192e-02 + -8.4872739463e-02 + -3.7130096331e-02 + -7.6635482717e-02 + -4.2520882129e-02 + -6.1112198733e-02 + -3.0134876583e-02 + 4.0572072844e-03 + 4.0150347967e-02 + -6.2038768884e-02 + -4.5144102561e-02 + -1.9312573409e-02 + -5.6745760263e-02 + 8.5117643359e-02 + -6.4699527886e-02 + 6.5091405484e-02 + -2.0034679820e-01 + 2.6224170018e-03 + 6.6232026453e-02 + 9.4180202910e-02 + -8.8677455945e-02 + 1.2043774025e-01 + 1.1077482342e-01 + 7.8275108898e-02 + -8.5043722640e-02 + -1.7183046168e-02 + 1.3589930139e-01 + 8.3873824940e-02 + 7.9130075675e-02 + -4.3336524488e-02 + -1.5830532500e-01 + 1.5586299132e-01 + -3.3934630737e-02 + 2.2049278494e-02 + 3.2839373230e-02 + 1.1336033549e-02 + -6.0960583556e-02 + 9.3457063358e-02 + -1.1364262062e-01 + -5.5148715998e-02 + 3.3529487533e-02 + -2.5869900754e-02 + -6.0197330970e-02 + 5.8442759879e-02 + -4.0291931218e-03 + 1.4147911289e-01 + 1.1303168046e-01 + 7.3245748044e-02 + 1.0420161224e-01 + 1.5404103797e-02 + -3.8266998746e-02 + -2.4057268534e-02 + -1.8430052852e-01 + -9.5270742433e-02 + 9.3576474736e-02 + -8.1436372259e-03 + -4.4577039113e-02 + -6.0327841802e-02 + -3.6140032465e-02 + -1.4189221380e-02 + 1.3984614149e-03 + 1.0287979475e-03 + -1.1773747633e-01 + -1.2575288571e-01 + 3.8004092066e-02 + -6.3186291283e-03 + 4.9220919182e-02 + 3.9024283106e-02 + 1.5058857528e-01 + 1.0885341435e-01 + -8.5560563849e-02 + -1.5919768951e-02 + -9.3827226575e-03 + -2.9435636315e-03 + 2.8671912472e-02 + -3.1000000000e-01 + -2.8885714286e-01 + -2.6771428571e-01 + -2.4657142857e-01 + -2.2542857143e-01 + -2.0428571429e-01 + -1.8314285714e-01 + -1.6200000000e-01 + -1.4085714286e-01 + -1.1971428571e-01 + -9.8571428571e-02 + -7.7428571429e-02 + -5.6285714286e-02 + -3.5142857143e-02 + -1.4000000000e-02 + 7.1428571429e-03 + 2.8285714286e-02 + 4.9428571429e-02 + 7.0571428571e-02 + 9.1714285714e-02 + 1.1285714286e-01 + 1.3400000000e-01 + 1.5514285714e-01 + 1.7628571429e-01 + 1.9742857143e-01 + 2.1857142857e-01 + 2.3971428571e-01 + 2.6085714286e-01 + 2.8200000000e-01 + 3.0314285714e-01 + 3.2428571429e-01 + 3.4542857143e-01 + 3.6657142857e-01 + 3.8771428571e-01 + 4.0885714286e-01 + 4.3000000000e-01 + 5.5000000000e-01 + 5.5666666667e-01 + 5.6333333333e-01 + 5.7000000000e-01 + 5.7666666667e-01 + 5.8333333333e-01 + 5.9000000000e-01 + 5.9666666667e-01 + 6.0333333333e-01 + 6.1000000000e-01 + 6.1666666667e-01 + 6.2333333333e-01 + 6.3000000000e-01 + 6.3666666667e-01 + 6.4333333333e-01 + 6.5000000000e-01 + 6.5666666667e-01 + 6.6333333333e-01 + 6.7000000000e-01 + 6.7666666667e-01 + 6.8333333333e-01 + 6.9000000000e-01 + 6.9666666667e-01 + 7.0333333333e-01 + 7.1000000000e-01 + 7.1666666667e-01 + 7.2333333333e-01 + 7.3000000000e-01 + 7.3666666667e-01 + 7.4333333333e-01 + 7.5000000000e-01 + 7.5666666667e-01 + 7.6333333333e-01 + 7.7000000000e-01 + 7.7666666667e-01 + 7.8333333333e-01 + 7.9000000000e-01 + 7.9666666667e-01 + 8.0333333333e-01 + 8.1000000000e-01 + 8.1666666667e-01 + 8.2333333333e-01 + 8.3000000000e-01 + 8.3666666667e-01 + 8.4333333333e-01 + 8.5000000000e-01 + 8.5666666667e-01 + 8.6333333333e-01 + 8.7000000000e-01 + 8.7666666667e-01 + 8.8333333333e-01 + 8.9000000000e-01 + 8.9666666667e-01 + 9.0333333333e-01 + 9.1000000000e-01 + 9.1666666667e-01 + 9.2333333333e-01 + 9.3000000000e-01 + 9.3666666667e-01 + 9.4333333333e-01 + 9.5000000000e-01 + 9.5666666667e-01 + 9.6333333333e-01 + 9.7000000000e-01 + 9.7666666667e-01 + 9.8333333333e-01 + 9.9000000000e-01 + 9.9666666667e-01 + 1.0033333333e+00 + 1.0100000000e+00 + 1.0166666667e+00 + 1.0233333333e+00 + 1.0300000000e+00 + 1.0366666667e+00 + 1.0433333333e+00 + 1.0500000000e+00 + 1.0566666667e+00 + 1.0633333333e+00 + 1.0700000000e+00 + 1.0766666667e+00 + 1.0833333333e+00 + 1.0900000000e+00 + 1.0966666667e+00 + 1.1033333333e+00 + 1.1100000000e+00 + 1.1166666667e+00 + 1.1233333333e+00 + 1.1300000000e+00 + 1.1366666667e+00 + 1.1433333333e+00 + 1.1500000000e+00 + 1.1566666667e+00 + 1.1633333333e+00 + 1.1700000000e+00 + 1.1766666667e+00 + 1.1833333333e+00 + 1.1900000000e+00 + 1.1966666667e+00 + 1.2033333333e+00 + 1.2100000000e+00 + 1.2166666667e+00 + 1.2233333333e+00 + 1.2300000000e+00 + 1.2366666667e+00 + 1.2433333333e+00 + 1.2500000000e+00 + 1.2566666667e+00 + 1.2633333333e+00 + 1.2700000000e+00 + 1.2766666667e+00 + 1.2833333333e+00 + 1.2900000000e+00 + 1.2966666667e+00 + 1.3033333333e+00 + 1.3100000000e+00 + 1.3166666667e+00 + 1.3233333333e+00 + 1.3300000000e+00 + 1.3366666667e+00 + 1.3433333333e+00 + 1.3500000000e+00 diff --git a/tests_pytest/fixtures/nep_spin3/spin3_o3c2_typewise_oracle.txt b/tests_pytest/fixtures/nep_spin3/spin3_o3c2_typewise_oracle.txt new file mode 100644 index 000000000..cfae76e5f --- /dev/null +++ b/tests_pytest/fixtures/nep_spin3/spin3_o3c2_typewise_oracle.txt @@ -0,0 +1,100 @@ +spin3_oc_oracle_v1 +model_sha256 5ad1b0e0ecb4f9174615b69de8e89c3d8e949f85dd35be8564adf77cde88384b +descriptor_dim 85 +spin_descriptor_dim 55 +case zero 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.39999999999999991e+00 1.30000000000000004e+00 8.00000000000000044e-01 6.99999999999999956e-01 2.60000000000000009e+00 1.39999999999999991e+00 1.30000000000000004e+00 5.00000000000000000e-01 2.70000000000000018e+00 3.10000000000000009e+00 2.79999999999999982e+00 2.20000000000000018e+00 +spins 15 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +potential 5 -9.51438283922142469e-02 3.15495448828676750e-01 -1.08666900340435135e-01 3.15251539019029303e-01 -1.03220535337539665e-01 +forces 15 -7.52203292929924140e-03 2.31254972312548226e-02 -4.21829351544954212e-03 9.05965312500611047e-03 -9.40866354915917066e-03 -1.06235972234496774e-02 -3.31555510242221869e-03 -8.85167160118362564e-03 -5.18027083270773160e-03 1.64491855772064678e-03 -9.75746987852190752e-03 1.60609755202270679e-02 1.33016348994703757e-04 4.89230779760988204e-03 3.96118605137988408e-03 +virial 45 1.02702889632011584e-02 -5.21060976712049186e-04 -1.60139496629025822e-03 3.55760238574007312e-03 -1.61083059951225779e-02 -6.13325693339412340e-03 1.83356420904859482e-03 -8.10798543137474827e-03 4.19823123613867911e-03 9.69384576071296265e-03 -7.00661316015066798e-03 -2.54926958819493466e-04 -5.92075271200100898e-03 1.73785961448429740e-02 1.35557769303652608e-02 -1.00259037219269142e-03 1.29741917532387886e-02 1.21147231061117956e-02 -5.01599256165076272e-03 8.92465357902397401e-03 1.54760166948164114e-03 8.20572838177515123e-04 -1.66091622133462645e-02 -4.64515135555315650e-03 -1.75758730647565336e-03 -1.10741371790085900e-03 -1.86503928197508757e-03 2.54197741665149798e-03 -3.34732896603774904e-03 2.29153516243151868e-03 -3.18040065181259381e-03 1.31041319777210046e-02 -1.32136445437912500e-02 4.31151539677081513e-03 -1.02903415625917247e-02 1.94838974880061529e-02 -3.03912877297456792e-03 -1.21967255316707789e-03 -2.16498640585475240e-03 1.55295606285244122e-03 -1.06564456577793809e-03 -1.93958946462374098e-03 -3.56707342620243058e-03 -5.84431640836846362e-03 -1.82211979063282535e-03 +mforces 15 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 +tau 15 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +descriptor 425 -9.66569040574016963e-02 -7.16298740671639372e-02 -1.73189969174782743e-01 4.76366185180938373e-01 -4.12470498393120277e-01 1.34087460383100817e-02 5.27635559719638950e-03 3.72521551461243820e-03 2.13110135221889017e-03 8.45895156176228701e-03 9.98854029181208032e-03 2.15408622475869163e-03 7.81295306505700587e-03 1.38590220109797361e-03 2.14753729129900650e-02 1.46478311468172633e-02 1.38738479170062261e-02 1.58711478660126769e-02 2.27768076142121191e-03 2.28236061717610392e-02 2.93962418547943326e-02 2.84879023537342631e-02 2.20832169080680575e-02 5.40172328181464691e-03 2.50571573319468520e-02 2.81989804142082959e-04 -3.54327218197930668e-05 8.37295302271673185e-05 5.66292471513821164e-06 -8.94117546733149142e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.23481863430668981e-01 -6.25519456753765857e-02 8.51240205412637368e-02 8.15468747031985464e-02 7.85428557155453400e-02 1.08520385650594199e-03 2.25565187138667246e-03 2.62300375686576673e-02 3.56218400246549214e-03 6.47919736489158040e-03 3.24120177481641326e-03 3.45992524584570445e-03 3.62884357741285468e-02 6.41520627434063757e-03 8.25179710454860063e-03 4.12119190671987427e-03 6.87815153668054364e-03 7.22165772550041746e-02 1.27083706069929855e-02 9.70001775216213294e-03 3.79518895268903715e-03 6.76040800978797152e-03 6.71064246207816739e-02 1.14815840210739043e-02 2.14924117281718521e-02 -4.98190639011998005e-05 -1.63240068267961694e-05 1.48189714530914669e-03 1.40789375474160956e-04 3.69467762617313488e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.28256597580786436e-02 -1.21321684924280374e-01 -2.51736097903013267e-01 4.41139871257841987e-01 -1.69534984766372604e-01 2.36483278288444135e-02 5.09077895784372167e-04 4.47456662717190309e-04 5.11256949154828728e-03 3.47069194175847646e-03 1.67476308446369779e-02 1.48822244535158394e-03 2.42360616812703749e-03 3.45420367220892295e-03 6.73791229793482480e-03 1.78383886569127431e-02 2.19744813218269433e-03 6.16423135505987652e-03 1.40912391900268642e-03 2.60579251694636749e-02 3.22463311903943908e-02 3.05329839939879081e-03 9.52283627664764730e-03 4.78958203400679187e-03 4.72957179029264291e-02 2.43362812275990588e-04 -1.25392048867713212e-05 6.68830164469984193e-06 -6.24196140510288014e-05 9.69016350838528565e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.67654325892752121e-01 -8.46864462824955394e-02 1.21450831052852232e-01 1.08055032490834133e-01 9.45616739415407609e-02 7.11320941908297330e-04 2.12511078507391553e-03 1.70582515936875470e-02 2.64931635386344861e-03 2.18064025574333555e-03 1.59932561322437446e-03 2.15845658955046184e-03 2.27419978233290333e-02 3.96413468664661567e-03 3.56106926010374240e-03 2.59990545962430694e-03 3.03905059423623201e-03 3.11069912527315307e-02 6.37131775233702822e-03 4.62383635655244651e-03 3.59636236081232411e-03 6.17591186421551520e-03 4.80324100201376808e-02 1.04848029426210711e-02 5.32240150754023644e-03 -1.76911719385717589e-05 -1.69381395814897815e-05 -9.11741056817430518e-04 -4.71091215613341857e-05 6.17099033772849394e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.27565858027677528e-02 -1.03934894915859624e-01 -1.96371946717433327e-01 3.03967099943896424e-01 -1.81996956816426053e-01 1.69024140400730119e-02 4.31019629144469203e-04 1.26413915592121242e-03 8.71073052748900199e-03 6.93545460899188879e-03 2.08052242569049944e-02 1.34971077451756971e-03 4.31588123035818883e-03 9.21180036173221452e-03 1.54199541076760083e-02 1.84259680460171389e-02 2.63204783691434749e-03 8.43915394317120739e-03 5.84012532135764866e-03 2.48697525804578053e-02 1.57093735726174591e-02 3.67507757349219873e-03 1.14238939699460324e-02 3.46662310439108372e-03 3.08011777513127784e-02 1.00797298090413438e-03 -1.73690169716654561e-05 8.47057556590328105e-06 -3.10423609983225002e-04 -6.49692747069250645e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +end +case collinear 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.39999999999999991e+00 1.30000000000000004e+00 8.00000000000000044e-01 6.99999999999999956e-01 2.60000000000000009e+00 1.39999999999999991e+00 1.30000000000000004e+00 5.00000000000000000e-01 2.70000000000000018e+00 3.10000000000000009e+00 2.79999999999999982e+00 2.20000000000000018e+00 +spins 15 0.00000000000000000e+00 0.00000000000000000e+00 8.00000000000000044e-01 0.00000000000000000e+00 0.00000000000000000e+00 -5.99999999999999978e-01 0.00000000000000000e+00 0.00000000000000000e+00 1.10000000000000009e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.99999999999999989e-01 0.00000000000000000e+00 0.00000000000000000e+00 5.00000000000000000e-01 +potential 5 -8.89976056331749921e-02 3.15495448828676750e-01 -1.05611294725650548e-01 3.15251539019029303e-01 -1.05226714498431601e-01 +forces 15 5.87141838484386575e-03 -4.01008473681468414e-02 -1.58664060337179273e-02 2.06903769495760323e-02 -1.65557325940442028e-02 -1.50650249492550806e-02 -1.68325511268236066e-03 6.81460876779533264e-02 2.11874215925238613e-02 2.22787528685610119e-03 -1.18656874910183924e-02 1.56351575452244422e-02 -2.71064155085936342e-02 3.76179775256105763e-04 -5.89114815477529991e-03 +virial 45 8.80612039323069862e-03 -1.27628589524993452e-02 -5.73917583021940018e-03 -8.70677383599903314e-03 3.21281665310120118e-02 4.70737202968213916e-03 -2.39060341916973434e-03 2.96729904565518586e-03 6.26064603587625501e-03 2.92101189452292423e-02 -1.84507982357927959e-02 -6.47082557426315996e-03 -1.76157572552985107e-02 2.72259275963131070e-02 1.82275379353624700e-02 -7.00595417112208352e-03 1.76507328705642723e-02 1.48510977354029423e-02 -3.52081361873915269e-02 -3.65337537300834507e-03 -1.20378292600159757e-02 -1.18459398118335862e-02 3.59911552732638182e-02 7.22575937332618767e-03 -1.49448661605531552e-02 1.12071366004307584e-02 -2.39258395908840439e-03 2.83971326701312884e-03 -5.07984516744795691e-03 2.63752035457747499e-03 -4.90688861371109310e-03 1.88980488439532690e-02 -1.49285621758863726e-02 4.89880006223654147e-03 -1.27543862292748954e-02 1.83125927659017890e-02 -3.24314221368601913e-02 -6.44470292556712388e-03 -1.35178149582539965e-02 -3.31622113747334635e-03 -3.56631039705994314e-03 -4.27338555043052775e-03 -1.41090643690367154e-02 -8.22145370180909531e-03 -6.03338891008083598e-03 +mforces 15 -3.04042717202605817e-04 -1.05383161850971727e-03 -1.21975805463681464e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -6.09617212848294343e-04 6.34673331631701578e-04 1.18316800530096286e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -6.24375057247498989e-04 3.65819010166202490e-05 9.90668379873406793e-03 +tau 15 8.43065294807773835e-04 -2.43234173762084659e-04 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -6.98140664794871801e-04 -6.70578934133123842e-04 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -1.82909505083101245e-05 -3.12187528623749494e-04 0.00000000000000000e+00 +descriptor 425 -9.66569040574016963e-02 -7.16298740671639372e-02 -1.73189969174782743e-01 4.76366185180938373e-01 -4.12470498393120277e-01 1.34087460383100817e-02 5.27635559719638950e-03 3.72521551461243820e-03 2.13110135221889017e-03 8.45895156176228701e-03 9.98854029181208032e-03 2.15408622475869163e-03 7.81295306505700587e-03 1.38590220109797361e-03 2.14753729129900650e-02 1.46478311468172633e-02 1.38738479170062261e-02 1.58711478660126769e-02 2.27768076142121191e-03 2.28236061717610392e-02 2.93962418547943326e-02 2.84879023537342631e-02 2.20832169080680575e-02 5.40172328181464691e-03 2.50571573319468520e-02 2.81989804142082959e-04 -3.54327218197930668e-05 8.37295302271673185e-05 5.66292471513821164e-06 -8.94117546733149142e-04 5.34857142854400114e-01 7.36501375805879571e-02 -4.29013767423223960e-02 -5.93149421770575586e-02 -6.79658444164838067e-03 -1.27954597431126187e-03 2.01968709104910103e-03 -1.48911195992080508e-02 1.67457731904936610e-02 -4.04714183976957118e-02 -4.63427054679241106e-03 1.11572414305096766e-02 3.73934704569106428e-03 4.65277511725393231e-04 3.53380832101800638e-04 6.98942392965125857e-03 7.22968172588896998e-04 3.88523560074015718e-03 6.13301089704879824e-04 3.91504700368765744e-03 6.67316907822396594e-05 -6.19357274814663367e-03 4.08051749385382185e-04 5.35929173741970209e-03 -1.57644302217018221e-03 1.11468391449348440e-03 2.72082343417201110e-03 -3.16075286894676108e-03 1.63270800876179367e-03 -2.21847075514990940e-04 4.14982271987483200e-04 -3.80455640856711206e-04 -1.57866175925590931e-03 1.97952753659080393e-03 -1.13127482194516930e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 9.21118667656189993e-02 -8.14884781847388245e-02 0.00000000000000000e+00 0.00000000000000000e+00 -1.44308933395845415e-06 -1.15776360807362397e-06 0.00000000000000000e+00 0.00000000000000000e+00 7.25435057545065442e-08 2.78664455656511986e-08 0.00000000000000000e+00 0.00000000000000000e+00 -3.23481863430668981e-01 -6.25519456753765857e-02 8.51240205412637368e-02 8.15468747031985464e-02 7.85428557155453400e-02 1.08520385650594199e-03 2.25565187138667246e-03 2.62300375686576673e-02 3.56218400246549214e-03 6.47919736489158040e-03 3.24120177481641326e-03 3.45992524584570445e-03 3.62884357741285468e-02 6.41520627434063757e-03 8.25179710454860063e-03 4.12119190671987427e-03 6.87815153668054364e-03 7.22165772550041746e-02 1.27083706069929855e-02 9.70001775216213294e-03 3.79518895268903715e-03 6.76040800978797152e-03 6.71064246207816739e-02 1.14815840210739043e-02 2.14924117281718521e-02 -4.98190639011998005e-05 -1.63240068267961694e-05 1.48189714530914669e-03 1.40789375474160956e-04 3.69467762617313488e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.28256597580786436e-02 -1.21321684924280374e-01 -2.51736097903013267e-01 4.41139871257841987e-01 -1.69534984766372604e-01 2.36483278288444135e-02 5.09077895784372167e-04 4.47456662717190309e-04 5.11256949154828728e-03 3.47069194175847646e-03 1.67476308446369779e-02 1.48822244535158394e-03 2.42360616812703749e-03 3.45420367220892295e-03 6.73791229793482480e-03 1.78383886569127431e-02 2.19744813218269433e-03 6.16423135505987652e-03 1.40912391900268642e-03 2.60579251694636749e-02 3.22463311903943908e-02 3.05329839939879081e-03 9.52283627664764730e-03 4.78958203400679187e-03 4.72957179029264291e-02 2.43362812275990588e-04 -1.25392048867713212e-05 6.68830164469984193e-06 -6.24196140510288014e-05 9.69016350838528565e-05 1.01121428570909999e+00 3.72253329266453298e-02 -9.08451901920691585e-02 -5.13050327151812480e-02 4.74554521536095508e-02 -7.98738856020705414e-03 1.99235782648391480e-02 4.92445502156595716e-02 -5.27365012165407002e-02 -6.61834922023582517e-02 6.11761552270423947e-02 1.50758389974228464e-03 8.86853318796493317e-03 2.49324039093528640e-04 3.27727754734796132e-04 2.34725545037978243e-03 9.87471834523533966e-03 1.36928723397620393e-03 5.25961144792427750e-03 2.90213156858008326e-03 6.94884266065265085e-03 -2.70770987421560961e-03 -6.03311150331142278e-03 5.95028245274563557e-03 -7.41850410840575424e-03 1.04222715015595147e-02 -4.01019729560592175e-03 2.50225735352134319e-03 1.75259381549651514e-03 -2.69589135212282630e-03 7.72058619235093052e-04 3.16180129195686071e-03 -5.24998621761030076e-04 -8.74721907988559302e-04 2.99664649701327250e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 8.27144059355810479e-02 -2.09726993587362687e-01 0.00000000000000000e+00 0.00000000000000000e+00 5.66003882555032023e-08 7.10495794506622243e-08 0.00000000000000000e+00 0.00000000000000000e+00 -3.49629368490270212e-08 -5.13332091443418895e-08 0.00000000000000000e+00 0.00000000000000000e+00 -2.67654325892752121e-01 -8.46864462824955394e-02 1.21450831052852232e-01 1.08055032490834133e-01 9.45616739415407609e-02 7.11320941908297330e-04 2.12511078507391553e-03 1.70582515936875470e-02 2.64931635386344861e-03 2.18064025574333555e-03 1.59932561322437446e-03 2.15845658955046184e-03 2.27419978233290333e-02 3.96413468664661567e-03 3.56106926010374240e-03 2.59990545962430694e-03 3.03905059423623201e-03 3.11069912527315307e-02 6.37131775233702822e-03 4.62383635655244651e-03 3.59636236081232411e-03 6.17591186421551520e-03 4.80324100201376808e-02 1.04848029426210711e-02 5.32240150754023644e-03 -1.76911719385717589e-05 -1.69381395814897815e-05 -9.11741056817430518e-04 -4.71091215613341857e-05 6.17099033772849394e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.27565858027677528e-02 -1.03934894915859624e-01 -1.96371946717433327e-01 3.03967099943896424e-01 -1.81996956816426053e-01 1.69024140400730119e-02 4.31019629144469203e-04 1.26413915592121242e-03 8.71073052748900199e-03 6.93545460899188879e-03 2.08052242569049944e-02 1.34971077451756971e-03 4.31588123035818883e-03 9.21180036173221452e-03 1.54199541076760083e-02 1.84259680460171389e-02 2.63204783691434749e-03 8.43915394317120739e-03 5.84012532135764866e-03 2.48697525804578053e-02 1.57093735726174591e-02 3.67507757349219873e-03 1.14238939699460324e-02 3.46662310439108372e-03 3.08011777513127784e-02 1.00797298090413438e-03 -1.73690169716654561e-05 8.47057556590328105e-06 -3.10423609983225002e-04 -6.49692747069250645e-04 2.08928571427499987e-01 1.49540048332757656e-03 -5.04579198971680937e-03 -9.75613828795229010e-02 1.12758349742273931e-01 8.30456782890214192e-03 -8.57730727852604180e-03 2.70412655412484394e-03 -4.49495289221238381e-03 -2.60029305607759505e-02 3.00330481942045792e-02 1.17751027259134621e-05 1.32419506861303790e-04 3.39182063520498533e-04 4.19270306896705276e-04 3.19420880001374408e-03 3.94845951470921500e-03 1.86329048956027912e-03 2.30278898347436841e-03 5.72449231505051722e-03 6.94824803542336365e-03 -2.06842145308881785e-04 -7.96216827686313565e-04 2.17575732704841998e-03 -2.42506188692313222e-03 2.73327896710018206e-03 -2.23130338847561498e-03 2.47875053054200231e-03 -2.76758986122019280e-03 -1.28801214585275289e-03 1.43784614586869018e-03 -1.62657024104229217e-03 5.55392630851656434e-05 -4.06736519184802941e-05 -7.31770445255312342e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.42392035720139945e-02 3.49602437274183081e-02 0.00000000000000000e+00 0.00000000000000000e+00 4.76454368084202563e-09 -2.99904666960329385e-09 0.00000000000000000e+00 0.00000000000000000e+00 -1.98309558785236962e-08 -2.54854733053756978e-08 0.00000000000000000e+00 0.00000000000000000e+00 +end +case noncollinear 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.39999999999999991e+00 1.30000000000000004e+00 8.00000000000000044e-01 6.99999999999999956e-01 2.60000000000000009e+00 1.39999999999999991e+00 1.30000000000000004e+00 5.00000000000000000e-01 2.70000000000000018e+00 3.10000000000000009e+00 2.79999999999999982e+00 2.20000000000000018e+00 +spins 15 8.00000000000000044e-01 1.00000000000000006e-01 2.00000000000000011e-01 2.00000000000000011e-01 9.00000000000000022e-01 -1.00000000000000006e-01 -2.99999999999999989e-01 4.00000000000000022e-01 6.99999999999999956e-01 5.00000000000000000e-01 -2.00000000000000011e-01 5.99999999999999978e-01 -4.00000000000000022e-01 -2.99999999999999989e-01 8.00000000000000044e-01 +potential 5 -1.05855434837585624e-01 3.15495448828676750e-01 -1.12108133404347055e-01 3.15251539019029303e-01 -1.00640447189407040e-01 +forces 15 -3.38800315168439302e-04 2.24125027974113392e-02 -1.91444392864795849e-03 -3.05931169357807897e-03 -1.48034582877570910e-02 -1.34279467366619255e-02 2.76742647819725150e-02 -1.11717252158093448e-02 3.19512223502286564e-03 -3.99519802077806865e-03 -9.05458915313700485e-03 1.12271862590131253e-02 -2.02809547524479272e-02 1.26172698592920997e-02 9.20082171273889186e-04 +virial 45 1.04828473263882064e-02 -1.27741694237554822e-03 -1.68548777492851616e-03 2.03037001886194595e-03 -1.22151335461653573e-02 -4.81666251509959599e-03 1.42904913098980098e-03 -7.14281112882283239e-03 4.57746250064830062e-03 -1.75913251608866318e-03 5.69307960749246451e-04 7.79054227667646398e-03 5.30111750541542408e-03 2.04106053870090551e-02 1.88820542450206519e-02 7.68924324758812287e-03 2.01390219067068242e-02 1.82568670772502960e-02 -3.57173392480393259e-02 6.42461074718052739e-03 -7.95475780002666104e-03 -2.64146143778134102e-03 -1.54613584227328866e-02 -5.24915741236255552e-03 -1.22693968333517887e-02 -1.52348726904857315e-03 -4.97469021314976556e-03 5.13273025339396581e-03 3.85219756449371080e-03 -5.59053740575047795e-04 5.01783090109565559e-03 1.31430124269123413e-02 -9.20665167210176112e-03 -2.30407937930747053e-03 -6.82498798334514427e-03 1.13248083951548069e-02 -3.45129860076293024e-02 -3.16213340959273920e-03 -1.20485766256006755e-02 -8.54946388526322751e-04 -9.54543353350943203e-04 -2.48321631163228801e-03 -1.39922302526742804e-02 -6.40781168344497793e-03 -5.03049427271112532e-03 +mforces 15 9.50924892920035868e-03 1.64302438976448931e-02 8.47447722662411466e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 4.01114401817137187e-03 -3.70578922698279207e-04 1.00589143093928537e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -5.75614499833528200e-04 1.28956947177739437e-02 3.89065341694728485e-03 +tau 15 -2.43860105686656732e-03 -4.87773199545922086e-03 1.21932702251958801e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 4.28297096964593699e-03 5.82547510553781643e-03 -1.49328393045906524e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.14837517993033409e-02 1.09576976691209147e-03 -5.33096223705963653e-03 +descriptor 425 -9.66569040574016963e-02 -7.16298740671639372e-02 -1.73189969174782743e-01 4.76366185180938373e-01 -4.12470498393120277e-01 1.34087460383100817e-02 5.27635559719638950e-03 3.72521551461243820e-03 2.13110135221889017e-03 8.45895156176228701e-03 9.98854029181208032e-03 2.15408622475869163e-03 7.81295306505700587e-03 1.38590220109797361e-03 2.14753729129900650e-02 1.46478311468172633e-02 1.38738479170062261e-02 1.58711478660126769e-02 2.27768076142121191e-03 2.28236061717610392e-02 2.93962418547943326e-02 2.84879023537342631e-02 2.20832169080680575e-02 5.40172328181464691e-03 2.50571573319468520e-02 2.81989804142082959e-04 -3.54327218197930668e-05 8.37295302271673185e-05 5.66292471513821164e-06 -8.94117546733149142e-04 5.76642857139900156e-01 -7.81713379023754457e-02 3.38396950238714633e-02 -1.76668050226569145e-01 5.68687549089528926e-02 -3.14154693788382192e-02 9.10214914530234169e-03 -2.65530653184888089e-02 1.17141926911111631e-02 -3.55075266034338283e-02 1.68807025332237091e-02 2.03896409796606726e-02 2.37967771087126915e-03 2.02072818961783647e-02 1.80103131434637123e-03 1.89227698277024819e-02 1.33915506890815747e-03 8.92348709449354398e-03 2.87174583494138966e-03 1.86136353995073195e-02 3.37275197282094078e-03 7.32336088457603580e-03 1.28694107402091960e-03 5.14003887817344671e-03 -2.39389417145511934e-03 1.16433171578438034e-03 3.98687211432695136e-03 -1.54325119429904413e-03 5.32491446974548690e-04 -1.64778744125221972e-04 1.66726949169157784e-04 -1.08884847931685325e-04 -2.13912958455993651e-03 9.04672554751614682e-04 -3.42152094816046805e-04 -9.18408358564746091e-07 -6.27475656268530007e-07 6.66809287346928456e-04 3.43314974430861195e-04 -1.82852762682735806e-07 -1.26261456955341788e-07 2.67013924189873949e-05 1.28266112888373526e-05 -1.62169651540012366e-01 6.83448667943597904e-02 -5.18842347162457051e-08 -3.10657219636635695e-08 -1.66198228161110539e-06 -3.57037997416570393e-07 -2.85368924547589180e-08 -1.99779911297807428e-08 1.00360327513866240e-06 8.50177755288578953e-07 -8.57289127910488234e-11 -5.80723929070285807e-12 -3.23481863430668981e-01 -6.25519456753765857e-02 8.51240205412637368e-02 8.15468747031985464e-02 7.85428557155453400e-02 1.08520385650594199e-03 2.25565187138667246e-03 2.62300375686576673e-02 3.56218400246549214e-03 6.47919736489158040e-03 3.24120177481641326e-03 3.45992524584570445e-03 3.62884357741285468e-02 6.41520627434063757e-03 8.25179710454860063e-03 4.12119190671987427e-03 6.87815153668054364e-03 7.22165772550041746e-02 1.27083706069929855e-02 9.70001775216213294e-03 3.79518895268903715e-03 6.76040800978797152e-03 6.71064246207816739e-02 1.14815840210739043e-02 2.14924117281718521e-02 -4.98190639011998005e-05 -1.63240068267961694e-05 1.48189714530914669e-03 1.40789375474160956e-04 3.69467762617313488e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.28256597580786436e-02 -1.21321684924280374e-01 -2.51736097903013267e-01 4.41139871257841987e-01 -1.69534984766372604e-01 2.36483278288444135e-02 5.09077895784372167e-04 4.47456662717190309e-04 5.11256949154828728e-03 3.47069194175847646e-03 1.67476308446369779e-02 1.48822244535158394e-03 2.42360616812703749e-03 3.45420367220892295e-03 6.73791229793482480e-03 1.78383886569127431e-02 2.19744813218269433e-03 6.16423135505987652e-03 1.40912391900268642e-03 2.60579251694636749e-02 3.22463311903943908e-02 3.05329839939879081e-03 9.52283627664764730e-03 4.78958203400679187e-03 4.72957179029264291e-02 2.43362812275990588e-04 -1.25392048867713212e-05 6.68830164469984193e-06 -6.24196140510288014e-05 9.69016350838528565e-05 6.18428571425399976e-01 -5.48416968914586730e-02 7.22475841401060137e-02 -1.51579337118842611e-01 1.87137321490419645e-01 2.16970877843698535e-04 -1.90942609488838001e-03 7.53181609805969945e-03 -1.92929542500169110e-02 -2.34695828658958022e-02 2.73877636907219613e-02 8.81928370923527709e-03 1.44630454420582623e-02 1.60671349425303667e-04 9.31018055902180708e-05 1.00971286374431143e-02 1.22092128368774290e-02 5.44544976661095331e-03 1.11123731648190543e-02 8.67903187644275889e-03 1.49026486303758046e-02 2.56652360257114426e-03 4.64197564320040310e-03 1.78146708878228156e-03 -2.09531763246593311e-03 2.57676030016694597e-03 2.73091601640426023e-03 -3.84183394605911973e-03 5.23035811213988684e-03 1.44668265480569829e-03 -1.95947275506910476e-03 2.62726031471167184e-03 -2.45606052312876192e-04 4.24883638366197391e-04 -6.10560260041813287e-04 1.02686322707539883e-07 4.98591398415716738e-08 1.39581908436114091e-05 2.23517851754251488e-05 -5.10480302362545731e-08 -2.73375846184233302e-08 -5.52234866211968424e-06 -8.92689931441016287e-06 -1.28043635267247879e-01 1.65353684877077495e-01 5.16002590191710608e-08 2.41077754268140003e-08 -3.75913206702972249e-08 5.63014544992516629e-08 -2.06806951855005302e-08 -8.98487367587937710e-09 3.32979829133530849e-08 -4.01120828901992568e-08 5.32051755982514452e-13 -2.65507969846976227e-13 -2.67654325892752121e-01 -8.46864462824955394e-02 1.21450831052852232e-01 1.08055032490834133e-01 9.45616739415407609e-02 7.11320941908297330e-04 2.12511078507391553e-03 1.70582515936875470e-02 2.64931635386344861e-03 2.18064025574333555e-03 1.59932561322437446e-03 2.15845658955046184e-03 2.27419978233290333e-02 3.96413468664661567e-03 3.56106926010374240e-03 2.59990545962430694e-03 3.03905059423623201e-03 3.11069912527315307e-02 6.37131775233702822e-03 4.62383635655244651e-03 3.59636236081232411e-03 6.17591186421551520e-03 4.80324100201376808e-02 1.04848029426210711e-02 5.32240150754023644e-03 -1.76911719385717589e-05 -1.69381395814897815e-05 -9.11741056817430518e-04 -4.71091215613341857e-05 6.17099033772849394e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.27565858027677528e-02 -1.03934894915859624e-01 -1.96371946717433327e-01 3.03967099943896424e-01 -1.81996956816426053e-01 1.69024140400730119e-02 4.31019629144469203e-04 1.26413915592121242e-03 8.71073052748900199e-03 6.93545460899188879e-03 2.08052242569049944e-02 1.34971077451756971e-03 4.31588123035818883e-03 9.21180036173221452e-03 1.54199541076760083e-02 1.84259680460171389e-02 2.63204783691434749e-03 8.43915394317120739e-03 5.84012532135764866e-03 2.48697525804578053e-02 1.57093735726174591e-02 3.67507757349219873e-03 1.14238939699460324e-02 3.46662310439108372e-03 3.08011777513127784e-02 1.00797298090413438e-03 -1.73690169716654561e-05 8.47057556590328105e-06 -3.10423609983225002e-04 -6.49692747069250645e-04 7.43785714281900101e-01 5.06948733191027890e-03 -4.84607053706286647e-03 -1.30376833326868030e-01 1.64400537766506483e-01 -1.17071571871904083e-02 1.21151993550077369e-02 3.90290530813584488e-02 -4.45332963801082157e-02 -3.74269654193785453e-02 4.41841930987717305e-02 1.45080526566661004e-02 2.01272243187965022e-02 4.35099150236527722e-03 6.96458565740448125e-03 5.97925962540294797e-03 6.21272615259960397e-03 9.60709949954346998e-03 1.42537840279281496e-02 8.50507451343612830e-03 1.20816071081288386e-02 -2.33405585746780360e-03 -3.19168600674040858e-03 3.38995649026104613e-03 -3.88193895203846340e-03 4.51295827032700998e-03 -3.44281360497040870e-03 3.94899060301455093e-03 -4.59760292841089862e-03 -2.02113206027595711e-03 2.32854709174501549e-03 -2.72590615849513298e-03 3.41547252301802769e-05 -2.40802301322220860e-05 4.54998569387058654e-06 -5.80623256790677846e-08 5.67231383948966303e-09 -5.72843738592007562e-06 -2.00662334587280675e-06 3.76737002412331378e-08 -4.86156619720939518e-09 3.68261851836484520e-06 1.21763233266768470e-06 1.97941407484336085e-02 -2.11820404039877903e-02 -7.58342126164474782e-09 -9.24493274308724034e-09 4.49411063477984044e-08 5.15479534623551190e-08 4.78017728393931057e-09 6.05785719164023019e-09 7.65552197424720801e-09 6.60525301766986812e-09 9.31959643333765604e-14 -1.75702214612999011e-13 +end +case chiral_soc 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.50000000000000000e+00 1.10000000000000009e+00 1.10000000000000009e+00 4.99999999999999944e-01 2.70000000000000018e+00 1.59999999999999987e+00 1.60000000000000009e+00 6.99999999999999956e-01 2.60000000000000009e+00 3.00000000000000000e+00 3.09999999999999964e+00 2.30000000000000027e+00 +spins 15 1.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.00000000000000000e+00 5.99999999999999978e-01 -2.00000000000000011e-01 6.99999999999999956e-01 -4.00000000000000022e-01 8.00000000000000044e-01 2.99999999999999989e-01 +potential 5 -1.05261155485234015e-01 3.16935531381510094e-01 -1.09947022970982716e-01 3.16237411060139140e-01 -1.06837254703782678e-01 +forces 15 -2.91024871164516190e-03 1.53933825374774798e-02 -1.02729856335568226e-03 1.41879017276042643e-02 5.84557898636933401e-03 3.61601718319009419e-03 1.82789580776315276e-02 -9.63728668408765470e-03 7.95534625102703452e-03 -7.90274340182147567e-03 4.86224281013486991e-03 3.15502112224111224e-03 -2.16538676917691526e-02 -1.64639176498940255e-02 -1.36990859931025617e-02 +virial 45 1.20343795815340566e-02 -2.52736419784799042e-03 1.14950772110046832e-03 9.99354068077409636e-04 -9.74472242905046436e-03 -3.42879869612929813e-03 4.06888062017395427e-03 -5.28490901385644980e-03 5.26020476757169640e-03 3.06951624748062930e-03 -1.79076703957027593e-02 -7.91840853255832561e-03 -1.11073406636420322e-02 -1.65167489938441332e-02 -1.13488614593587334e-02 -5.61358423777110448e-03 -1.24078402058409969e-02 -5.90032425839102925e-03 -2.29344327722917560e-02 2.36969741038107681e-03 -4.92155063680474285e-03 -5.75650410073244405e-03 -8.21255169966161880e-03 -1.73382462669622109e-03 -8.31425811399774499e-03 -1.12154409582987326e-03 -2.01365669632114393e-03 -2.39294342264956793e-03 9.95769232045561753e-03 -4.28095600948746532e-03 1.18718705377005018e-02 -8.18742832169144785e-03 4.71437429000018567e-03 -9.52267009882595827e-03 6.35506458032233761e-03 -6.56438810073092446e-04 -2.56835275061139331e-02 -8.31583292939525043e-03 -8.08739920583877343e-03 -6.61666006883818159e-03 -9.17027792788233098e-03 -4.03178608493867142e-03 -9.02662059245407447e-03 -6.36208982525712091e-03 -4.31575352929875443e-03 +mforces 15 1.35250856933336813e-02 1.50372691377593584e-02 3.14793543241324997e-02 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 1.63063429608512125e-02 8.65587094925858794e-03 -1.83792893158459241e-03 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 2.71249163011594557e-04 -6.21590366980544033e-04 6.17301453134778792e-03 +tau 15 0.00000000000000000e+00 -3.14793543241324997e-02 1.50372691377593584e-02 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -8.65587094925858794e-03 1.63063429608512125e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 5.12488873517239363e-03 2.55058056144259358e-03 3.16368163829419747e-05 +descriptor 425 -1.16146870932738511e-01 -5.44997247220408779e-02 -1.67922932658313179e-01 4.63890345476966448e-01 -4.42590674784521410e-01 1.12487733029452072e-02 6.48297996058465591e-03 6.07899492453601795e-03 2.34261182721013685e-03 8.62757005584224163e-03 9.06070918055255740e-03 4.96465951194150802e-03 9.20271364617481456e-03 1.53408857343331870e-03 1.97005493326668085e-02 1.08315265142348797e-02 7.54172563370391919e-03 1.09898443130773942e-02 8.82051915877943922e-04 1.64129589247990447e-02 2.02501310326845541e-02 1.60820619832233586e-02 1.85383061168941758e-02 2.58487947783608710e-03 2.19350544240077168e-02 1.97254594968305802e-04 -9.38271106184100970e-05 2.84438868965413172e-05 -1.79561953282346376e-05 -8.71260723233180812e-04 8.35714285709999949e-01 -6.41692711337840949e-02 2.56527856540059301e-02 -2.41529587373726345e-01 5.52445034755327247e-02 -1.52346416621281806e-02 9.12092862170566995e-03 -4.23039106903051465e-02 1.39070676609094300e-02 -4.10028300880482116e-02 1.77276423166710557e-02 3.06866039249301392e-02 1.77077814536572399e-03 1.66470393911055947e-02 1.82744252386906648e-03 2.06089500026879618e-02 1.64337719970662310e-03 1.33118169315784036e-02 2.05526165383648025e-03 2.04261685377009269e-02 3.16965980427864240e-03 9.02901622721370527e-03 8.47929838142336004e-04 5.91311986941374466e-03 -2.47265954823361550e-03 1.03622226421627543e-03 1.70637743429178664e-04 4.90312653802850676e-05 -7.08822982159953990e-05 8.41748831909509398e-05 2.41815014073600536e-05 -3.49504159004598801e-05 -2.75756579090020301e-05 -7.92016471130409710e-06 1.14449111950223188e-05 -1.56506394921655757e-06 -1.09817010863428486e-06 4.98294505133348490e-04 2.61346992320729359e-04 -6.13939119168914977e-07 -4.28361491708342751e-07 -4.02609730662888219e-04 -1.99534567619362636e-04 -1.78674364607121522e-01 7.11725462278334359e-02 7.35267552067430261e-08 5.46170617783148532e-08 -1.88486194983496149e-07 -2.39934476333086008e-07 -1.26253983694043529e-07 -9.04388774174253511e-08 4.29281774319760039e-07 4.70183231138567086e-07 -7.81438385020957173e-11 -1.33895954044645821e-11 -3.32923829386318204e-01 -3.60611363215902342e-02 8.98369845801973432e-02 1.17017830520669677e-01 1.42581913862859927e-01 2.94672959340922674e-04 1.89304741933513663e-03 2.03207905394245519e-02 4.37293532659051125e-03 3.33316492609661737e-03 6.95568410948279887e-04 4.60237073751297576e-03 3.23123290917254058e-02 4.24067973016666912e-03 5.19104368881810607e-03 7.44570850637201365e-04 8.36650883667493413e-03 6.28581995094227575e-02 7.81078617537373648e-03 4.76439050657084025e-03 6.93315995277122015e-04 7.95033268072797318e-03 5.43935700603309299e-02 7.90235673001788742e-03 7.75503922682841285e-03 -1.46756778118909190e-06 -2.09170633365566446e-05 9.58894372181939196e-04 4.04851149140820709e-05 8.70889481059250177e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.18866632033709423e-02 -1.25616904456226947e-01 -2.41526850944396632e-01 3.60985083274788621e-01 -1.11385168368811058e-01 1.91964091946690181e-02 1.04766062835099719e-04 8.92697179342440660e-04 5.38899239582176556e-03 2.74736612790413325e-03 1.47928463806994651e-02 3.07116445798808098e-04 1.07802090428069661e-03 4.67766462734487808e-03 5.99573572176860092e-03 1.74647998550215740e-02 4.21860436653466182e-04 2.00647852058887053e-03 2.67208452180241023e-03 2.44607362094166857e-02 2.98471501693943451e-02 5.22102758267767786e-04 3.24930667892137093e-03 3.62337223857072625e-03 4.48871182744859862e-02 1.22580778029987450e-04 -1.44090952284939391e-06 -2.26742764821762819e-06 -9.29342291003885235e-05 8.60763023606210484e-06 8.35714285709999949e-01 -4.60168533213952471e-02 8.06768463670283209e-02 -1.52708577987480248e-01 1.96937776922481961e-01 2.14730092547658685e-03 9.50703401503696227e-03 3.98981400057537711e-02 -5.25758246668542942e-02 -3.00812493903905541e-02 5.56021669331724089e-02 1.02659269273247498e-02 2.20417546635660044e-02 3.20144882334043952e-04 3.46408036855899417e-05 1.87408400693869770e-02 2.32923695649522519e-02 1.44500029835735520e-03 1.04485568865076116e-02 6.73628801778893005e-03 1.46431770260743565e-02 3.18940032413939827e-03 6.73477728923505513e-03 1.95118840372955149e-03 -3.63903072105661082e-03 6.89159865191405884e-03 1.20693933238001194e-03 -1.87899148799378904e-03 2.74565975278690368e-03 5.01494821664253353e-04 -7.80564081282615380e-04 1.14034132943745216e-03 -3.22943579904155309e-04 5.02546619337916438e-04 -7.34026578662448073e-04 -6.85175731646727414e-07 -4.21172661441034197e-07 -1.58312245779297439e-04 -4.26648176002612670e-05 3.91177991541181266e-07 2.32009405465453455e-07 1.30700518192024154e-04 4.20685949807909245e-05 -1.28130363383395784e-01 2.23834426990445534e-01 2.29747468904408288e-07 1.33193774084855915e-07 -4.21266449749810157e-08 -2.84434983157643191e-07 -1.20705326550793748e-07 -7.09722821896954628e-08 2.43491265854640046e-07 2.14400323995645269e-07 -9.13323737536577222e-13 4.69616812675891041e-13 -3.15630608757079101e-01 -4.56786953069863860e-02 1.08898204883334057e-01 1.03850900790870185e-01 1.43502492981653906e-01 2.64068579772752600e-04 1.54732304685143069e-03 1.98014878754102577e-02 4.66300887546951953e-03 2.38529576629519392e-03 7.31106904124441360e-04 2.76924807947468441e-03 2.43312837803217712e-02 3.75815941067826186e-03 3.38889385780084254e-03 1.04523358726793395e-03 5.88523464418498447e-03 3.49855813292192508e-02 3.79937708249956626e-03 3.99790283129961357e-03 1.17618671092358396e-03 9.38253267535743216e-03 5.19433107924765491e-02 7.00209020655463612e-03 4.61038068286980397e-03 -1.25835806920423249e-06 -5.12714592657406933e-06 -5.45455664370362464e-04 -5.01244973274503024e-05 4.02902454321699984e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -5.11808075400997722e-02 -1.37066153791403689e-01 -2.07303648244596905e-01 2.73228777561494884e-01 -1.25746582549394997e-01 1.57008542988412471e-02 1.14368716159972403e-04 1.42979227276845977e-03 8.08753275186715158e-03 6.10999976565029627e-03 1.78895726978526015e-02 4.26167908245384962e-04 2.47623504322480158e-03 8.59984374662286881e-03 1.40948791196409025e-02 1.46001067057306508e-02 9.91204624020871087e-04 3.19652223794574929e-03 5.89224507814080020e-03 2.20810095477000888e-02 1.29641469082683470e-02 1.68736876071746175e-03 3.44935802032881158e-03 4.23321839790373206e-03 2.52016225046176982e-02 7.50311306208062629e-04 -3.12213089651221140e-06 -3.24046161224581978e-05 -2.62628950558281820e-04 -5.53687863570044439e-04 7.43785714281900101e-01 -5.87788204337757331e-02 8.53102402078644156e-02 -1.21660680708668312e-01 2.08331898113398611e-01 -1.84116025078351585e-02 3.77122025640203792e-02 -4.03841871858093455e-03 8.97274062068612044e-03 -4.83141795818837899e-02 8.00247834951555437e-02 8.52340732050803525e-03 2.26291960199120137e-02 5.32829792368607301e-03 1.44206345979719739e-02 3.22142063871322989e-03 6.44891258472759122e-03 5.04694596510034486e-03 1.43059024638014492e-02 5.36720494738624106e-03 1.41818162094257683e-02 5.02213485047043988e-03 1.17429334482514035e-02 3.99213664719228964e-03 -6.52622685711356978e-03 1.07455833706514656e-02 1.13869182641656653e-03 -8.83670584137855844e-04 -5.04508204435677861e-05 3.84780622694375866e-04 3.48735448483417532e-05 -1.06598405432114336e-03 -4.92752434750358599e-04 1.01376539829885399e-03 -1.96706269092837387e-03 2.32694993555003100e-07 1.21182837880928531e-07 -3.33373872701318188e-05 -7.32520210049182309e-06 -1.05700205049464622e-07 -5.41368163119533981e-08 2.63977929824352175e-05 6.03053202542480283e-06 -1.64342023641681129e-01 2.38474436826866060e-01 -2.31379132841809208e-08 -2.09043890066783929e-08 1.82800069320478186e-08 -9.83404859632325185e-08 2.27821583984367140e-08 1.60796612550344440e-08 -2.19103252107471177e-08 -2.20489457829079475e-08 1.20380747717529286e-13 -2.06761301812178270e-14 +end +case strained 5 +types Fe Ge Fe Ge Fe +cell 9 1.42099999999999991e+01 0.00000000000000000e+00 5.60000000000000012e-02 1.56000000000000000e-01 1.28309999999999995e+01 0.00000000000000000e+00 -8.99999999999999967e-02 1.34999999999999981e-01 1.51200000000000010e+01 +positions 15 1.02099999999999991e+00 9.95999999999999996e-01 1.01200000000000001e+00 2.44679999999999964e+00 1.29030000000000022e+00 8.16000000000000059e-01 7.33299999999999952e-01 2.57880000000000020e+00 1.41399999999999992e+00 1.30929999999999991e+00 5.17800000000000038e-01 2.72680000000000033e+00 3.16689999999999960e+00 2.78339999999999987e+00 2.22999999999999998e+00 +spins 15 8.00000000000000044e-01 1.00000000000000006e-01 2.00000000000000011e-01 2.00000000000000011e-01 9.00000000000000022e-01 -1.00000000000000006e-01 -2.99999999999999989e-01 4.00000000000000022e-01 6.99999999999999956e-01 5.00000000000000000e-01 -2.00000000000000011e-01 5.99999999999999978e-01 -4.00000000000000022e-01 -2.99999999999999989e-01 8.00000000000000044e-01 +potential 5 -1.05816422368456564e-01 3.15258241658601057e-01 -1.11572579453972642e-01 3.15129367316841824e-01 -1.00329068079353850e-01 +forces 15 -1.50372417328934090e-03 2.23247794386574917e-02 -1.57793091574500843e-03 -1.85187232006642222e-03 -1.42421605207927252e-02 -1.33527923251030908e-02 2.69425897028728566e-02 -1.16870669856589289e-02 2.97721141813642003e-03 -4.20911475905227320e-03 -8.64968388044900366e-03 1.10301469575919027e-02 -1.93778784504648194e-02 1.22541319482431695e-02 9.23364865119778635e-04 +virial 45 1.06984862048379679e-02 -1.71318041183432588e-03 -1.90305501944546093e-03 1.81883619984906210e-03 -1.19172344278117119e-02 -4.79105737363776443e-03 1.18229639374709157e-03 -7.08847443171059174e-03 4.37100425165068418e-03 -1.01355801161781903e-04 1.11234827153977849e-03 7.92641369916853578e-03 5.80219195873388823e-03 2.00756178370734457e-02 1.87969709989029912e-02 7.72367266519890204e-03 1.99839306095292227e-02 1.84242361508693067e-02 -3.51416141829663797e-02 6.71134785464157398e-03 -7.81850874122951532e-03 -2.42319465902297295e-03 -1.64741165302414103e-02 -5.12537231943720195e-03 -1.21501077924941608e-02 -1.43344190923093938e-03 -5.18513862226134374e-03 5.40844890546438896e-03 4.06875416960826054e-03 -7.06661949631291059e-04 5.12676975232219737e-03 1.27858891485902355e-02 -9.02802434346857557e-03 -2.26623985521914872e-03 -6.67147723187885150e-03 1.14735305215065558e-02 -3.40522248895286372e-02 -3.32093529772592216e-03 -1.22317029790578301e-02 -8.48099558552584554e-04 -1.12059921786027681e-03 -2.69410742621631425e-03 -1.41157793174337652e-02 -6.60421970810213914e-03 -5.23049160735967154e-03 +mforces 15 9.69157277563400046e-03 1.61208947669035131e-02 7.73198331956024675e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 4.39336200774854274e-03 -3.38232722764101983e-04 8.14448798830309101e-03 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 1.23824695861665841e-04 1.21351536201276550e-02 2.17857344166383360e-03 +tau 15 -2.45098062142467795e-03 -4.24727210052139748e-03 1.19275585359594118e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 3.49455810125610814e-03 5.51869980191490705e-03 -1.65587498627018650e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.03616949286012752e-02 9.70489133354866156e-04 -4.81691403929256252e-03 +descriptor 425 -1.02276431807068691e-01 -7.54024624507977914e-02 -1.74108507775408289e-01 4.82777274865200334e-01 -4.11214724871681314e-01 1.34738727101999401e-02 5.29161679376475343e-03 3.85557511675083337e-03 2.18093624090613626e-03 8.27483415489234722e-03 9.92285227225611459e-03 2.02467380472679415e-03 7.52725123365514774e-03 1.38280749397188380e-03 2.11046946327470772e-02 1.45860681730504028e-02 1.35476559703624124e-02 1.64728559494597068e-02 2.30881175333827633e-03 2.24914212504507792e-02 3.00881927297188163e-02 2.82848634042846998e-02 2.39373617765167995e-02 5.44112669717587011e-03 2.45434115157715411e-02 2.80994406810357821e-04 -3.19698978421215440e-05 3.93886041180352832e-05 5.86150942490222477e-06 -8.73283161412617627e-04 5.76642857139900156e-01 -7.81118897513177202e-02 3.41645106861937983e-02 -1.72266012794783124e-01 5.54241197974436745e-02 -3.01228687283493675e-02 8.40259242843150768e-03 -2.60586499417139288e-02 9.88265730116997913e-03 -3.53404449043406635e-02 1.69830881847647906e-02 1.97442962561476254e-02 2.43369838928776195e-03 1.93032813309335673e-02 1.89192369409778380e-03 1.83994455796600356e-02 1.32073588531127217e-03 9.04563994830326346e-03 2.76497972396138898e-03 1.83756636254172774e-02 3.26417854752583496e-03 7.17922736322999192e-03 1.32032986296747772e-03 5.10744434441655435e-03 -2.41261028040008589e-03 1.19474633383256142e-03 4.00626139605889976e-03 -1.55936859238711332e-03 5.34595944251653986e-04 -1.26732520565525669e-04 1.34646893818330911e-04 -8.80339930695078949e-05 -2.12529882849427521e-03 8.93070939647365274e-04 -3.31158106145614775e-04 -7.94116167115508757e-07 -5.40158274508111851e-07 6.46757827534967717e-04 3.32989567469542012e-04 -1.47242205019660791e-07 -1.01537006653967536e-07 2.23845617546840951e-05 1.08243082500328970e-05 -1.62021145994210886e-01 6.89574776359108688e-02 -2.60043729310580021e-08 -1.15404160163779293e-08 -1.73467865398784715e-06 -3.68385751877792973e-07 -2.28209580158653667e-08 -1.58477352826158307e-08 1.01883409565324113e-06 8.32290049476242437e-07 -7.46151556888272473e-11 -4.06298216678654016e-12 -3.21697946179745120e-01 -6.34383644000802438e-02 8.79640348992093701e-02 7.97233359752247961e-02 7.73705881143963159e-02 1.00526849838234486e-03 2.30155259385825001e-03 2.58820437024729448e-02 3.51107953757774996e-03 6.32656288759144390e-03 3.06353392545862966e-03 3.50234692136121512e-03 3.60723361385138150e-02 6.48709267592078361e-03 8.10385304634980361e-03 4.04578602958585373e-03 6.87964848152918668e-03 7.25901495815683001e-02 1.31021099187478875e-02 1.00400371622792126e-02 3.86310112042774229e-03 6.76016559399578512e-03 6.77164359276463956e-02 1.19590206219860329e-02 2.18013056582773875e-02 -4.73392889238781646e-05 -2.23644741369774499e-05 1.36377345582134680e-03 1.36336713352059772e-04 1.14945932989427867e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.57175498266946534e-02 -1.23933679626611018e-01 -2.52551548798289338e-01 4.45057143540657452e-01 -1.72401023089740091e-01 2.39332976753160488e-02 5.14759296181932003e-04 4.58331543391576391e-04 5.18536150871397577e-03 3.57384440858600971e-03 1.66266114665768842e-02 1.54298554397060204e-03 2.42432223396619887e-03 3.43633756806423956e-03 6.91106512887552232e-03 1.74417319869930830e-02 2.45306243639701075e-03 6.05812419309381851e-03 1.39518488438337518e-03 2.67525759022875301e-02 3.18976348104379262e-02 3.60632540898578758e-03 9.26610500015421883e-03 4.97987359655068570e-03 4.81263454199324925e-02 2.56426370576835901e-04 -1.56566830546968905e-05 3.45221783200958593e-07 -6.14519529589145435e-05 1.02983670214488386e-04 6.18428571425399976e-01 -5.30419851018179359e-02 7.14337149952286032e-02 -1.48249553628855363e-01 1.88506544921065999e-01 -1.40125241616919022e-04 -1.62145681912785264e-03 7.87639213061083754e-03 -1.96987578079838611e-02 -2.20372108265995577e-02 2.66937043999528612e-02 8.70119803925037578e-03 1.49412805006459825e-02 7.07026534723371433e-05 1.85322648860815933e-04 9.70115719589455250e-03 1.28410124272194479e-02 5.42091477412187054e-03 1.13043369517411285e-02 8.41160387933774338e-03 1.52320914139005732e-02 2.46037828247629717e-03 4.66158935375966896e-03 1.59631047838450961e-03 -1.95982825383922074e-03 2.49649395208534006e-03 2.62667127796709088e-03 -3.71897818662343801e-03 5.13632048931737892e-03 1.37563530311840695e-03 -1.88469836352072521e-03 2.56215236839162953e-03 -2.54119527725032372e-04 4.28072329724274296e-04 -6.29232703367129157e-04 1.24660948633937143e-07 6.51394461626660221e-08 2.93144572035039746e-06 1.65234876634393180e-05 -6.10895798658475686e-08 -3.37412658636210810e-08 -2.19650612756111142e-06 -7.11714088433286413e-06 -1.23441301974982431e-01 1.63206800205412311e-01 5.24043860610003759e-08 2.54864024216452883e-08 -7.47515642760732499e-08 2.64147978102450458e-08 -2.29185417158077419e-08 -1.08561882145232486e-08 4.58644526689789436e-08 -1.75767110435306673e-08 4.94866856105745329e-13 -2.04127962099457801e-13 -2.67307980043016757e-01 -8.48438114131245674e-02 1.22729295432109670e-01 1.05943573097951063e-01 9.38456546664994395e-02 6.56672626348225093e-04 2.13241618265598001e-03 1.75142362898076595e-02 2.64525865591000182e-03 2.41395862047906907e-03 1.59634187457638834e-03 2.11936101991179633e-03 2.32820869033610184e-02 4.02661774033554690e-03 4.05725871239115583e-03 2.66385509483321433e-03 2.99038338381907775e-03 3.16427313545239730e-02 6.55882580351152458e-03 5.37867195868666284e-03 3.64092044458291320e-03 6.12397947418405995e-03 4.83251750478546904e-02 1.07324327223637331e-02 6.20975876993596146e-03 -1.67153010117699515e-05 -1.60099601889987002e-05 -9.54889019689022004e-04 -4.79243237786853920e-05 7.39907258974648735e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.68110452036635172e-02 -1.09830927958438421e-01 -1.93928679064428122e-01 2.99724702387080599e-01 -1.76778817747582195e-01 1.65683086030372108e-02 4.58742546940883148e-04 1.24090287790347940e-03 8.64662500161532226e-03 6.77836203226294710e-03 2.05818206126585565e-02 1.37809699317148547e-03 4.19674696880101544e-03 9.19171956297653789e-03 1.52059241325971824e-02 1.84321586640518384e-02 2.65888263708931620e-03 8.18704175522314351e-03 5.84793338716114216e-03 2.48754003662868713e-02 1.56882834461566090e-02 3.72148364162350198e-03 1.10639920151365725e-02 3.37549779717411218e-03 3.13648292565695541e-02 9.95465805260724920e-04 -1.80278335460533054e-05 5.24920625804457099e-06 -3.09431705378305502e-04 -6.37105912691158984e-04 7.43785714281900101e-01 6.85865433853794122e-03 -6.40385419435899206e-03 -1.25013263993399043e-01 1.61161876296296386e-01 -1.21591992391065652e-02 1.26229067212132069e-02 3.69059924506374634e-02 -4.33649788461209981e-02 -3.56006544803387157e-02 4.32843796837153669e-02 1.34531095253204950e-02 1.95599345378247580e-02 4.10709616113443237e-03 6.80658189036609934e-03 5.61574064341637674e-03 6.28103537295120196e-03 8.94676548547942985e-03 1.38371646209056749e-02 8.03631947784662001e-03 1.19234286790332530e-02 -2.49846587967388805e-03 -3.43010413437815510e-03 3.13719905987538657e-03 -3.70143341825257240e-03 4.42002753411121704e-03 -3.15084804620171599e-03 3.73436230331108043e-03 -4.47575730001083943e-03 -1.87187146081188474e-03 2.22139650507751285e-03 -2.66917390556627252e-03 -8.62012637299303031e-06 1.20370413119665482e-05 -2.34664270529355409e-05 -6.29814203966394844e-08 -2.05573953081755301e-09 -3.98244183897372422e-06 -1.26799783927164333e-06 4.16167668991562442e-08 9.67268962545854541e-10 2.68395821832895742e-06 8.31163257247103858e-07 2.40260720854602802e-02 -2.49443784026108055e-02 -7.15948092591315907e-09 -8.98027292210516538e-09 2.13264942999514302e-08 5.18393570216644192e-08 4.65848932992755244e-09 5.94137051058537145e-09 9.20069797024334592e-09 5.48052576136640852e-09 3.30195256365197961e-14 -1.06421908601455132e-13 +end +case random_multitype 8 +types Ge Fe Ge Ge Fe Fe Ge Fe +cell 9 1.30000000000000000e+01 4.00000000000000022e-01 -2.00000000000000011e-01 0.00000000000000000e+00 1.40000000000000000e+01 2.99999999999999989e-01 0.00000000000000000e+00 0.00000000000000000e+00 1.35000000000000000e+01 +positions 24 1.05195795123286806e+00 7.54513157485344976e+00 1.92678016605364433e+00 6.46852031811661554e+00 3.67791605244682529e+00 1.05287067051035566e+00 4.81735914385441433e+00 2.66519633158947888e+00 4.46326047297769435e+00 1.31815556951734236e+00 7.47518901279024117e+00 5.42123896216220835e+00 6.89722237837808461e+00 4.40524688937426134e+00 2.81634767538512243e+00 7.91697690449841840e+00 5.61941046163939095e+00 7.59164543829853056e+00 7.22363391762259788e+00 1.69287733412652353e+00 7.21909484608720842e+00 1.96643034124545912e+00 3.58552152099393107e+00 3.24131466612851726e+00 +spins 24 3.42956689606492948e-01 -1.44334109384587284e+00 -9.20576318816501371e-01 -7.93035969575581312e-01 -8.50622373758950362e-03 -1.58959621466146922e-01 5.74721063246211528e-01 4.25502328712981936e-01 8.60292342154923562e-01 -5.68052435501097297e-01 6.94785435747145463e-01 1.51775094776792541e+00 -3.21782166655971369e-01 7.04734259188120715e-01 7.16111647147331332e-01 7.38660791723244614e-02 -3.32854884286343966e-01 4.08657239828918162e-01 1.49528411107386322e-01 -7.40695736034854835e-01 1.30976057471167306e-01 -4.33378437932692290e-02 2.65331202826330936e-01 -1.14193824659042251e-01 +potential 8 3.04100791523011948e-01 -1.06038527832739482e-01 3.12958722714717252e-01 3.03895029320121246e-01 -1.09143822299465648e-01 -1.02037788463550272e-01 3.05038059901286296e-01 -1.02481328483130796e-01 +forces 24 -1.42421694266469019e-04 1.31009871615256129e-03 2.12349558818347717e-03 9.22919165501626202e-04 2.34669279807718728e-03 -1.66822374644423101e-03 -8.43253342821403615e-03 -1.28784698216722095e-02 1.63116572825877104e-02 -2.95400256342679855e-04 6.76788002767082135e-04 -2.19184921804832337e-03 1.10999557577180774e-02 8.79310262472150599e-03 -1.17567123309644944e-02 4.26204100708472934e-04 4.39685226004785405e-04 -1.25112412047491970e-05 -1.36585870378367149e-03 -1.19510326870443445e-04 -8.06279161513752700e-04 -2.21286494132131922e-03 -5.68387219180469840e-04 -1.99957717259563678e-03 +virial 72 6.13495204177357591e-05 -2.81975592285458210e-04 -2.65301894728190639e-04 -3.70797816167965969e-04 1.24930473067156331e-03 -2.29582185246444037e-04 -2.14054403044207147e-04 -3.23800672957009030e-04 -4.34291108402601322e-03 2.94284775312438724e-04 7.52572974055022476e-04 -3.50599714279105877e-03 9.54161463649198707e-04 2.06607676777635380e-04 -3.35191354559682096e-03 -2.82497660571854941e-03 -3.14486864193760842e-03 3.61059101647773174e-03 2.06436789776517186e-02 1.70978527399043879e-02 -1.90780316518944643e-02 1.72596455756655921e-02 1.40113103269357830e-02 -1.34374776354541803e-02 -1.86564284138675505e-02 -1.32654360315097794e-02 1.93624976911840399e-02 -2.26994821179410633e-05 -2.49923459602523559e-05 -3.63512083799937609e-04 -1.13005226239712301e-05 1.81822445724815884e-04 2.25035582408029955e-04 -3.47605064781873242e-04 1.75633881439752910e-04 -4.39966120770949112e-03 3.54050951401279571e-03 3.50427022152697719e-03 -4.36419669874798730e-03 4.18151960925617489e-03 3.59047620937682143e-03 -5.23926550499975892e-03 -2.73522021106519788e-03 -5.12725218866331121e-03 1.45233480718921174e-03 8.54764384097605003e-04 1.95595577722399100e-03 5.03548516570048493e-04 1.94572181077122194e-03 8.38812521953176404e-03 1.01764168424353803e-03 5.04573968129959794e-04 1.02894797843225438e-03 -6.91961912732876961e-04 -1.80077938187104885e-03 -7.54437671106844196e-04 -1.76636587553063041e-03 -5.71018341912917643e-04 -6.74766176280634788e-03 -9.90699848123145115e-04 -1.78499348210975849e-03 -1.38102601586460915e-03 1.34076525132651890e-04 6.95226917543859298e-03 -4.69158052224356598e-03 5.02865349467793415e-03 -4.70407765177315029e-03 7.33756798664136900e-03 -1.41397480033486449e-03 4.98204481562904838e-03 -1.38080762256262033e-03 2.62292140439877213e-03 +mforces 24 -0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 5.27825832416553217e-04 1.46985958636412142e-02 1.40416116493003555e-02 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.23171558132934116e-02 -1.01059716145359985e-03 -9.57857333301483094e-04 -2.11242389241953496e-04 2.03494493434557173e-03 -3.84066741919522354e-03 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 1.92715485507890757e-03 -4.05246279928198755e-03 2.44341451496812379e-03 +tau 24 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 2.21704214424298844e-03 1.10516001141856973e-02 -1.16520254174973248e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 4.86655196988254466e-05 -9.12868014568493473e-03 9.00551382161490083e-03 4.46789929325057075e-04 1.97369311938358743e-04 8.00003426041893419e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.85547885921309475e-04 -1.14176867039807503e-04 -3.35709315957372632e-04 +descriptor 680 -3.44114736151920064e-02 1.86180867479240064e-02 5.70409350194572770e-02 -4.11230975355890566e-02 5.10596697295911672e-02 1.45173245391687697e-05 6.09988458476464626e-05 4.23089609772806766e-05 1.21730760932601450e-04 1.86173006913540034e-04 1.88642277944261757e-05 7.02667722732145425e-05 4.84360678400616883e-05 2.12205904947975285e-04 4.61464312709406247e-04 2.69224325439909480e-05 9.77443034040588666e-05 6.72353666323891779e-05 3.16878853930088354e-04 7.16291139035507693e-04 4.62116267771717240e-05 1.84093443199888140e-04 1.27049940788585798e-04 4.42020630691291510e-04 8.19652402777943843e-04 2.44322529561276452e-08 -1.36557013749831249e-07 -7.62961654523313699e-08 1.08976492358664936e-06 -2.96208681365751854e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 4.79519063854449076e-02 -5.76477145115504089e-02 -5.60153026269178608e-02 2.12836707723255497e-01 -5.02329376751375067e-02 4.56431265394115215e-03 2.84178458687084953e-04 1.42067769343092305e-04 2.21955269112227157e-04 2.42312577480806746e-03 8.33555878999734171e-03 4.24628491937504378e-04 2.59085809862142236e-04 2.67478084275615271e-04 4.96368902328498361e-03 1.26606929488786747e-02 5.46404045396507417e-04 3.92980436091569995e-04 2.62797701870305417e-04 8.09148974723642236e-03 1.74147970924642542e-02 7.37485324742832632e-04 5.39647353275560042e-04 3.41061243578866962e-04 1.11721172217613459e-02 2.76552501744960471e-04 -3.01957477252810115e-06 -1.48575646928377593e-06 -1.21589088955731228e-06 -1.19967347414364812e-04 5.46763201699590362e-01 8.24433779385062501e-03 -5.73637963741579441e-03 -8.78057530198777941e-02 8.86018716408488831e-03 8.84531181047286223e-03 3.41751300968812797e-03 1.08170530686639201e-02 -1.43484458696081113e-03 -1.06548410209868459e-02 3.46403500342311972e-03 6.91426578610926986e-03 1.00757569295147208e-04 3.49256786924351508e-03 3.27875294825377854e-06 1.70402796459360995e-03 1.35511834188752197e-04 4.24445066846737638e-03 5.44703948514299187e-05 3.33879495657004406e-03 1.01585160144412946e-04 -7.46888761087380858e-04 -7.60592381403303971e-05 3.92331425784244554e-04 -1.15427975134875169e-04 4.31637858633478663e-05 -2.99892886284825323e-04 4.69893644901162442e-05 5.33749223032661010e-06 -1.83426293838630364e-04 2.87341090855059138e-05 3.26317088668087812e-06 -1.03192900020458206e-05 1.61619423524343624e-06 1.83503673535022410e-07 -6.94146659551127819e-08 -4.80327608701377035e-08 1.93395591536017947e-06 9.37387794628371706e-07 4.27137447873046496e-08 2.95490276565454423e-08 -1.18944180015140164e-06 -5.76379612123979311e-07 2.45013443983045469e-02 -1.59811406233284249e-02 3.39912850894292626e-09 2.64335143831501839e-09 -3.79028888230545761e-07 -5.83704307338827498e-08 -2.08665347277588535e-09 -1.62234295502301406e-09 1.19761806749703827e-07 2.26749190643845826e-08 -1.07088143106184471e-27 0.00000000000000000e+00 -1.55396506855348393e-01 -6.65593682471745662e-02 6.89216622691256608e-02 9.34604366069386322e-02 8.22585687784110203e-02 2.53226637091085729e-05 7.73394953571378274e-04 5.00071879169492243e-04 4.75593984041219994e-05 1.53887525790616801e-05 6.94139070856514859e-05 1.20550983279762904e-03 6.42025178967086762e-04 7.92780818893201495e-05 1.19600949790416611e-04 2.14773354232470042e-04 3.35100522557259207e-03 1.83226830702566267e-03 2.38628335310274832e-04 1.07144668350352468e-04 2.83893126830596766e-04 5.04670305640859528e-03 2.56945768728946778e-03 1.29915471187265453e-04 3.00071593488749093e-04 4.80193784615965829e-08 1.36980447565459188e-05 3.59661013232446859e-06 1.19410126751703110e-07 -1.91659119607233226e-07 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.91876716087522969e-02 2.39032025338826760e-02 6.06853058452816035e-02 -4.18215171396897206e-02 5.13285272312208954e-02 1.18921361679660737e-05 4.69595394336680652e-05 2.10704216447355245e-05 1.14357194076122174e-04 1.88713985585057490e-04 2.08325585305602076e-05 7.64638450675900319e-05 2.20944002052686293e-05 2.20185960889060370e-04 3.97953235783157257e-04 3.09790175800071888e-05 1.10091672828704521e-04 2.37598500323323445e-05 3.39045932483903357e-04 6.31619991930627953e-04 4.29939399107434945e-05 1.57102164118470280e-04 4.43791126638193645e-05 4.53400199033849693e-04 8.20293513302459607e-04 3.45293806824607915e-08 -2.37495855798468950e-07 -1.92855676367490630e-08 1.14595254809222743e-06 -2.68642004698085176e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 2.43036928119996012e-02 -6.77704616679622174e-02 -9.48999521147003977e-02 1.93140879172906732e-01 -1.73197728380275057e-02 4.62021533845817858e-03 1.03326875209110614e-03 2.90110053769974041e-04 5.03963540825565605e-04 3.47310533133475497e-03 8.22762219276598587e-03 1.73921915728597284e-03 3.10808799383487284e-04 7.23314163278775558e-04 7.64814376944224911e-03 1.26061091826009299e-02 2.93606025473100657e-03 1.04280100745949233e-03 1.57912144019658422e-03 7.54704505901312474e-03 1.73941709440577560e-02 4.12959293489787577e-03 1.60590544462519487e-03 2.31484015334088543e-03 9.14828250028106374e-03 2.71075017877838169e-04 -2.53962039901826715e-05 1.50575832674105946e-06 -4.74104868108782958e-06 -1.55243110114080374e-04 9.30158382235677372e-01 -2.34630367911174975e-02 1.63647976240922470e-02 -6.22753726311548392e-02 2.75973129325560798e-02 2.27080755933986578e-02 -5.78614384698344572e-03 -9.14265484466185267e-03 -8.95209367844264879e-03 -1.43842726965526854e-02 1.32410340625238807e-02 1.17403914489142632e-03 9.38924842214201427e-04 1.92146832725548672e-04 2.69624819791946538e-05 4.37950232496937906e-03 7.87324500729147327e-04 1.05284378098013227e-03 4.83233841292854784e-04 2.73422740755199919e-03 5.85118842413415424e-04 1.65899222973049914e-04 7.23883636522332599e-04 4.82853431611221583e-04 -4.10397016386240029e-04 4.09645844388818888e-04 3.38847764213372302e-04 -1.59395546804123466e-04 -1.64698788756516726e-05 -4.18847438757514705e-05 1.96983641282545974e-05 2.03492674437753086e-06 -1.70599636736394524e-04 8.02158130867017580e-05 8.28490888054499042e-06 -1.40885785249176654e-07 -9.37655192081190883e-08 2.55582694317241627e-05 1.69061418742464009e-05 -1.75202137317502700e-08 -1.16574784081300771e-08 3.17675617852904098e-06 2.10082384300733155e-06 -7.58875347261399047e-02 5.70882497882378229e-02 -1.45475377900588314e-08 -7.80423483122303932e-09 -3.26328449976779412e-07 -1.96628429424161972e-08 -1.80479573095145480e-09 -9.67996755185313776e-10 1.23413168482465965e-07 2.36148065092123531e-08 0.00000000000000000e+00 -3.87496723506280800e-29 -1.92308136926794236e-02 -1.31456948482829936e-02 -2.10557765017861005e-02 2.89788376747549883e-02 -3.14708674536539404e-02 5.85552889017074116e-07 1.47872466228329282e-04 6.62408913707872145e-07 7.71482395509776741e-05 2.45874628531442026e-05 1.05368414956070549e-06 2.65783844528519613e-04 1.18926696862734396e-06 1.38358376381233600e-04 4.40487006171380789e-05 1.58402554439680456e-06 3.99159010147087277e-04 1.78432671347979867e-06 2.07390894915173059e-04 6.59656150706502102e-05 2.17657707352537663e-06 5.47997963084033467e-04 2.44758814830820974e-06 2.84245795152796824e-04 9.03382062136808169e-05 -3.93138294160327154e-10 -1.55935233836109243e-06 4.62187344124478223e-10 -5.74418307587342364e-07 1.02214357530592412e-07 2.36715495879417703e-01 -6.61296008431984557e-03 2.46846367134006183e-03 -1.27831712767197056e-02 4.77048780867332222e-03 -1.90875326044924638e-03 7.12150679854609719e-04 4.19478021891379373e-04 -1.56470877655932980e-04 -2.24283584676943223e-03 8.36426963070230041e-04 3.49805748161048050e-04 4.81428978613841329e-05 2.87375217658394542e-04 3.95428677893663820e-05 7.08951582999053204e-05 9.75331695577134130e-06 2.35327326747629515e-04 3.23689187256313032e-05 2.52096294462547980e-04 3.46693216014187571e-05 1.19850011067249872e-04 1.64794543668780854e-05 6.45636557429717344e-05 -2.40467646709313109e-05 8.95551189774040454e-06 0.00000000000000000e+00 0.00000000000000000e+00 1.86750597421674896e-21 -1.50691194806119690e-20 7.59909558374497315e-21 -1.91590785696539668e-21 -4.63690036278034492e-20 1.16890546721093438e-20 -3.92861947908927559e-21 4.22114751317370107e-26 1.33069629384500467e-26 5.67844165540870216e-23 -5.00779054185592172e-23 8.17099387540823216e-25 -3.20095357155115849e-26 2.42147776577517645e-22 7.40137383507692448e-24 -8.48952287916815602e-03 3.15759883139587333e-03 1.42024259565577012e-26 4.47452053796630424e-27 -1.57122186344434253e-09 -9.40634741470243961e-10 2.74266792419229341e-25 -1.07381396843886350e-26 5.39287652576008223e-10 3.22783806312614335e-10 7.81058729738212197e-32 1.32004696291564014e-33 -4.63920033044187136e-02 5.78861317504657073e-03 3.99812648673872340e-02 -3.19614956498119399e-02 4.95078663382726158e-02 5.18226490461428532e-06 9.58210584503361404e-05 5.86968864388365337e-05 4.05260673556339873e-05 3.76789184495582630e-05 1.12747477663737902e-05 8.26154263663691796e-05 6.67367783747639280e-05 4.20260524527173477e-05 1.05954444686226897e-04 1.49726828992332455e-05 2.14856706211747424e-04 1.39241864418202210e-04 9.39894889734903846e-05 1.19828763993967894e-04 1.72669380274639858e-05 4.46693103493481594e-04 2.56311313423936930e-04 1.80533138932443323e-04 9.93452536027660573e-05 1.24644608912192789e-08 2.28204479070444991e-07 -7.30882789829024203e-08 6.33016344940391075e-09 1.17190407714150749e-07 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -6.07519773076615963e-02 -4.48763498126867541e-02 -6.73534736112026411e-02 3.62780520365339615e-02 -3.79450056455554047e-02 7.23654991923344314e-07 9.22782044675384298e-04 1.87911641051182864e-04 3.74795351456223965e-04 3.38360792374442379e-04 9.49024278043105418e-07 1.92485579252900862e-03 3.08214568362735037e-04 8.13675761298039940e-04 6.83995405527871875e-04 9.83570635812497389e-07 3.46123786672951263e-03 3.61781253505272531e-04 1.58876881067079932e-03 1.25762029106812477e-03 1.00095430627400275e-06 3.76719696233450852e-03 6.07827694561470316e-04 1.58527112625850308e-03 1.38514167838505223e-03 -2.96911731890821882e-10 -2.91404527975477124e-05 -1.83415989160625243e-06 -7.47794467197943093e-06 5.95418412923645604e-06 7.13023451576112188e-02 2.93590698208726856e-03 -1.32137016466630803e-03 -7.12328802053650845e-02 4.23634543207417058e-02 4.39087457973543101e-03 -2.82966017872816975e-03 -4.75460711230320980e-04 1.62837473896032319e-04 -8.94438224743980049e-04 3.77093450712259564e-04 7.42201227756463487e-04 5.17083299373567490e-04 1.73272752768299711e-04 1.78429726583102273e-04 1.20896488461186432e-03 5.53336641134479575e-04 1.13314428304610673e-03 5.12327663684459416e-04 9.45017163426265937e-04 4.78414680755208149e-04 3.04815686542821828e-05 2.10217906984662704e-05 1.15361108452250455e-05 -4.87713448572296455e-06 2.07475327331752833e-06 1.22178911108080492e-06 -8.60149993328199867e-07 5.04495178568892609e-07 -1.87388884249561755e-06 1.03536329798487001e-06 -5.38389587073119619e-07 -1.79532198999803438e-07 7.96767192264073995e-08 -3.42678354040369094e-08 8.57072894793234409e-10 7.15144638420967698e-10 3.63276312137521370e-06 2.02091934793834181e-06 4.39051574836645048e-10 3.62927944773235211e-10 6.39921540650614269e-07 4.06943956531843908e-07 1.28594519432571990e-02 -5.53826719796288169e-03 1.16412094735399349e-10 8.26970311578653855e-11 -3.33791036510362058e-10 9.27297591530017171e-10 4.01497407502561406e-11 2.83662739368542655e-11 -9.10840511764760914e-10 1.11827010017185436e-09 -1.48824765363573666e-16 -5.43309682262198255e-17 +end +case pbc_wrap 4 +types Fe Ge Fe Ge +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 12 2.50000000000000000e-01 1.10000000000000009e+00 1.19999999999999996e+00 1.34499999999999993e+01 1.39999999999999991e+00 1.00000000000000000e+00 6.79999999999999982e+00 2.00000000000000011e-01 1.44000000000000004e+01 6.50000000000000000e+00 1.25000000000000000e+01 4.50000000000000011e-01 +spins 12 6.99999999999999956e-01 -1.00000000000000006e-01 2.99999999999999989e-01 -2.00000000000000011e-01 8.00000000000000044e-01 4.00000000000000022e-01 5.00000000000000000e-01 2.00000000000000011e-01 -5.99999999999999978e-01 -4.00000000000000022e-01 2.99999999999999989e-01 9.00000000000000022e-01 +potential 4 -9.96433581016339803e-02 3.10190714093547260e-01 -8.64653399974324721e-02 3.12481088925483597e-01 +forces 12 -2.63270972110230539e-02 5.86702621651039383e-03 -9.03861583574057034e-03 2.63270972110230539e-02 -5.86702621651039383e-03 9.03861583574057034e-03 2.31619934326455666e-03 -2.21518519455950582e-03 -2.22026500090653257e-03 -2.31619934326455666e-03 2.21518519455950582e-03 2.22026500090653257e-03 +virial 36 -1.30918246472596731e-02 4.90943424272237330e-03 -3.27295616181491611e-03 4.90943424272237330e-03 -1.84103784102088879e-03 1.22735856068059267e-03 -3.27295616181491437e-03 1.22735856068059202e-03 -8.18239040453728160e-04 -7.96985312155879151e-03 -2.15813269514053465e-04 -3.95793650677754745e-03 2.98869492058454530e-03 8.09299760677699952e-05 1.48422619004157921e-03 -1.99246328038969571e-03 -5.39533173785132578e-05 -9.89484126694385778e-04 3.36375396595747973e-04 7.84875925390078350e-04 -1.17731388808511839e-03 7.84875925390078242e-04 1.83137715924351543e-03 -2.74706573886527488e-03 -1.17731388808512013e-03 -2.74706573886527921e-03 4.12059860829792207e-03 3.58484406383618548e-04 -1.44943148375792970e-03 5.11234387813158924e-04 8.36463614895110704e-04 -3.38200679543517119e-03 1.19288023823070546e-03 -1.25469542234266660e-03 5.07301019315276047e-03 -1.78932035734605862e-03 +mforces 12 -1.22653343150911660e-02 1.84869051073272596e-02 5.24850654046770879e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.63744294076475123e-02 2.05894776030080733e-03 2.30093089850026550e-02 0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 +tau 12 -6.07092218624494858e-03 -7.35355487285474594e-03 1.17143001436199636e-02 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 5.83723045318101583e-03 -1.67999684791282048e-03 4.30435976167990644e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +descriptor 340 -5.32647174737394952e-02 -2.90005009069129321e-02 -2.33707105154369529e-02 2.90676644302350178e-02 -6.72033708908375271e-02 4.34908783140388906e-03 6.38430429410170397e-05 1.10139813576221697e-03 4.81573862599628721e-04 1.10165175703432383e-03 7.82604782411721114e-03 1.14750567377850876e-04 1.97741364142843762e-03 8.63659081849775566e-04 1.97362081316753606e-03 1.17650623009191331e-02 1.72334488462276331e-04 2.96682921251278150e-03 1.29457308311357227e-03 2.95561751045568316e-03 1.61661312618096749e-02 2.36594806194293579e-04 4.06964484908669665e-03 1.77431586639102148e-03 4.04764184889877011e-03 2.51647966058948032e-04 -4.42367945031308316e-07 -3.13361258652487514e-05 -8.95846505523654649e-06 3.06554591452280604e-05 4.93071428568899961e-01 1.95917452274566202e-02 -1.57073472355527266e-02 -1.68279294500626314e-01 1.34881922166841889e-01 4.84835071178635474e-02 -3.88521458321002613e-02 -7.36324704099602101e-02 5.89919239065076206e-02 -2.13577616986489627e-03 1.71074450392732450e-03 4.24438933975276392e-02 2.69474865728955640e-02 6.85572061717825386e-03 4.35180796922738592e-03 3.71713253854028883e-02 2.35907403461395639e-02 2.36993661075311571e-02 1.50380084123348991e-02 3.05882573523461737e-02 1.94057923358826843e-02 -4.67420091837849987e-03 -2.96489889851378344e-03 5.66686099328139953e-04 -4.53325324459831318e-04 3.62612377499346998e-04 0.00000000000000000e+00 0.00000000000000000e+00 -5.97601911749359668e-20 1.20552955844895752e-19 0.00000000000000000e+00 6.13090514228926937e-20 2.47301352681618412e-19 -2.49366499671666001e-19 1.25715823330856819e-19 -1.76630687999675933e-22 1.57382758928889509e-22 -1.10750893474310196e-20 2.00354543020968422e-20 7.91603026994395697e-22 8.07940349842652545e-23 3.59149444705698890e-20 9.05653431716442630e-21 4.12745643314964897e-02 -3.29727408093890076e-02 1.91020153427104134e-23 -1.70100557624818483e-23 1.57299311633090235e-06 4.45925090018310536e-08 -8.54056914768521438e-23 -8.71184212817004304e-24 -5.39895596516666721e-07 -1.53021562505150999e-08 -1.76281107407633171e-28 4.61385561663178268e-29 -8.24615094866147230e-02 -3.50160846113524923e-02 3.00012193109828393e-02 7.35847907364700349e-02 9.36480450569126405e-02 1.41087007633410293e-03 4.68599379569618023e-04 6.80681328025675367e-03 7.32319317327973949e-04 1.71604146866133112e-04 2.53881667122882095e-03 8.42253786809647764e-04 1.22207265456474659e-02 1.31334833209201620e-03 3.07430650129037820e-04 3.81665650132779555e-03 1.26491205073790756e-03 1.83354700069562754e-02 1.96863025609237546e-03 4.60396144340329255e-04 5.24438956663103324e-03 1.73657417135439883e-03 2.51510436646247525e-02 2.69816508932905520e-03 6.30500629500008202e-04 4.64971881668313109e-05 -8.79662028360053341e-06 -4.81442641939822699e-04 -1.67992532798913733e-05 1.88465992440847680e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -7.23402185964119315e-02 2.30267774086733608e-02 -4.05081924114139291e-02 1.55675344005795618e-02 -1.63640688547461638e-01 1.39414216753964499e-04 3.43708462139657436e-03 5.27409151628835577e-05 1.78087106319724764e-05 2.01147153190228602e-03 2.50871532140608817e-04 6.17776647637749074e-03 9.46892878407973001e-05 3.19383086746235928e-05 3.60357259461318224e-03 3.77140450901119594e-04 9.27788201726493199e-03 1.42067870572174740e-04 4.78736061476767977e-05 5.39656969047822357e-03 5.18220973035500381e-04 1.27374312440589922e-02 1.94876663360438244e-04 6.56146030511325213e-05 7.39046281949746163e-03 1.44429780621412884e-06 -1.74742529722090087e-04 -3.28360032129270218e-07 -6.37071179534175626e-08 7.56331456878102035e-05 5.43214285711499989e-01 9.06396225615570678e-02 -3.95547129813733772e-02 -1.44475202855552126e-01 6.30328299363286521e-02 3.35509499634935732e-02 -1.46344441994025413e-02 -4.07553224758595775e-02 1.77728858455253047e-02 -6.71907692205143126e-02 2.92947272631868851e-02 2.47921331986569390e-02 4.66356252530997217e-03 1.03679558302768194e-02 1.94989222979615731e-03 1.52226001746395764e-02 2.86235320161409585e-03 1.49458431345461541e-02 2.80979652705747648e-03 1.78670732086594515e-02 3.35838838500794211e-03 -1.85658556962832004e-02 -3.48913956141552262e-03 1.21292092175829310e-02 -5.28141552570291200e-03 2.29949998006709387e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -9.72684234719356564e-19 4.90472411383141550e-19 5.93523246435884150e-18 -2.99239799605999201e-18 1.00572658664685455e-18 3.04344395767050908e-22 -7.45939513213227337e-24 1.33591075572336335e-20 -5.95434172568621583e-21 -2.93004427535990251e-23 -2.13752450874559090e-23 -1.69781745152430839e-20 -2.75018801882144784e-20 2.28342911669900700e-01 -9.92911440072030693e-02 -2.23814000874306998e-22 5.48227868481544072e-24 -1.42429266168888916e-06 -1.08793614814826194e-06 2.14962380417653249e-23 1.56729487849696438e-23 4.88857407075308815e-07 3.73331066185682722e-07 1.15408552297537742e-26 -2.62550862098480914e-28 -1.17417291713641264e-01 -8.31344198739986974e-03 -3.90067183899393197e-02 8.77541295031859653e-02 2.67199112242264177e-03 4.21460413838679488e-06 1.36372242593615152e-03 1.19094463745237911e-02 1.27801585515762068e-03 2.31996778937379271e-04 7.58404861556688739e-06 2.45113507930140801e-03 2.13818245720438539e-02 2.29200562110353162e-03 4.15624691355505197e-04 1.14012598006847222e-05 3.68115922819291100e-03 3.20804005940498668e-02 3.43557874372209552e-03 6.22423318274860880e-04 1.56662376937404079e-05 5.05379487261069411e-03 4.40051744413146456e-02 4.70873522301334599e-03 8.52392659695452013e-04 -7.59156545200818016e-09 -4.36719169328134187e-05 -1.11420770454859121e-03 -3.87296529361918503e-05 -2.96254025844020867e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +end +case cutoff_boundary 3 +types Fe Ge Fe +cell 9 3.00000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.00000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.00000000000000000e+01 +positions 9 1.00000000000000000e+01 1.00000000000000000e+01 1.00000000000000000e+01 1.59990000000000006e+01 1.00000000000000000e+01 1.00000000000000000e+01 1.60010000000000012e+01 1.00000000000000000e+01 1.00000000000000000e+01 +spins 9 8.00000000000000044e-01 2.00000000000000011e-01 -1.00000000000000006e-01 1.00000000000000006e-01 -6.99999999999999956e-01 4.00000000000000022e-01 -2.00000000000000011e-01 2.99999999999999989e-01 9.00000000000000022e-01 +potential 3 -9.99714607721798876e-02 3.18197839767975998e-01 -1.02063024333441860e-01 +forces 9 -9.77799931309055266e-07 0.00000000000000000e+00 0.00000000000000000e+00 6.09127638932633469e-02 4.01161783311540954e-01 -3.01948050853824423e-01 -6.09117860933320460e-02 -4.01161783311540954e-01 3.01948050853824423e-01 +virial 27 3.90923019949175488e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.15187078249338859e-04 -8.02323566623349880e-04 6.03896101707850508e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.67990234893465461e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +mforces 9 -9.12112166283736772e-03 -2.28028041570934193e-03 1.14014020785467097e-03 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 4.30914675744001677e-03 -1.94356095126224336e-02 1.58173994192688933e-03 +tau 9 -9.02594434909841409e-21 -3.61037773963936563e-20 7.22075547927873127e-20 -0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 1.79665705439382567e-02 4.19458007008139278e-03 2.59437787529248187e-03 +descriptor 255 -9.45621605356385041e-09 5.18272841461248658e-09 -9.95684890003848630e-09 7.72126562865520608e-10 -2.68815677166646850e-09 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 5.76642857139900156e-01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.72226844063625462e-01 -6.55645332435197403e-02 1.43694548132365513e-02 2.15369059060903895e-01 1.72352903361884996e-01 4.62370242821188971e-04 1.27605340811850348e-02 1.85699188870036454e-02 8.06689859238085213e-03 5.72207721524236224e-04 8.32020822076441689e-04 2.29356004727593495e-02 3.33398157624158614e-02 1.44672515947219579e-02 1.02511620522947205e-03 1.25079440189793047e-03 3.44451018009611365e-02 5.00216733977199776e-02 2.16855410829995196e-02 1.53517402441930603e-03 1.71869098228565986e-03 4.72890380657905382e-02 6.86154917941207282e-02 2.97217670572136120e-02 2.10238117909374240e-03 -8.72330326353498565e-06 -1.25001884203299399e-03 -2.16942083853579725e-03 -6.14184905616135617e-04 1.14755074438959742e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.68214732286710716e-01 -2.08682051201021304e-02 -1.33995155927235793e-01 1.85248626253599114e-01 -5.34317316903695702e-02 2.52667168161865505e-03 2.18444869829251091e-03 4.59550540688331410e-03 8.31437615971793338e-03 2.71212721140220081e-03 4.54666683744743734e-03 3.92629667994456345e-03 8.25061781545548788e-03 1.49110801850673071e-02 4.85880467961223670e-03 6.83509988774263621e-03 5.89658374116226042e-03 1.23788839337070945e-02 2.23508134788466470e-02 7.27635627630913561e-03 9.39197083250427681e-03 8.09530988194562262e-03 1.69803037619362732e-02 3.06335760410560293e-02 9.96478200149292226e-03 1.11434424931775358e-04 -8.85372556727694103e-05 2.67072221864289561e-04 -6.42663664536941340e-04 1.18414916258275125e-04 7.85571428567400032e-01 -2.54335458833941826e-02 2.47356834599829385e-02 -1.32033996159481248e-01 1.28379628191422374e-01 1.29491560080148178e-02 -1.25877969183154949e-02 5.70909165013729764e-02 -5.54852421071279633e-02 -3.60439913631735746e-03 3.50226961078139087e-03 3.32552897542532019e-02 3.10697922380094686e-02 5.14072948632779067e-04 4.80193113119956234e-04 3.40780615949358920e-02 3.18260668954334497e-02 1.77270126262038252e-02 1.65525043739881972e-02 2.39662594522770805e-02 2.23744034330933296e-02 4.76097882422648645e-03 4.44399258886861003e-03 9.55014874611244120e-04 -9.26754789670837737e-04 8.99258940748781828e-04 0.00000000000000000e+00 0.00000000000000000e+00 -1.19520382349871934e-19 0.00000000000000000e+00 0.00000000000000000e+00 -1.22618102845785387e-19 -1.23650676340809206e-19 0.00000000000000000e+00 -2.51431646661713637e-19 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -5.99515244916202644e-02 5.80978504014967381e-02 0.00000000000000000e+00 0.00000000000000000e+00 1.40370458961435493e-06 1.12260433238778492e-06 0.00000000000000000e+00 0.00000000000000000e+00 -4.81791000148025522e-07 -3.85227637695777447e-07 0.00000000000000000e+00 0.00000000000000000e+00 +end diff --git a/tests_pytest/fixtures/nep_spin3/spin3_o3c2_uniform_oracle.txt b/tests_pytest/fixtures/nep_spin3/spin3_o3c2_uniform_oracle.txt new file mode 100644 index 000000000..82e82f7b3 --- /dev/null +++ b/tests_pytest/fixtures/nep_spin3/spin3_o3c2_uniform_oracle.txt @@ -0,0 +1,100 @@ +spin3_oc_oracle_v1 +model_sha256 4fe437867031a28e0cfba62d701a7b60c85fe7d6f728653be6552ab3ee57430d +descriptor_dim 85 +spin_descriptor_dim 55 +case zero 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.39999999999999991e+00 1.30000000000000004e+00 8.00000000000000044e-01 6.99999999999999956e-01 2.60000000000000009e+00 1.39999999999999991e+00 1.30000000000000004e+00 5.00000000000000000e-01 2.70000000000000018e+00 3.10000000000000009e+00 2.79999999999999982e+00 2.20000000000000018e+00 +spins 15 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +potential 5 -9.51438283922142469e-02 3.15495448828676750e-01 -1.08666900340435135e-01 3.15251539019029303e-01 -1.03220535337539665e-01 +forces 15 -7.52203292929924140e-03 2.31254972312548226e-02 -4.21829351544954212e-03 9.05965312500611047e-03 -9.40866354915917066e-03 -1.06235972234496774e-02 -3.31555510242221869e-03 -8.85167160118362564e-03 -5.18027083270773160e-03 1.64491855772064678e-03 -9.75746987852190752e-03 1.60609755202270679e-02 1.33016348994703757e-04 4.89230779760988204e-03 3.96118605137988408e-03 +virial 45 1.02702889632011584e-02 -5.21060976712049186e-04 -1.60139496629025822e-03 3.55760238574007312e-03 -1.61083059951225779e-02 -6.13325693339412340e-03 1.83356420904859482e-03 -8.10798543137474827e-03 4.19823123613867911e-03 9.69384576071296265e-03 -7.00661316015066798e-03 -2.54926958819493466e-04 -5.92075271200100898e-03 1.73785961448429740e-02 1.35557769303652608e-02 -1.00259037219269142e-03 1.29741917532387886e-02 1.21147231061117956e-02 -5.01599256165076272e-03 8.92465357902397401e-03 1.54760166948164114e-03 8.20572838177515123e-04 -1.66091622133462645e-02 -4.64515135555315650e-03 -1.75758730647565336e-03 -1.10741371790085900e-03 -1.86503928197508757e-03 2.54197741665149798e-03 -3.34732896603774904e-03 2.29153516243151868e-03 -3.18040065181259381e-03 1.31041319777210046e-02 -1.32136445437912500e-02 4.31151539677081513e-03 -1.02903415625917247e-02 1.94838974880061529e-02 -3.03912877297456792e-03 -1.21967255316707789e-03 -2.16498640585475240e-03 1.55295606285244122e-03 -1.06564456577793809e-03 -1.93958946462374098e-03 -3.56707342620243058e-03 -5.84431640836846362e-03 -1.82211979063282535e-03 +mforces 15 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 +tau 15 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +descriptor 425 -9.66569040574016963e-02 -7.16298740671639372e-02 -1.73189969174782743e-01 4.76366185180938373e-01 -4.12470498393120277e-01 1.34087460383100817e-02 5.27635559719638950e-03 3.72521551461243820e-03 2.13110135221889017e-03 8.45895156176228701e-03 9.98854029181208032e-03 2.15408622475869163e-03 7.81295306505700587e-03 1.38590220109797361e-03 2.14753729129900650e-02 1.46478311468172633e-02 1.38738479170062261e-02 1.58711478660126769e-02 2.27768076142121191e-03 2.28236061717610392e-02 2.93962418547943326e-02 2.84879023537342631e-02 2.20832169080680575e-02 5.40172328181464691e-03 2.50571573319468520e-02 2.81989804142082959e-04 -3.54327218197930668e-05 8.37295302271673185e-05 5.66292471513821164e-06 -8.94117546733149142e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.23481863430668981e-01 -6.25519456753765857e-02 8.51240205412637368e-02 8.15468747031985464e-02 7.85428557155453400e-02 1.08520385650594199e-03 2.25565187138667246e-03 2.62300375686576673e-02 3.56218400246549214e-03 6.47919736489158040e-03 3.24120177481641326e-03 3.45992524584570445e-03 3.62884357741285468e-02 6.41520627434063757e-03 8.25179710454860063e-03 4.12119190671987427e-03 6.87815153668054364e-03 7.22165772550041746e-02 1.27083706069929855e-02 9.70001775216213294e-03 3.79518895268903715e-03 6.76040800978797152e-03 6.71064246207816739e-02 1.14815840210739043e-02 2.14924117281718521e-02 -4.98190639011998005e-05 -1.63240068267961694e-05 1.48189714530914669e-03 1.40789375474160956e-04 3.69467762617313488e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.28256597580786436e-02 -1.21321684924280374e-01 -2.51736097903013267e-01 4.41139871257841987e-01 -1.69534984766372604e-01 2.36483278288444135e-02 5.09077895784372167e-04 4.47456662717190309e-04 5.11256949154828728e-03 3.47069194175847646e-03 1.67476308446369779e-02 1.48822244535158394e-03 2.42360616812703749e-03 3.45420367220892295e-03 6.73791229793482480e-03 1.78383886569127431e-02 2.19744813218269433e-03 6.16423135505987652e-03 1.40912391900268642e-03 2.60579251694636749e-02 3.22463311903943908e-02 3.05329839939879081e-03 9.52283627664764730e-03 4.78958203400679187e-03 4.72957179029264291e-02 2.43362812275990588e-04 -1.25392048867713212e-05 6.68830164469984193e-06 -6.24196140510288014e-05 9.69016350838528565e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.67654325892752121e-01 -8.46864462824955394e-02 1.21450831052852232e-01 1.08055032490834133e-01 9.45616739415407609e-02 7.11320941908297330e-04 2.12511078507391553e-03 1.70582515936875470e-02 2.64931635386344861e-03 2.18064025574333555e-03 1.59932561322437446e-03 2.15845658955046184e-03 2.27419978233290333e-02 3.96413468664661567e-03 3.56106926010374240e-03 2.59990545962430694e-03 3.03905059423623201e-03 3.11069912527315307e-02 6.37131775233702822e-03 4.62383635655244651e-03 3.59636236081232411e-03 6.17591186421551520e-03 4.80324100201376808e-02 1.04848029426210711e-02 5.32240150754023644e-03 -1.76911719385717589e-05 -1.69381395814897815e-05 -9.11741056817430518e-04 -4.71091215613341857e-05 6.17099033772849394e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.27565858027677528e-02 -1.03934894915859624e-01 -1.96371946717433327e-01 3.03967099943896424e-01 -1.81996956816426053e-01 1.69024140400730119e-02 4.31019629144469203e-04 1.26413915592121242e-03 8.71073052748900199e-03 6.93545460899188879e-03 2.08052242569049944e-02 1.34971077451756971e-03 4.31588123035818883e-03 9.21180036173221452e-03 1.54199541076760083e-02 1.84259680460171389e-02 2.63204783691434749e-03 8.43915394317120739e-03 5.84012532135764866e-03 2.48697525804578053e-02 1.57093735726174591e-02 3.67507757349219873e-03 1.14238939699460324e-02 3.46662310439108372e-03 3.08011777513127784e-02 1.00797298090413438e-03 -1.73690169716654561e-05 8.47057556590328105e-06 -3.10423609983225002e-04 -6.49692747069250645e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +end +case collinear 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.39999999999999991e+00 1.30000000000000004e+00 8.00000000000000044e-01 6.99999999999999956e-01 2.60000000000000009e+00 1.39999999999999991e+00 1.30000000000000004e+00 5.00000000000000000e-01 2.70000000000000018e+00 3.10000000000000009e+00 2.79999999999999982e+00 2.20000000000000018e+00 +spins 15 0.00000000000000000e+00 0.00000000000000000e+00 8.00000000000000044e-01 0.00000000000000000e+00 0.00000000000000000e+00 -5.99999999999999978e-01 0.00000000000000000e+00 0.00000000000000000e+00 1.10000000000000009e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.99999999999999989e-01 0.00000000000000000e+00 0.00000000000000000e+00 5.00000000000000000e-01 +potential 5 -9.48096627449567797e-02 3.15495448828676750e-01 -1.00754545455655722e-01 3.15251539019029303e-01 -1.05953423094407723e-01 +forces 15 -2.57260916358869572e-02 7.95780170668485831e-02 8.63688865137079639e-03 1.69088822536933789e-02 -1.33786225089030618e-02 -1.40359763145745404e-02 -2.13260984407410981e-02 -6.37733947608690593e-02 -2.68020027986980540e-02 1.96244763067700626e-03 -1.41043801998398319e-02 1.86251678762150014e-02 2.81808601922576701e-02 1.16783804027633699e-02 1.35759225856867949e-02 +virial 45 1.64497200075989988e-02 1.51792758975617566e-02 4.44143913071831133e-03 1.79560474270719084e-02 -5.91903377798079222e-02 -1.56709817348877276e-02 8.16521838927311040e-03 -1.65331223268859878e-02 3.12288025014328561e-03 2.13151094863787728e-02 -1.60737207603013667e-02 -5.98800296250479123e-03 -1.33799713910928101e-02 2.20388568184657699e-02 1.69583060265763724e-02 -5.39755757398994226e-03 1.44888245621219384e-02 1.38650443235484866e-02 2.22472752457787172e-02 2.05754771117378291e-02 1.30542121426178784e-02 1.16774498466821509e-02 -6.63109382031771555e-02 -1.60185251286818001e-02 9.97168802150407742e-03 -1.28153990893214807e-02 -1.82404337428044173e-03 4.27756617040285329e-03 -3.93826726649516845e-03 3.38624774478396822e-03 -3.59760109251944064e-03 2.26652565690724575e-02 -1.77919962337679330e-02 5.27651301391532900e-03 -1.51875339621766713e-02 2.29289319896697555e-02 2.55491344701779012e-02 4.95246671914451649e-03 7.59332573639647564e-03 8.03930691150575583e-03 2.81941905027943262e-03 5.53276414600572088e-04 7.22511552512243062e-03 -2.74979244271647506e-03 1.94747344674426541e-03 +mforces 15 -1.04678662550885312e-03 -1.08516636494629696e-03 5.86208208594196298e-03 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -7.33293283623173112e-04 1.06206669392376629e-03 -1.21810006931975055e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.23977968333944307e-03 2.80800263497618793e-05 1.76476382586831029e-02 +tau 15 8.68133091957037570e-04 -8.37429300407082559e-04 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -1.16827336331614307e-03 -8.06622611985490499e-04 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -1.40400131748809396e-05 -6.19889841669721536e-04 0.00000000000000000e+00 +descriptor 425 -9.66569040574016963e-02 -7.16298740671639372e-02 -1.73189969174782743e-01 4.76366185180938373e-01 -4.12470498393120277e-01 1.34087460383100817e-02 5.27635559719638950e-03 3.72521551461243820e-03 2.13110135221889017e-03 8.45895156176228701e-03 9.98854029181208032e-03 2.15408622475869163e-03 7.81295306505700587e-03 1.38590220109797361e-03 2.14753729129900650e-02 1.46478311468172633e-02 1.38738479170062261e-02 1.58711478660126769e-02 2.27768076142121191e-03 2.28236061717610392e-02 2.93962418547943326e-02 2.84879023537342631e-02 2.20832169080680575e-02 5.40172328181464691e-03 2.50571573319468520e-02 2.81989804142082959e-04 -3.54327218197930668e-05 8.37295302271673185e-05 5.66292471513821164e-06 -8.94117546733149142e-04 5.34857142854400114e-01 4.85063403990600682e-03 8.49209336932024855e-02 -1.80652577463754821e-01 2.16956067239304218e-01 1.63013452893876996e-02 -2.85398944374893535e-02 1.26523924521811434e-02 -3.58014921953053109e-02 -1.23261791697163350e-01 1.47932115165654104e-01 4.83956944645044099e-05 1.46515251865179733e-02 2.67611331619457815e-04 2.01318902336487630e-03 2.26954680914354320e-02 3.76189331933283050e-02 1.17541052465416837e-02 2.05669464491204032e-02 2.34596374112921169e-02 3.51842001993805525e-02 -1.24235651460607782e-03 2.57833805198634039e-02 1.70958444273023175e-02 -1.82602311201961916e-02 2.69811644234664409e-02 -1.75232592363492971e-02 1.93735310544757115e-02 -1.68180143139450462e-02 -1.31937089998509366e-03 -1.72227595128724743e-03 6.43741236558443707e-04 6.77876382721778400e-03 -1.07855055257929950e-02 9.03059775840351839e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -8.89886835468746001e-02 2.87980836805852403e-01 0.00000000000000000e+00 0.00000000000000000e+00 2.58179008208667711e-06 -4.00841900877747942e-07 0.00000000000000000e+00 0.00000000000000000e+00 -9.13634151329400981e-07 -1.15899003294015838e-06 0.00000000000000000e+00 0.00000000000000000e+00 -3.23481863430668981e-01 -6.25519456753765857e-02 8.51240205412637368e-02 8.15468747031985464e-02 7.85428557155453400e-02 1.08520385650594199e-03 2.25565187138667246e-03 2.62300375686576673e-02 3.56218400246549214e-03 6.47919736489158040e-03 3.24120177481641326e-03 3.45992524584570445e-03 3.62884357741285468e-02 6.41520627434063757e-03 8.25179710454860063e-03 4.12119190671987427e-03 6.87815153668054364e-03 7.22165772550041746e-02 1.27083706069929855e-02 9.70001775216213294e-03 3.79518895268903715e-03 6.76040800978797152e-03 6.71064246207816739e-02 1.14815840210739043e-02 2.14924117281718521e-02 -4.98190639011998005e-05 -1.63240068267961694e-05 1.48189714530914669e-03 1.40789375474160956e-04 3.69467762617313488e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.28256597580786436e-02 -1.21321684924280374e-01 -2.51736097903013267e-01 4.41139871257841987e-01 -1.69534984766372604e-01 2.36483278288444135e-02 5.09077895784372167e-04 4.47456662717190309e-04 5.11256949154828728e-03 3.47069194175847646e-03 1.67476308446369779e-02 1.48822244535158394e-03 2.42360616812703749e-03 3.45420367220892295e-03 6.73791229793482480e-03 1.78383886569127431e-02 2.19744813218269433e-03 6.16423135505987652e-03 1.40912391900268642e-03 2.60579251694636749e-02 3.22463311903943908e-02 3.05329839939879081e-03 9.52283627664764730e-03 4.78958203400679187e-03 4.72957179029264291e-02 2.43362812275990588e-04 -1.25392048867713212e-05 6.68830164469984193e-06 -6.24196140510288014e-05 9.69016350838528565e-05 1.01121428570909999e+00 2.54629512867102920e-02 4.14018628775726996e-02 -1.02706909086306322e-01 1.23098174860970924e-01 2.87215166489314529e-04 -2.03634916812371093e-02 7.56537089216651748e-02 -7.64585787610180673e-02 -1.32491912720883620e-01 1.58689312011698308e-01 7.05377801250934287e-04 1.84199176350579360e-03 1.81071355455387253e-04 1.79571538688861124e-03 2.19807007954861584e-03 6.68792928040312998e-03 1.24593431107407381e-03 4.65263235613264624e-03 4.38798555415415709e-03 1.13167698686691773e-02 -3.70776301454155523e-03 7.13222104022029433e-03 1.61915323814773200e-02 -1.93618745759498237e-02 2.89662236508179821e-02 -1.56469754007274621e-02 2.14763153262601814e-02 -2.71506301736402465e-02 -1.37927829988412944e-02 1.75237371028716740e-02 -1.87094430020097943e-02 -8.57325064282861427e-03 9.92471263910474182e-03 -8.06968394227750713e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.77429710180779694e-02 1.63754206008890041e-01 0.00000000000000000e+00 0.00000000000000000e+00 6.07034626906017174e-08 1.57110167310782747e-07 0.00000000000000000e+00 0.00000000000000000e+00 -2.31611644265203212e-08 -2.18453359221660161e-08 0.00000000000000000e+00 0.00000000000000000e+00 -2.67654325892752121e-01 -8.46864462824955394e-02 1.21450831052852232e-01 1.08055032490834133e-01 9.45616739415407609e-02 7.11320941908297330e-04 2.12511078507391553e-03 1.70582515936875470e-02 2.64931635386344861e-03 2.18064025574333555e-03 1.59932561322437446e-03 2.15845658955046184e-03 2.27419978233290333e-02 3.96413468664661567e-03 3.56106926010374240e-03 2.59990545962430694e-03 3.03905059423623201e-03 3.11069912527315307e-02 6.37131775233702822e-03 4.62383635655244651e-03 3.59636236081232411e-03 6.17591186421551520e-03 4.80324100201376808e-02 1.04848029426210711e-02 5.32240150754023644e-03 -1.76911719385717589e-05 -1.69381395814897815e-05 -9.11741056817430518e-04 -4.71091215613341857e-05 6.17099033772849394e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.27565858027677528e-02 -1.03934894915859624e-01 -1.96371946717433327e-01 3.03967099943896424e-01 -1.81996956816426053e-01 1.69024140400730119e-02 4.31019629144469203e-04 1.26413915592121242e-03 8.71073052748900199e-03 6.93545460899188879e-03 2.08052242569049944e-02 1.34971077451756971e-03 4.31588123035818883e-03 9.21180036173221452e-03 1.54199541076760083e-02 1.84259680460171389e-02 2.63204783691434749e-03 8.43915394317120739e-03 5.84012532135764866e-03 2.48697525804578053e-02 1.57093735726174591e-02 3.67507757349219873e-03 1.14238939699460324e-02 3.46662310439108372e-03 3.08011777513127784e-02 1.00797298090413438e-03 -1.73690169716654561e-05 8.47057556590328105e-06 -3.10423609983225002e-04 -6.49692747069250645e-04 2.08928571427499987e-01 1.26713914932433218e-02 -4.06664675700570341e-02 -9.04153319624631385e-02 6.98555947197079200e-03 5.46898964928734053e-03 5.66046151219082479e-03 5.00451920883058631e-03 -5.69508853041760313e-03 -2.40983012874338674e-02 1.86059519995375043e-03 8.45470169823664972e-04 8.60134127925587383e-03 4.19140458993136279e-04 6.39801127326210402e-04 1.22550766324433275e-03 5.72751380698370213e-03 9.15201761013064775e-04 3.36226386528711962e-03 2.13370846180581039e-03 2.00826745579863212e-03 -1.62431389494282650e-03 -3.97549253149652795e-04 2.36781265238271768e-03 -9.75914204693636533e-04 9.60842411444145952e-04 -2.18847804227434743e-03 2.22642295755451082e-04 1.50884319766419442e-03 -2.02654381216715081e-03 5.66968895131893355e-04 8.13597470006700981e-04 -1.66264914437044484e-03 9.74295883440305524e-04 -1.86588452274164717e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -6.37043499442862919e-03 -4.45728433881877190e-02 0.00000000000000000e+00 0.00000000000000000e+00 -9.02905406140204270e-07 1.63911295252198732e-06 0.00000000000000000e+00 0.00000000000000000e+00 9.30913986331100066e-07 -3.44008162355048284e-07 0.00000000000000000e+00 0.00000000000000000e+00 +end +case noncollinear 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.39999999999999991e+00 1.30000000000000004e+00 8.00000000000000044e-01 6.99999999999999956e-01 2.60000000000000009e+00 1.39999999999999991e+00 1.30000000000000004e+00 5.00000000000000000e-01 2.70000000000000018e+00 3.10000000000000009e+00 2.79999999999999982e+00 2.20000000000000018e+00 +spins 15 8.00000000000000044e-01 1.00000000000000006e-01 2.00000000000000011e-01 2.00000000000000011e-01 9.00000000000000022e-01 -1.00000000000000006e-01 -2.99999999999999989e-01 4.00000000000000022e-01 6.99999999999999956e-01 5.00000000000000000e-01 -2.00000000000000011e-01 5.99999999999999978e-01 -4.00000000000000022e-01 -2.99999999999999989e-01 8.00000000000000044e-01 +potential 5 -1.08564104011231413e-01 3.15495448828676750e-01 -1.12620527556477390e-01 3.15251539019029303e-01 -9.52773105801160702e-02 +forces 15 -8.05044118186701296e-04 2.76069160431682385e-02 2.37011633784811430e-03 -8.91196316352626736e-04 -1.26374290346625458e-02 -1.24983133824466564e-02 -2.19114580207356996e-02 -2.20837476338120453e-02 -1.18644623410733528e-02 1.13131688338759620e-03 3.58122864017594231e-04 7.18819644897950895e-03 2.24763815718874334e-02 6.75613776128875312e-03 1.48044629366923877e-02 +virial 45 1.04845517799065473e-02 -8.44042169620998380e-04 -3.39970502231014791e-03 4.19551422632280860e-03 -1.57336429087333272e-02 -8.86554601311973466e-03 2.09577179590647806e-03 -8.09208331030388493e-03 2.80420073283237179e-03 2.19932136777383630e-05 5.68734967907064820e-05 4.28543364808161870e-03 9.09481374016311156e-04 1.80107639965493491e-02 1.60143152809490569e-02 5.31829508201503952e-03 1.76767312608020755e-02 1.56237944695357400e-02 2.39872546305657935e-02 1.20540865852932378e-02 1.13364385077385776e-02 4.27240429737238241e-03 -1.97297314640654531e-02 -3.22338730897088867e-03 8.22859074011248089e-03 -1.10468640850083441e-03 1.58437637489851520e-03 -5.46388514263409283e-03 -8.28793887754277619e-03 1.60763357169782474e-03 -7.18260317705973414e-03 -7.81427062472555764e-03 -6.64862581707387559e-04 -2.88002963256705179e-04 -4.27955120411082843e-04 7.50488831522396448e-03 2.38356444477909220e-02 2.49070764607542535e-04 5.47773036343668102e-03 2.37133993896890445e-03 -1.87635738521209393e-03 -2.93921807604585923e-03 4.95389798822278883e-03 -5.64184548580216709e-03 2.21907334865426758e-04 +mforces 15 3.30889269910945340e-03 1.71468792982114489e-02 2.63716566976182031e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.13728538681392346e-02 1.00883905905313296e-02 9.85217462151220628e-03 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 1.90991257114164203e-02 1.72435965263126774e-02 -5.19464838581010745e-03 +tau 15 -7.92210189880469319e-04 -2.04355468182726742e-02 1.33866141686582139e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -3.12100356476704760e-03 1.09166500941511261e-02 -7.57565872441509289e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.22364827053071095e-02 1.32014412148090936e-02 -1.16770089710014507e-03 +descriptor 425 -9.66569040574016963e-02 -7.16298740671639372e-02 -1.73189969174782743e-01 4.76366185180938373e-01 -4.12470498393120277e-01 1.34087460383100817e-02 5.27635559719638950e-03 3.72521551461243820e-03 2.13110135221889017e-03 8.45895156176228701e-03 9.98854029181208032e-03 2.15408622475869163e-03 7.81295306505700587e-03 1.38590220109797361e-03 2.14753729129900650e-02 1.46478311468172633e-02 1.38738479170062261e-02 1.58711478660126769e-02 2.27768076142121191e-03 2.28236061717610392e-02 2.93962418547943326e-02 2.84879023537342631e-02 2.20832169080680575e-02 5.40172328181464691e-03 2.50571573319468520e-02 2.81989804142082959e-04 -3.54327218197930668e-05 8.37295302271673185e-05 5.66292471513821164e-06 -8.94117546733149142e-04 5.76642857139900156e-01 -7.38557641705864243e-02 2.32599555474246322e-02 -3.18849588406399098e-01 2.10484671700818610e-01 -4.02348602280177409e-02 2.39039354228826537e-02 -3.69587714371138812e-02 -6.02099305234771003e-03 -4.10885611831804387e-02 1.34040765789195885e-02 5.47512881834275461e-02 3.90083510490187718e-02 4.25234385747487176e-02 2.61835425903013917e-02 4.70710166066940425e-02 2.82090712645608373e-02 8.37827713524082543e-03 7.91939150565401824e-03 2.73846734687644006e-02 1.77944413644387511e-02 1.01133424547538448e-02 1.63044835882714362e-03 6.41148395480757062e-03 -2.21565121875396797e-03 9.60302792844974144e-04 1.68612249275232893e-03 -3.23426427131116856e-04 -1.69536514916123192e-04 -1.47778886109594006e-03 3.28486367307282312e-04 -5.37431031348763481e-05 -2.10884581131774154e-03 5.01492077658903914e-04 2.25618137346167541e-05 2.18388188538680416e-06 2.26752554461506473e-06 5.87904048578695741e-04 3.40504946527757152e-04 -9.23748547527666156e-08 -1.09722851739078609e-07 1.14866481202498659e-04 4.57332575597070730e-05 -1.52117433784159484e-01 5.00604210656990373e-02 1.10210622156733125e-06 8.18609272569806424e-07 -2.45929652824788124e-06 -3.58355843798455741e-06 -6.17487168268593039e-08 -4.72549368992598554e-08 5.51236698125671887e-07 -5.85834687806039948e-07 2.47698434496134914e-10 2.91508684554326143e-10 -3.23481863430668981e-01 -6.25519456753765857e-02 8.51240205412637368e-02 8.15468747031985464e-02 7.85428557155453400e-02 1.08520385650594199e-03 2.25565187138667246e-03 2.62300375686576673e-02 3.56218400246549214e-03 6.47919736489158040e-03 3.24120177481641326e-03 3.45992524584570445e-03 3.62884357741285468e-02 6.41520627434063757e-03 8.25179710454860063e-03 4.12119190671987427e-03 6.87815153668054364e-03 7.22165772550041746e-02 1.27083706069929855e-02 9.70001775216213294e-03 3.79518895268903715e-03 6.76040800978797152e-03 6.71064246207816739e-02 1.14815840210739043e-02 2.14924117281718521e-02 -4.98190639011998005e-05 -1.63240068267961694e-05 1.48189714530914669e-03 1.40789375474160956e-04 3.69467762617313488e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.28256597580786436e-02 -1.21321684924280374e-01 -2.51736097903013267e-01 4.41139871257841987e-01 -1.69534984766372604e-01 2.36483278288444135e-02 5.09077895784372167e-04 4.47456662717190309e-04 5.11256949154828728e-03 3.47069194175847646e-03 1.67476308446369779e-02 1.48822244535158394e-03 2.42360616812703749e-03 3.45420367220892295e-03 6.73791229793482480e-03 1.78383886569127431e-02 2.19744813218269433e-03 6.16423135505987652e-03 1.40912391900268642e-03 2.60579251694636749e-02 3.22463311903943908e-02 3.05329839939879081e-03 9.52283627664764730e-03 4.78958203400679187e-03 4.72957179029264291e-02 2.43362812275990588e-04 -1.25392048867713212e-05 6.68830164469984193e-06 -6.24196140510288014e-05 9.69016350838528565e-05 6.18428571425399976e-01 -4.17266840269568465e-02 1.27294515670632238e-02 -2.20085971089699795e-01 2.06803563471589125e-01 -7.99324036521538092e-03 7.76557268808631372e-03 -3.61379855258263253e-03 9.62274335861671749e-03 -1.27635393048805487e-02 6.67394382924126300e-04 3.73825162660365584e-02 5.69534723229486936e-02 4.30135426513831253e-04 2.25853207400433060e-03 4.56326592921829366e-02 6.21169016877645350e-02 1.39118713328748866e-02 2.07982381105424607e-02 2.23749582538593922e-02 2.89713671387456413e-02 4.59791115195533340e-03 3.71605617710679898e-03 1.41322752337048755e-03 -1.01996239291832344e-03 1.20309023685560347e-03 1.18865991787588349e-03 2.43886745584634765e-04 -9.90611692969657100e-04 5.10506705486367222e-04 3.04520475984554632e-04 -7.79605933028946151e-04 -3.71472243308123022e-04 3.18134604675621776e-04 -2.87085456888799600e-04 -4.24182114238475955e-07 1.84267855565465983e-07 -9.68133078336037508e-05 -5.83461479498038161e-05 2.49621050847188621e-07 -1.02180522865727275e-07 -7.26697331104599252e-06 1.10442972918331949e-05 -9.42151435500302031e-02 2.55952870211717254e-02 2.00748588950218879e-07 1.73277081676432279e-07 2.72213817676983875e-06 2.55592524053507837e-06 -1.15422283446363011e-07 -9.94420694996263777e-08 -1.26698954809749020e-06 -1.68388932426677145e-06 1.29428762093791979e-11 -2.04576553968383994e-12 -2.67654325892752121e-01 -8.46864462824955394e-02 1.21450831052852232e-01 1.08055032490834133e-01 9.45616739415407609e-02 7.11320941908297330e-04 2.12511078507391553e-03 1.70582515936875470e-02 2.64931635386344861e-03 2.18064025574333555e-03 1.59932561322437446e-03 2.15845658955046184e-03 2.27419978233290333e-02 3.96413468664661567e-03 3.56106926010374240e-03 2.59990545962430694e-03 3.03905059423623201e-03 3.11069912527315307e-02 6.37131775233702822e-03 4.62383635655244651e-03 3.59636236081232411e-03 6.17591186421551520e-03 4.80324100201376808e-02 1.04848029426210711e-02 5.32240150754023644e-03 -1.76911719385717589e-05 -1.69381395814897815e-05 -9.11741056817430518e-04 -4.71091215613341857e-05 6.17099033772849394e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.27565858027677528e-02 -1.03934894915859624e-01 -1.96371946717433327e-01 3.03967099943896424e-01 -1.81996956816426053e-01 1.69024140400730119e-02 4.31019629144469203e-04 1.26413915592121242e-03 8.71073052748900199e-03 6.93545460899188879e-03 2.08052242569049944e-02 1.34971077451756971e-03 4.31588123035818883e-03 9.21180036173221452e-03 1.54199541076760083e-02 1.84259680460171389e-02 2.63204783691434749e-03 8.43915394317120739e-03 5.84012532135764866e-03 2.48697525804578053e-02 1.57093735726174591e-02 3.67507757349219873e-03 1.14238939699460324e-02 3.46662310439108372e-03 3.08011777513127784e-02 1.00797298090413438e-03 -1.73690169716654561e-05 8.47057556590328105e-06 -3.10423609983225002e-04 -6.49692747069250645e-04 7.43785714281900101e-01 3.43048320498622536e-02 -4.44280957126416166e-03 -1.73628042633545782e-01 1.02676083747325883e-01 -1.70595726236305693e-02 4.25338388462082398e-03 4.46744520773760603e-02 -3.42991573267509243e-03 -3.27727587552590141e-02 1.63027292335391240e-02 2.41292889356622443e-02 9.54674954061110123e-03 1.55792389153960528e-02 2.71244576914687809e-03 3.74170949607740633e-03 4.34240442002362895e-03 1.76443082345592410e-02 8.36593155168538841e-03 1.60827267797047958e-02 9.10206039838045745e-03 -6.41925700583371919e-03 1.19144396349899970e-03 3.72462008540440327e-03 -2.42325678068929700e-03 2.70937789404159055e-03 -2.04102084980403373e-03 2.25776753178555997e-03 -2.75168557114183589e-03 -1.01261279088551547e-03 1.42466053146175472e-03 -1.75355737730598701e-03 5.10439298932873907e-04 1.21003353410606545e-04 -2.19317092319733985e-04 2.73899829254449957e-06 2.03932535230664812e-06 3.89768787156323493e-05 1.57735356200755747e-05 -1.87216776366956271e-06 -1.39563096613840213e-06 -3.25661851618453896e-05 -1.28402289513505937e-05 9.19857241862554048e-02 -1.91577370786443595e-02 -8.97932473795784984e-07 -6.30033788528895062e-07 -2.97418143691077539e-06 -1.56490989706284376e-07 6.20185206735701078e-07 4.33983720056922116e-07 -2.57997694399673079e-08 -3.47573826447467750e-07 -1.14930773501518036e-11 -8.48112163764630702e-12 +end +case chiral_soc 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.50000000000000000e+00 1.10000000000000009e+00 1.10000000000000009e+00 4.99999999999999944e-01 2.70000000000000018e+00 1.59999999999999987e+00 1.60000000000000009e+00 6.99999999999999956e-01 2.60000000000000009e+00 3.00000000000000000e+00 3.09999999999999964e+00 2.30000000000000027e+00 +spins 15 1.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.00000000000000000e+00 5.99999999999999978e-01 -2.00000000000000011e-01 6.99999999999999956e-01 -4.00000000000000022e-01 8.00000000000000044e-01 2.99999999999999989e-01 +potential 5 -1.02378756853245295e-01 3.16935531381510094e-01 -1.17509799722396807e-01 3.16237411060139140e-01 -1.12126298936847127e-01 +forces 15 -9.77915409831730739e-03 1.95979736617469605e-02 2.14169920173527513e-03 1.22583541704282713e-02 3.27974971864231427e-03 1.81235090611685332e-03 -1.02464878979822167e-02 -2.45743889221430173e-02 -4.64253766448215113e-03 -1.12265915612345321e-02 4.95278037998323969e-03 7.83453503224104675e-05 1.89938793871057832e-02 -3.25611483822950236e-03 6.10142206307611769e-04 +virial 45 1.43114507017142300e-02 1.81571739508908266e-03 4.11667784148067421e-03 6.67220170882976832e-03 -1.28252894393884945e-02 -6.23111874539763067e-03 6.91337178861508445e-03 -5.63841945336996352e-03 4.72863612110310718e-03 3.20960167603872876e-03 -1.28251755322178855e-02 -3.77111851019155519e-03 -5.98259672618148882e-03 -9.94954148527128421e-03 -6.51581847867760237e-03 -2.94801562079532184e-03 -7.92089748492585781e-03 -2.53350937113285858e-03 1.80332207088866950e-02 1.00139957129859094e-02 7.27255712155529862e-03 5.30335581285175817e-03 -1.25202406311929262e-02 -2.11184508941759507e-03 5.02956472808098465e-03 -1.28045221624747269e-03 4.32425217028859247e-04 -2.78559780313197402e-03 1.43220996050505249e-02 -7.74680660705189070e-03 1.79248029758834644e-02 -8.11489323513303260e-03 9.08159918943996641e-03 -1.23970606209494565e-02 7.46150194307984918e-03 -4.49306203775961394e-03 2.19939037585966737e-02 3.39620409658287006e-04 6.43577696843249721e-03 3.14416640038204902e-03 -6.36219667907008887e-03 -6.76100786805845528e-04 5.20957910856447749e-03 -3.34689185168329534e-03 1.79759991398649628e-04 +mforces 15 -1.99233047069084096e-03 3.49975226575223938e-02 1.54354832260345971e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 2.66018108252193304e-03 1.38836046993340012e-02 1.24648609879759557e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 1.67449143957973424e-02 1.23588157050990126e-02 9.47167381792484581e-03 +tau 15 0.00000000000000000e+00 -1.54354832260345971e-02 3.49975226575223938e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.38836046993340012e-02 2.66018108252193304e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.86969434281017339e-03 8.81214384590914106e-03 -1.83394577986774783e-02 +descriptor 425 -1.16146870932738511e-01 -5.44997247220408779e-02 -1.67922932658313179e-01 4.63890345476966448e-01 -4.42590674784521410e-01 1.12487733029452072e-02 6.48297996058465591e-03 6.07899492453601795e-03 2.34261182721013685e-03 8.62757005584224163e-03 9.06070918055255740e-03 4.96465951194150802e-03 9.20271364617481456e-03 1.53408857343331870e-03 1.97005493326668085e-02 1.08315265142348797e-02 7.54172563370391919e-03 1.09898443130773942e-02 8.82051915877943922e-04 1.64129589247990447e-02 2.02501310326845541e-02 1.60820619832233586e-02 1.85383061168941758e-02 2.58487947783608710e-03 2.19350544240077168e-02 1.97254594968305802e-04 -9.38271106184100970e-05 2.84438868965413172e-05 -1.79561953282346376e-05 -8.71260723233180812e-04 8.35714285709999949e-01 -4.09030082586571489e-02 8.21970025214806450e-03 -3.53334157553000572e-01 2.35412783238968887e-01 -4.57213025486123553e-02 9.54653636940266080e-03 -6.55908386433502882e-02 1.28026277369073706e-02 -5.62573230050394113e-02 1.72190062819437273e-02 6.83235385983560345e-02 3.45096476637756500e-02 3.05784160597982503e-02 8.17860585448832930e-03 5.46209821975294149e-02 2.39172707901486904e-02 2.48503581395999283e-02 1.38536250321314031e-02 3.74507076054192978e-02 1.56036715038694214e-02 2.42849372615141145e-03 6.79689054129482828e-04 7.90144407682704525e-03 -2.34578032690232335e-03 7.09952821786981369e-04 -5.57851364999499034e-03 1.90018468592963673e-03 -6.26900873210248471e-04 -2.75185738764967833e-03 9.37143235049507401e-04 -3.09110268692095835e-04 9.01507374403364716e-04 -3.06942429034521549e-04 1.01221673147643921e-04 1.24033663942514320e-05 9.25488267873277006e-06 1.69907316431646121e-03 8.26902603923482748e-04 -2.37191742254093037e-07 -1.34477862634662753e-07 -5.58725312908928519e-04 -2.83358438420230506e-04 -1.13891257949596619e-01 2.28052034607627956e-02 -1.78661521515812136e-06 -1.28355433216016654e-06 -1.70636502360206558e-05 -1.14454212074101843e-05 3.28727956505345100e-07 2.32123048162560534e-07 3.38647020698707695e-06 5.43358560492929534e-07 1.60705273507469656e-10 -4.93047133610184034e-11 -3.32923829386318204e-01 -3.60611363215902342e-02 8.98369845801973432e-02 1.17017830520669677e-01 1.42581913862859927e-01 2.94672959340922674e-04 1.89304741933513663e-03 2.03207905394245519e-02 4.37293532659051125e-03 3.33316492609661737e-03 6.95568410948279887e-04 4.60237073751297576e-03 3.23123290917254058e-02 4.24067973016666912e-03 5.19104368881810607e-03 7.44570850637201365e-04 8.36650883667493413e-03 6.28581995094227575e-02 7.81078617537373648e-03 4.76439050657084025e-03 6.93315995277122015e-04 7.95033268072797318e-03 5.43935700603309299e-02 7.90235673001788742e-03 7.75503922682841285e-03 -1.46756778118909190e-06 -2.09170633365566446e-05 9.58894372181939196e-04 4.04851149140820709e-05 8.70889481059250177e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.18866632033709423e-02 -1.25616904456226947e-01 -2.41526850944396632e-01 3.60985083274788621e-01 -1.11385168368811058e-01 1.91964091946690181e-02 1.04766062835099719e-04 8.92697179342440660e-04 5.38899239582176556e-03 2.74736612790413325e-03 1.47928463806994651e-02 3.07116445798808098e-04 1.07802090428069661e-03 4.67766462734487808e-03 5.99573572176860092e-03 1.74647998550215740e-02 4.21860436653466182e-04 2.00647852058887053e-03 2.67208452180241023e-03 2.44607362094166857e-02 2.98471501693943451e-02 5.22102758267767786e-04 3.24930667892137093e-03 3.62337223857072625e-03 4.48871182744859862e-02 1.22580778029987450e-04 -1.44090952284939391e-06 -2.26742764821762819e-06 -9.29342291003885235e-05 8.60763023606210484e-06 8.35714285709999949e-01 -7.31697982940377745e-02 6.11620185782532633e-02 -2.38871126279140311e-01 2.86094362882660269e-01 -9.70810790441991103e-03 1.20255107799965549e-02 6.13125617922922056e-02 -7.13990260790255821e-02 -5.37622600769256109e-02 4.97421141546892515e-02 2.80119351545592178e-02 5.12782788934361897e-02 7.23412572733872256e-04 1.85577100313279544e-03 3.71674517460518911e-02 5.53332303000762527e-02 9.63936847173934089e-03 2.08053882136485721e-02 1.81903316199201019e-02 3.05773496268319789e-02 9.48914314533722512e-03 1.32140091887153928e-02 6.94364630343396409e-03 -6.83400934388489131e-03 6.93241242626246347e-03 9.86612568073028714e-04 2.48031135944351815e-04 -1.47263293175310043e-03 4.09946946464836688e-04 1.03036228208038181e-04 -6.11621375687272976e-04 -2.63990232287514498e-04 -6.63372929871352299e-05 3.93694707227720331e-04 -2.42829973853549996e-06 -1.56085962960363479e-06 -1.80969231032599445e-04 -7.89391708141298602e-05 1.54518301113770843e-06 9.91319049322888645e-07 5.89695559936625537e-06 1.24802030089966548e-05 -2.03735635260089809e-01 1.69691379850927304e-01 -1.87271780198249392e-07 -2.19676946645712510e-08 1.52749860634589396e-06 8.59778304899942062e-09 1.17195909471439176e-07 1.27478510339835143e-08 -4.98438278508440006e-07 -4.11542878123627743e-07 2.38866069109404446e-12 1.17589843197490923e-11 -3.15630608757079101e-01 -4.56786953069863860e-02 1.08898204883334057e-01 1.03850900790870185e-01 1.43502492981653906e-01 2.64068579772752600e-04 1.54732304685143069e-03 1.98014878754102577e-02 4.66300887546951953e-03 2.38529576629519392e-03 7.31106904124441360e-04 2.76924807947468441e-03 2.43312837803217712e-02 3.75815941067826186e-03 3.38889385780084254e-03 1.04523358726793395e-03 5.88523464418498447e-03 3.49855813292192508e-02 3.79937708249956626e-03 3.99790283129961357e-03 1.17618671092358396e-03 9.38253267535743216e-03 5.19433107924765491e-02 7.00209020655463612e-03 4.61038068286980397e-03 -1.25835806920423249e-06 -5.12714592657406933e-06 -5.45455664370362464e-04 -5.01244973274503024e-05 4.02902454321699984e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -5.11808075400997722e-02 -1.37066153791403689e-01 -2.07303648244596905e-01 2.73228777561494884e-01 -1.25746582549394997e-01 1.57008542988412471e-02 1.14368716159972403e-04 1.42979227276845977e-03 8.08753275186715158e-03 6.10999976565029627e-03 1.78895726978526015e-02 4.26167908245384962e-04 2.47623504322480158e-03 8.59984374662286881e-03 1.40948791196409025e-02 1.46001067057306508e-02 9.91204624020871087e-04 3.19652223794574929e-03 5.89224507814080020e-03 2.20810095477000888e-02 1.29641469082683470e-02 1.68736876071746175e-03 3.44935802032881158e-03 4.23321839790373206e-03 2.52016225046176982e-02 7.50311306208062629e-04 -3.12213089651221140e-06 -3.24046161224581978e-05 -2.62628950558281820e-04 -5.53687863570044439e-04 7.43785714281900101e-01 -4.65773967948531140e-02 3.04372003953948429e-02 -2.54870529855179162e-01 1.88996650442137537e-01 -6.90818433435321788e-02 5.60674744445242915e-02 -6.03944166237356701e-03 1.51760700421414083e-02 -8.79160371412276848e-02 6.65994028899055124e-02 3.19215538724952341e-02 1.97386038231231638e-02 2.51547526109120421e-02 1.04279271626903456e-02 6.55784683550452666e-03 6.35099973378433318e-03 2.05176119315360860e-02 1.65392999170458424e-02 2.07808449869019765e-02 1.81986513465572999e-02 4.89487496689610703e-03 2.14224524513180123e-03 1.13819605101782833e-02 -9.13257780558130415e-03 7.82347260318093027e-03 -8.40058977916541619e-03 7.23328204917631033e-03 -6.63381742991070791e-03 -7.76248452958133890e-03 6.03238457261440729e-03 -5.08664555903082152e-03 -6.08830973986564366e-03 3.86343268843382468e-03 -2.59776403619962513e-03 -2.00374884332258849e-06 -1.62650277977684593e-06 5.13687388638860151e-05 1.73057592582741022e-05 1.27127556459371174e-06 1.03227236449838526e-06 -3.90536731838933817e-05 -1.44205559357306976e-05 -1.31865924446436938e-01 8.77371182530452542e-02 1.37581238466734423e-08 5.94943894798313647e-08 -2.54288140205931509e-07 6.10757227233597523e-08 6.12983805321133000e-09 -3.55916601503213915e-08 -6.03929888663094819e-07 -4.35887827113752369e-07 9.39610735511599670e-13 2.69435560129640742e-12 +end +case strained 5 +types Fe Ge Fe Ge Fe +cell 9 1.42099999999999991e+01 0.00000000000000000e+00 5.60000000000000012e-02 1.56000000000000000e-01 1.28309999999999995e+01 0.00000000000000000e+00 -8.99999999999999967e-02 1.34999999999999981e-01 1.51200000000000010e+01 +positions 15 1.02099999999999991e+00 9.95999999999999996e-01 1.01200000000000001e+00 2.44679999999999964e+00 1.29030000000000022e+00 8.16000000000000059e-01 7.33299999999999952e-01 2.57880000000000020e+00 1.41399999999999992e+00 1.30929999999999991e+00 5.17800000000000038e-01 2.72680000000000033e+00 3.16689999999999960e+00 2.78339999999999987e+00 2.22999999999999998e+00 +spins 15 8.00000000000000044e-01 1.00000000000000006e-01 2.00000000000000011e-01 2.00000000000000011e-01 9.00000000000000022e-01 -1.00000000000000006e-01 -2.99999999999999989e-01 4.00000000000000022e-01 6.99999999999999956e-01 5.00000000000000000e-01 -2.00000000000000011e-01 5.99999999999999978e-01 -4.00000000000000022e-01 -2.99999999999999989e-01 8.00000000000000044e-01 +potential 5 -1.08498322097417527e-01 3.15258241658601057e-01 -1.13203852532121119e-01 3.15129367316841824e-01 -9.58266421135702817e-02 +forces 15 -1.46243931119742487e-03 2.77276763772356209e-02 2.36443819357677869e-03 -2.21846043610980648e-04 -1.22935329538018182e-02 -1.24618259154602624e-02 -2.29875701086015086e-02 -2.23744537310844108e-02 -1.25228333663011011e-02 1.27872070849805700e-03 1.10644463186621023e-04 7.44739364309045596e-03 2.33931347549118582e-02 6.82966584446399044e-03 1.51728274450941298e-02 +virial 45 1.09662205003788656e-02 -1.02562656999678173e-03 -3.53018809996658630e-03 4.09008406632935598e-03 -1.58804515551666803e-02 -8.83599301970332783e-03 1.96959975370130432e-03 -8.10520422519815133e-03 2.61316192648512052e-03 1.03932846732088073e-03 5.34893089994233246e-04 4.50200464705288565e-03 1.53626475612873761e-03 1.77615259134217968e-02 1.60701473544908081e-02 5.56620644167087758e-03 1.76686029957891788e-02 1.58707008378847145e-02 2.53580767162554406e-02 1.23763058439027296e-02 1.19774952938721431e-02 4.31655401236023632e-03 -2.01990775645518386e-02 -2.95211825922497059e-03 8.64863598702963685e-03 -8.37118223271559095e-04 1.61044313006685402e-03 -5.72283947588274680e-03 -8.60204401217557792e-03 1.76845684895756295e-03 -7.58285523066462488e-03 -6.55134558293291036e-03 -1.13982782041730478e-03 8.46132955032597583e-05 -1.04714250717442316e-03 8.32998678345346112e-03 2.52244126740170174e-02 3.13161435549724494e-04 5.82343308103604532e-03 2.39134195544278604e-03 -2.00848877653556340e-03 -3.07229613901115629e-03 5.21901156539997073e-03 -5.75586985706626631e-03 2.35340635583184722e-04 +mforces 15 3.09986794025962891e-03 1.68377985753053495e-02 2.70599400999103241e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.12747710842892954e-02 1.01389589657995861e-02 1.24153872654383275e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 1.82452067904501636e-02 1.77277650059869951e-02 -3.12637062167512572e-03 +tau 15 -6.61565705070037645e-04 -2.10279784918763341e-02 1.31602520662183180e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -2.13111636988437807e-03 1.16169559386340038e-02 -7.55159612345559454e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.32443008182870602e-02 1.33456171836900811e-02 -1.61754396525974945e-03 +descriptor 425 -1.02276431807068691e-01 -7.54024624507977914e-02 -1.74108507775408289e-01 4.82777274865200334e-01 -4.11214724871681314e-01 1.34738727101999401e-02 5.29161679376475343e-03 3.85557511675083337e-03 2.18093624090613626e-03 8.27483415489234722e-03 9.92285227225611459e-03 2.02467380472679415e-03 7.52725123365514774e-03 1.38280749397188380e-03 2.11046946327470772e-02 1.45860681730504028e-02 1.35476559703624124e-02 1.64728559494597068e-02 2.30881175333827633e-03 2.24914212504507792e-02 3.00881927297188163e-02 2.82848634042846998e-02 2.39373617765167995e-02 5.44112669717587011e-03 2.45434115157715411e-02 2.80994406810357821e-04 -3.19698978421215440e-05 3.93886041180352832e-05 5.86150942490222477e-06 -8.73283161412617627e-04 5.76642857139900156e-01 -7.20696697477793830e-02 2.09191846997278559e-02 -3.20018914687680678e-01 2.10645562837251027e-01 -3.85056678125956370e-02 2.24698305902845293e-02 -3.60945498927579753e-02 -7.47158849262650245e-03 -4.08875049188369769e-02 1.31775172320629675e-02 5.53476358621052128e-02 3.90897219763738160e-02 4.19111319873445368e-02 2.54654445041150902e-02 4.65783805964236977e-02 2.77162628281066338e-02 8.60162907317460652e-03 8.43528796049876697e-03 2.66292090661906893e-02 1.75416007397381606e-02 9.70080138246913817e-03 1.17454715238159190e-03 6.31134962764238073e-03 -2.12792833450823043e-03 8.90037028348664660e-04 1.39374883005243997e-03 -9.54795960569028760e-05 -2.53434541423542420e-04 -1.53493169870211896e-03 3.78719698018635477e-04 -8.46119183469662010e-05 -2.01219706809356840e-03 4.18818166175338464e-04 3.89696018582387355e-05 2.52114003316642476e-06 2.50080102880066189e-06 5.91352487339454557e-04 3.38554151298791175e-04 -1.80957528635848502e-07 -1.85632871957982286e-07 1.11904781572758205e-04 4.41759488180720536e-05 -1.48100218996599836e-01 4.47576587468732010e-02 1.16894208494114522e-06 8.57959589947110452e-07 -2.50831357182889329e-06 -3.46499490714387291e-06 -9.12890533018577515e-08 -6.77586024460497242e-08 6.48632510672687313e-07 -7.12206630240835555e-07 3.02152356111559343e-10 2.86326594642703070e-10 -3.21697946179745120e-01 -6.34383644000802438e-02 8.79640348992093701e-02 7.97233359752247961e-02 7.73705881143963159e-02 1.00526849838234486e-03 2.30155259385825001e-03 2.58820437024729448e-02 3.51107953757774996e-03 6.32656288759144390e-03 3.06353392545862966e-03 3.50234692136121512e-03 3.60723361385138150e-02 6.48709267592078361e-03 8.10385304634980361e-03 4.04578602958585373e-03 6.87964848152918668e-03 7.25901495815683001e-02 1.31021099187478875e-02 1.00400371622792126e-02 3.86310112042774229e-03 6.76016559399578512e-03 6.77164359276463956e-02 1.19590206219860329e-02 2.18013056582773875e-02 -4.73392889238781646e-05 -2.23644741369774499e-05 1.36377345582134680e-03 1.36336713352059772e-04 1.14945932989427867e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.57175498266946534e-02 -1.23933679626611018e-01 -2.52551548798289338e-01 4.45057143540657452e-01 -1.72401023089740091e-01 2.39332976753160488e-02 5.14759296181932003e-04 4.58331543391576391e-04 5.18536150871397577e-03 3.57384440858600971e-03 1.66266114665768842e-02 1.54298554397060204e-03 2.42432223396619887e-03 3.43633756806423956e-03 6.91106512887552232e-03 1.74417319869930830e-02 2.45306243639701075e-03 6.05812419309381851e-03 1.39518488438337518e-03 2.67525759022875301e-02 3.18976348104379262e-02 3.60632540898578758e-03 9.26610500015421883e-03 4.97987359655068570e-03 4.81263454199324925e-02 2.56426370576835901e-04 -1.56566830546968905e-05 3.45221783200958593e-07 -6.14519529589145435e-05 1.02983670214488386e-04 6.18428571425399976e-01 -4.37219570976270303e-02 1.15342732706803560e-02 -2.26783422908236221e-01 2.06199713577205151e-01 -7.71895463954902755e-03 9.25656769802050278e-03 -2.38700919720411355e-03 1.09218728226755084e-02 -1.39555518569403729e-02 1.87154397507512371e-04 3.88509402724354289e-02 5.75064405578092977e-02 4.93197535879924434e-04 2.09078231624815853e-03 4.71369205659906421e-02 6.29556670026156090e-02 1.44419094840090561e-02 2.06192487160023474e-02 2.29740284640068022e-02 2.88335631039364007e-02 4.64009517596075411e-03 3.70480747520942353e-03 1.46522022543673410e-03 -9.87395908599889623e-04 1.21131884194743415e-03 1.39378915496561292e-03 2.51071002796311531e-04 -1.04281463052776518e-03 6.05595351223396942e-04 3.17112008115614716e-04 -8.25880309529925861e-04 -4.17258287598008771e-04 3.32820562105025288e-04 -2.95356988004450425e-04 -4.83964196463204601e-07 1.90426176173421701e-07 -1.26580199753091344e-04 -7.13947176121641509e-05 2.69429402696015866e-07 -1.01209859225659843e-07 -1.26668253800510597e-06 1.43624634945336562e-05 -9.89228159840131877e-02 2.29372892240634098e-02 2.00996046412653187e-07 1.73895876064961800e-07 2.94879894815372339e-06 2.92636794067493259e-06 -1.10507863024750917e-07 -9.53209116786965890e-08 -1.59788289357676090e-06 -1.89819423211463652e-06 1.48997492596699940e-11 -1.64931831263869767e-12 -2.67307980043016757e-01 -8.48438114131245674e-02 1.22729295432109670e-01 1.05943573097951063e-01 9.38456546664994395e-02 6.56672626348225093e-04 2.13241618265598001e-03 1.75142362898076595e-02 2.64525865591000182e-03 2.41395862047906907e-03 1.59634187457638834e-03 2.11936101991179633e-03 2.32820869033610184e-02 4.02661774033554690e-03 4.05725871239115583e-03 2.66385509483321433e-03 2.99038338381907775e-03 3.16427313545239730e-02 6.55882580351152458e-03 5.37867195868666284e-03 3.64092044458291320e-03 6.12397947418405995e-03 4.83251750478546904e-02 1.07324327223637331e-02 6.20975876993596146e-03 -1.67153010117699515e-05 -1.60099601889987002e-05 -9.54889019689022004e-04 -4.79243237786853920e-05 7.39907258974648735e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -3.68110452036635172e-02 -1.09830927958438421e-01 -1.93928679064428122e-01 2.99724702387080599e-01 -1.76778817747582195e-01 1.65683086030372108e-02 4.58742546940883148e-04 1.24090287790347940e-03 8.64662500161532226e-03 6.77836203226294710e-03 2.05818206126585565e-02 1.37809699317148547e-03 4.19674696880101544e-03 9.19171956297653789e-03 1.52059241325971824e-02 1.84321586640518384e-02 2.65888263708931620e-03 8.18704175522314351e-03 5.84793338716114216e-03 2.48754003662868713e-02 1.56882834461566090e-02 3.72148364162350198e-03 1.10639920151365725e-02 3.37549779717411218e-03 3.13648292565695541e-02 9.95465805260724920e-04 -1.80278335460533054e-05 5.24920625804457099e-06 -3.09431705378305502e-04 -6.37105912691158984e-04 7.43785714281900101e-01 3.33268257999239231e-02 -6.77268513393658889e-03 -1.77324243651665991e-01 1.05434147700752379e-01 -1.61017761770864201e-02 4.08623310485808650e-03 4.63263508235956731e-02 -4.47331625160171751e-03 -3.38623239396347725e-02 1.62640328565118591e-02 2.49542698013195882e-02 1.02452629353765381e-02 1.62170822722507053e-02 3.30331744732429659e-03 3.71671446035436864e-03 4.33875465980935494e-03 1.81540617775132439e-02 8.84244754405539603e-03 1.64076664999069192e-02 9.48672954638784920e-03 -6.47766642798041758e-03 1.04415750835702313e-03 3.75378435591377981e-03 -2.42172245698552956e-03 2.76432848094548258e-03 -2.17127390174346813e-03 2.14531116785940997e-03 -2.76867136574465928e-03 -1.08012416789416018e-03 1.32086045821679923e-03 -1.76112185382961534e-03 5.28858504764584728e-04 4.32015769972171921e-05 -2.08898813631234901e-04 2.74478523653562402e-06 2.05257264950681818e-06 2.91411339230413385e-05 1.27664254604042269e-05 -1.87483659809983450e-06 -1.40408430653566730e-06 -2.63592577297284005e-05 -1.11170778064109762e-05 8.95614145664085370e-02 -2.47647040865241821e-02 -8.49264914507795253e-07 -5.97286860396118520e-07 -3.04190462822702632e-06 -1.70216091184038905e-07 5.88164949536916874e-07 4.12366904291819604e-07 -6.73482674371293297e-08 -4.20273997700852409e-07 -1.10591840854671597e-11 -1.04224848002940492e-11 +end +case random_multitype 8 +types Ge Fe Ge Ge Fe Fe Ge Fe +cell 9 1.30000000000000000e+01 4.00000000000000022e-01 -2.00000000000000011e-01 0.00000000000000000e+00 1.40000000000000000e+01 2.99999999999999989e-01 0.00000000000000000e+00 0.00000000000000000e+00 1.35000000000000000e+01 +positions 24 1.05195795123286806e+00 7.54513157485344976e+00 1.92678016605364433e+00 6.46852031811661554e+00 3.67791605244682529e+00 1.05287067051035566e+00 4.81735914385441433e+00 2.66519633158947888e+00 4.46326047297769435e+00 1.31815556951734236e+00 7.47518901279024117e+00 5.42123896216220835e+00 6.89722237837808461e+00 4.40524688937426134e+00 2.81634767538512243e+00 7.91697690449841840e+00 5.61941046163939095e+00 7.59164543829853056e+00 7.22363391762259788e+00 1.69287733412652353e+00 7.21909484608720842e+00 1.96643034124545912e+00 3.58552152099393107e+00 3.24131466612851726e+00 +spins 24 3.42956689606492948e-01 -1.44334109384587284e+00 -9.20576318816501371e-01 -7.93035969575581312e-01 -8.50622373758950362e-03 -1.58959621466146922e-01 5.74721063246211528e-01 4.25502328712981936e-01 8.60292342154923562e-01 -5.68052435501097297e-01 6.94785435747145463e-01 1.51775094776792541e+00 -3.21782166655971369e-01 7.04734259188120715e-01 7.16111647147331332e-01 7.38660791723244614e-02 -3.32854884286343966e-01 4.08657239828918162e-01 1.49528411107386322e-01 -7.40695736034854835e-01 1.30976057471167306e-01 -4.33378437932692290e-02 2.65331202826330936e-01 -1.14193824659042251e-01 +potential 8 3.04100791523011948e-01 -1.01993022432103259e-01 3.12958722714717252e-01 3.03895029320121246e-01 -1.00272040721369277e-01 -1.02567741661746287e-01 3.05038059901286296e-01 -1.03452630685564151e-01 +forces 24 -2.25801695383783327e-04 1.57772790279343670e-03 2.09234319779494533e-03 2.96602341784779015e-03 5.94566162531114193e-03 1.71657800544349586e-02 7.56054742509628015e-03 1.97765935955334727e-03 -1.54205786629487210e-03 -2.06181064846135511e-04 4.42518215570366930e-04 -2.21437626449219258e-03 -7.90854541589545469e-03 -7.17011206938467961e-03 -1.44004928569241245e-02 2.46534487984172081e-04 2.94063591244989866e-03 -4.49209099796846353e-04 -1.82317279966102172e-03 -4.26553792310465502e-03 3.47252382396936099e-04 -6.09404355141847810e-04 -1.44855302318885881e-03 -9.99239547118808882e-04 +virial 72 1.37598229318738728e-04 -5.26715094230065239e-04 -2.36813893834984812e-04 -7.00950106882901607e-04 2.30901194880101836e-03 -3.52933503430630723e-04 -1.04448514959216003e-04 -6.75608472023416949e-04 -4.30196019210048620e-03 -1.04281932549718666e-04 -4.53650334057917120e-04 -5.71772123076713223e-03 -1.11669117346640805e-04 -1.78955205588209000e-03 -6.93154203794725532e-03 -5.53374316698633170e-03 -7.96864908623160992e-03 -5.01329840261239158e-03 -2.17401748648157096e-02 -9.60519412927532575e-03 1.00446490783729844e-02 -1.07237562868172896e-02 -1.05153732558162048e-02 1.10502269251271119e-02 1.07080347984169003e-02 1.11724081635526506e-02 -2.52954413248855509e-02 -8.05380331191304650e-05 1.26878846857492742e-04 -3.48908367908829691e-04 3.35732466184486891e-04 -7.29409129844287105e-04 1.37412862169126408e-04 -1.53113981566073724e-04 -3.35056519497009455e-04 -4.44876846357036143e-03 2.99699630979343486e-03 2.42000267426608707e-03 -7.52018480874730704e-03 1.64022528353609080e-03 1.49454728694285548e-03 -1.04523486320097884e-02 -9.41122877468452725e-03 -1.02831548286651236e-02 -1.10768037036591497e-02 8.49985366238751499e-04 1.94245852114192236e-03 4.85251166002726613e-04 1.94003170668558488e-03 8.37205480626992786e-03 9.95856072158708304e-04 4.82194824222524025e-04 9.65743143226095073e-04 -7.77644589292102173e-04 -1.36525908348454671e-03 1.15998042008964635e-03 -1.06066015215118244e-03 1.36566604824442557e-03 8.38859627855471218e-03 -3.72756816873281993e-03 -1.05996865636741973e-03 -4.33284230958815627e-03 6.75426422441325995e-03 7.44054375123516867e-03 -4.66809506593437226e-03 4.90881282549799139e-03 -4.65625447407815550e-03 7.34436665756968074e-03 -1.41752475783220528e-03 4.84843825086809978e-03 -1.37488892156362478e-03 2.67818266759925396e-03 +mforces 24 -0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 1.50176120920007816e-02 2.70401208660732873e-04 4.52890526632447003e-03 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 7.70474687061704997e-03 -1.18954301922314844e-02 -1.32341008221709949e-02 5.90803161436182227e-04 1.14630025018611428e-03 -3.46622037857267700e-03 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -2.03075232395963519e-04 -9.93860079068242634e-03 5.49262989705653383e-03 +tau 24 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 4.45899229099538884e-06 1.20439084552570745e-03 -8.66947162257851624e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -8.08068130448591601e-04 1.25896133606906695e-03 -1.60206177753519346e-03 6.85304486764519937e-04 4.97472098147082797e-04 2.81324422971349465e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.22439261218468779e-04 2.61228673973695443e-04 4.84599724266114747e-04 +descriptor 680 -3.44114736151920064e-02 1.86180867479240064e-02 5.70409350194572770e-02 -4.11230975355890566e-02 5.10596697295911672e-02 1.45173245391687697e-05 6.09988458476464626e-05 4.23089609772806766e-05 1.21730760932601450e-04 1.86173006913540034e-04 1.88642277944261757e-05 7.02667722732145425e-05 4.84360678400616883e-05 2.12205904947975285e-04 4.61464312709406247e-04 2.69224325439909480e-05 9.77443034040588666e-05 6.72353666323891779e-05 3.16878853930088354e-04 7.16291139035507693e-04 4.62116267771717240e-05 1.84093443199888140e-04 1.27049940788585798e-04 4.42020630691291510e-04 8.19652402777943843e-04 2.44322529561276452e-08 -1.36557013749831249e-07 -7.62961654523313699e-08 1.08976492358664936e-06 -2.96208681365751854e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 4.79519063854449076e-02 -5.76477145115504089e-02 -5.60153026269178608e-02 2.12836707723255497e-01 -5.02329376751375067e-02 4.56431265394115215e-03 2.84178458687084953e-04 1.42067769343092305e-04 2.21955269112227157e-04 2.42312577480806746e-03 8.33555878999734171e-03 4.24628491937504378e-04 2.59085809862142236e-04 2.67478084275615271e-04 4.96368902328498361e-03 1.26606929488786747e-02 5.46404045396507417e-04 3.92980436091569995e-04 2.62797701870305417e-04 8.09148974723642236e-03 1.74147970924642542e-02 7.37485324742832632e-04 5.39647353275560042e-04 3.41061243578866962e-04 1.11721172217613459e-02 2.76552501744960471e-04 -3.01957477252810115e-06 -1.48575646928377593e-06 -1.21589088955731228e-06 -1.19967347414364812e-04 5.46763201699590362e-01 1.20239130634508789e-02 7.75481971651907870e-04 -6.62602462142716231e-02 1.23040386829932014e-01 1.66060751803571841e-03 -2.32375620104545190e-02 9.16067281558835371e-03 -1.43492533422094164e-02 -1.08138299738303224e-02 8.90600990538740686e-03 3.79715501119268738e-03 1.46651569886301850e-02 1.60324420081874963e-03 8.59392059814467583e-03 1.14873939249903172e-03 3.98592731428568450e-03 2.28132302672068733e-03 9.22885302109056373e-03 1.74314287045915315e-03 8.42822332825127370e-03 -9.50681743276767703e-04 4.99008585771518317e-04 3.89432550003004886e-04 -3.23940863075076731e-04 3.84376519939831933e-04 -1.80753707752055390e-04 3.46741730021055833e-04 -3.93696462326095721e-04 -1.08754283081643476e-04 2.10521556787681281e-04 -2.40391844538101463e-04 -3.04510485552373636e-06 9.69777836885899138e-06 -1.30969142450111070e-05 -8.35939041905153484e-08 -4.37255689324034047e-08 1.02507489322562571e-05 3.87665708516312981e-06 6.49969544604175449e-08 3.41551822752939885e-08 -5.87083072738776168e-07 -4.07865063547054240e-08 3.43140272401297741e-02 -2.08481673547293919e-04 -3.46412220265093489e-08 -2.36681643877278558e-08 2.79104606344528412e-07 -2.64305006171947799e-07 2.62290931730564604e-08 1.78858266485131038e-08 -1.09394327565361910e-07 7.72479272618821835e-08 -3.68911036705571941e-14 2.17277783251926755e-14 -1.55396506855348393e-01 -6.65593682471745662e-02 6.89216622691256608e-02 9.34604366069386322e-02 8.22585687784110203e-02 2.53226637091085729e-05 7.73394953571378274e-04 5.00071879169492243e-04 4.75593984041219994e-05 1.53887525790616801e-05 6.94139070856514859e-05 1.20550983279762904e-03 6.42025178967086762e-04 7.92780818893201495e-05 1.19600949790416611e-04 2.14773354232470042e-04 3.35100522557259207e-03 1.83226830702566267e-03 2.38628335310274832e-04 1.07144668350352468e-04 2.83893126830596766e-04 5.04670305640859528e-03 2.56945768728946778e-03 1.29915471187265453e-04 3.00071593488749093e-04 4.80193784615965829e-08 1.36980447565459188e-05 3.59661013232446859e-06 1.19410126751703110e-07 -1.91659119607233226e-07 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.91876716087522969e-02 2.39032025338826760e-02 6.06853058452816035e-02 -4.18215171396897206e-02 5.13285272312208954e-02 1.18921361679660737e-05 4.69595394336680652e-05 2.10704216447355245e-05 1.14357194076122174e-04 1.88713985585057490e-04 2.08325585305602076e-05 7.64638450675900319e-05 2.20944002052686293e-05 2.20185960889060370e-04 3.97953235783157257e-04 3.09790175800071888e-05 1.10091672828704521e-04 2.37598500323323445e-05 3.39045932483903357e-04 6.31619991930627953e-04 4.29939399107434945e-05 1.57102164118470280e-04 4.43791126638193645e-05 4.53400199033849693e-04 8.20293513302459607e-04 3.45293806824607915e-08 -2.37495855798468950e-07 -1.92855676367490630e-08 1.14595254809222743e-06 -2.68642004698085176e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 2.43036928119996012e-02 -6.77704616679622174e-02 -9.48999521147003977e-02 1.93140879172906732e-01 -1.73197728380275057e-02 4.62021533845817858e-03 1.03326875209110614e-03 2.90110053769974041e-04 5.03963540825565605e-04 3.47310533133475497e-03 8.22762219276598587e-03 1.73921915728597284e-03 3.10808799383487284e-04 7.23314163278775558e-04 7.64814376944224911e-03 1.26061091826009299e-02 2.93606025473100657e-03 1.04280100745949233e-03 1.57912144019658422e-03 7.54704505901312474e-03 1.73941709440577560e-02 4.12959293489787577e-03 1.60590544462519487e-03 2.31484015334088543e-03 9.14828250028106374e-03 2.71075017877838169e-04 -2.53962039901826715e-05 1.50575832674105946e-06 -4.74104868108782958e-06 -1.55243110114080374e-04 9.30158382235677372e-01 -2.34690326216245825e-02 6.71050684015756516e-02 -6.44342681463526690e-02 1.59974451077191382e-01 1.70911896451413081e-02 -5.01664735508639131e-02 3.92324520995701673e-03 2.00181466727445464e-03 -2.13735274042623491e-02 4.79076883112523194e-02 8.28869255462875662e-04 5.63063715018379939e-03 6.64882658336820979e-05 3.76546596678146355e-04 3.73969771791986044e-03 2.55986958172801614e-02 8.46384517359716638e-04 5.51792387307528751e-03 2.32198994305918326e-03 1.54252994783434516e-02 7.64354126851839871e-04 3.87683374747421544e-03 8.74242417048885345e-04 -2.06693022517473023e-03 4.97483373542055227e-03 -6.27164797877963258e-05 -2.59844609506944334e-04 1.68721257528283547e-03 -2.16012093049621737e-04 3.39559507409653647e-04 -4.17025516586485732e-04 -2.08071216455123838e-04 4.74094171184646798e-04 -1.08507591923410053e-03 -1.47086101859667033e-08 -7.18506430283824293e-09 2.04294089580652892e-04 6.96564168737003666e-05 -7.30993182408990194e-09 -3.36620996587215013e-09 2.76933669907492055e-05 9.72929128644503885e-06 -8.26642305198485305e-02 2.24205708303041262e-01 -1.61311782380517487e-08 -9.96833251276528491e-09 5.34753632464561030e-07 -9.50901448850927747e-07 -1.17453413133469909e-08 -7.11315031226662493e-09 -5.47706521285111507e-07 7.69243615147013800e-07 2.66949542169886240e-12 -2.28329414371734043e-13 -1.92308136926794236e-02 -1.31456948482829936e-02 -2.10557765017861005e-02 2.89788376747549883e-02 -3.14708674536539404e-02 5.85552889017074116e-07 1.47872466228329282e-04 6.62408913707872145e-07 7.71482395509776741e-05 2.45874628531442026e-05 1.05368414956070549e-06 2.65783844528519613e-04 1.18926696862734396e-06 1.38358376381233600e-04 4.40487006171380789e-05 1.58402554439680456e-06 3.99159010147087277e-04 1.78432671347979867e-06 2.07390894915173059e-04 6.59656150706502102e-05 2.17657707352537663e-06 5.47997963084033467e-04 2.44758814830820974e-06 2.84245795152796824e-04 9.03382062136808169e-05 -3.93138294160327154e-10 -1.55935233836109243e-06 4.62187344124478223e-10 -5.74418307587342364e-07 1.02214357530592412e-07 2.36715495879417703e-01 -1.00967205773855890e-02 5.62771996137053417e-03 -2.04865260696614204e-02 1.22287502932094255e-02 -2.03342293617329211e-03 1.42392689357514579e-03 1.03167340664394539e-03 -5.26020760876954956e-04 -3.37401467452094457e-03 1.87502912008881569e-03 7.21200439545384431e-04 2.07223130202608736e-04 3.75583491809588956e-04 1.10789695375843996e-04 1.97479102444702702e-04 5.11325454552785238e-05 4.87359690942806639e-04 1.53882553472441233e-04 4.61795024930054527e-04 1.48689697027668818e-04 2.32767058836587094e-04 6.98471736358232054e-05 1.21033790673897833e-04 -6.81607937580808816e-05 3.84084027932403532e-05 3.02716825993989460e-05 -1.59605953668319689e-05 8.35626720722497882e-06 2.26529321801917198e-05 -1.17978085074571466e-05 6.08737208462855467e-06 8.97715449114591538e-06 -4.50319612109392086e-06 2.21521418987733692e-06 4.65776652446602644e-10 3.41425814766301468e-10 1.22663299078779534e-07 -1.34315188726115301e-08 -1.33403471535223357e-10 -9.76787722706955479e-11 1.28148384827504154e-06 7.09988902338459074e-07 -1.40797251653431727e-02 7.73346683689977391e-03 1.23077218710623122e-10 9.17943611873602644e-11 -2.29683017161071127e-09 -2.90650074383325446e-09 -3.49428807316435454e-11 -2.60248440373838646e-11 4.44354163995172389e-10 3.86895349797781838e-10 -1.97375523559335358e-17 -4.70299853013884871e-18 -4.63920033044187136e-02 5.78861317504657073e-03 3.99812648673872340e-02 -3.19614956498119399e-02 4.95078663382726158e-02 5.18226490461428532e-06 9.58210584503361404e-05 5.86968864388365337e-05 4.05260673556339873e-05 3.76789184495582630e-05 1.12747477663737902e-05 8.26154263663691796e-05 6.67367783747639280e-05 4.20260524527173477e-05 1.05954444686226897e-04 1.49726828992332455e-05 2.14856706211747424e-04 1.39241864418202210e-04 9.39894889734903846e-05 1.19828763993967894e-04 1.72669380274639858e-05 4.46693103493481594e-04 2.56311313423936930e-04 1.80533138932443323e-04 9.93452536027660573e-05 1.24644608912192789e-08 2.28204479070444991e-07 -7.30882789829024203e-08 6.33016344940391075e-09 1.17190407714150749e-07 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -6.07519773076615963e-02 -4.48763498126867541e-02 -6.73534736112026411e-02 3.62780520365339615e-02 -3.79450056455554047e-02 7.23654991923344314e-07 9.22782044675384298e-04 1.87911641051182864e-04 3.74795351456223965e-04 3.38360792374442379e-04 9.49024278043105418e-07 1.92485579252900862e-03 3.08214568362735037e-04 8.13675761298039940e-04 6.83995405527871875e-04 9.83570635812497389e-07 3.46123786672951263e-03 3.61781253505272531e-04 1.58876881067079932e-03 1.25762029106812477e-03 1.00095430627400275e-06 3.76719696233450852e-03 6.07827694561470316e-04 1.58527112625850308e-03 1.38514167838505223e-03 -2.96911731890821882e-10 -2.91404527975477124e-05 -1.83415989160625243e-06 -7.47794467197943093e-06 5.95418412923645604e-06 7.13023451576112188e-02 9.37560216149629228e-03 -4.10517170444163731e-03 -2.33019064370005496e-01 1.64655310056159049e-01 3.09911053471053320e-03 -8.25552841376461267e-03 -2.16394318304596097e-03 5.29508102225104724e-04 -3.10218817427173514e-03 1.20144786795040362e-03 2.57835378811667676e-03 8.13075817928373031e-03 1.10587578159504333e-03 3.57493117819465949e-03 2.65088149135664971e-03 6.50559727912911143e-03 4.61548939984402721e-03 5.83645641556408343e-03 5.01245743737731547e-03 5.77637722142908174e-03 1.56976008505251133e-04 3.56478617956272061e-04 1.41940056362543199e-04 -5.42121822932152810e-05 2.12794128777637441e-05 -1.24934746813194304e-05 -2.55211801136178206e-06 3.58191626671874207e-06 -2.74285234656583072e-05 1.49490969274893455e-05 -7.57760340610730293e-06 -1.26075941036178264e-05 3.43647154218964045e-06 -8.80251140366019735e-07 -1.64342305124510189e-07 -9.61193596733930399e-08 2.37768960773599104e-05 1.51389625827838428e-05 -7.21429508014441419e-08 -4.25596260783183390e-08 -5.86898905363207721e-05 -2.74642567709335221e-05 4.10215047271312028e-02 -1.67670435412835099e-02 2.61622015745123660e-08 1.84610810357898668e-08 3.64660514037887409e-07 -6.41231294984235358e-07 7.19650917988572176e-09 5.03957833140624911e-09 -5.86590204326049517e-07 -1.89994341274391102e-07 -6.90878501200705088e-13 1.19148425210728933e-13 +end +case pbc_wrap 4 +types Fe Ge Fe Ge +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 12 2.50000000000000000e-01 1.10000000000000009e+00 1.19999999999999996e+00 1.34499999999999993e+01 1.39999999999999991e+00 1.00000000000000000e+00 6.79999999999999982e+00 2.00000000000000011e-01 1.44000000000000004e+01 6.50000000000000000e+00 1.25000000000000000e+01 4.50000000000000011e-01 +spins 12 6.99999999999999956e-01 -1.00000000000000006e-01 2.99999999999999989e-01 -2.00000000000000011e-01 8.00000000000000044e-01 4.00000000000000022e-01 5.00000000000000000e-01 2.00000000000000011e-01 -5.99999999999999978e-01 -4.00000000000000022e-01 2.99999999999999989e-01 9.00000000000000022e-01 +potential 4 -9.92921517100119055e-02 3.10190714093547260e-01 -8.53094557609729853e-02 3.12481088925483597e-01 +forces 12 -2.57237949549735424e-02 6.35832324657400246e-03 -8.44957422755218332e-03 2.57237949549735424e-02 -6.35832324657400246e-03 8.44957422755218332e-03 2.43543776298446807e-03 -1.83989786522077486e-03 -3.18081488572111853e-03 -2.43543776298446807e-03 1.83989786522077486e-03 3.18081488572111853e-03 +virial 36 -1.30918246472596731e-02 4.90943424272237330e-03 -3.27295616181491611e-03 4.90943424272237330e-03 -1.84103784102088879e-03 1.22735856068059267e-03 -3.27295616181491437e-03 1.22735856068059202e-03 -8.18239040453728160e-04 -7.48721131671918096e-03 1.77224354536832315e-04 -3.48670322022683662e-03 2.80770424376969134e-03 -6.64591329513121182e-05 1.30751370758506276e-03 -1.87180282917979350e-03 4.43060886342078620e-05 -8.71675805056708179e-04 3.36375396595747973e-04 7.84875925390078350e-04 -1.17731388808511839e-03 7.84875925390078242e-04 1.83137715924351543e-03 -2.74706573886527488e-03 -1.17731388808512013e-03 -2.74706573886527921e-03 4.12059860829792207e-03 3.94255932299592059e-04 -1.33684528495631042e-03 2.23069422368783396e-04 9.19930508699048390e-04 -3.11930566489805952e-03 5.20495318860494591e-04 -1.37989576304857389e-03 4.67895849734709275e-03 -7.80742978290742753e-04 +mforces 12 -1.15652213404332585e-02 1.54906829098488373e-02 3.73269823589186551e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.69162657445878217e-02 1.98516978283194917e-03 2.46006035822866585e-02 0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 +tau 12 -5.02047469654383696e-03 -6.08245516725428297e-03 9.68695590285085888e-03 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 6.11122258615650130e-03 -2.15054234439063675e-03 4.37583804033353941e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +descriptor 340 -5.32647174737394952e-02 -2.90005009069129321e-02 -2.33707105154369529e-02 2.90676644302350178e-02 -6.72033708908375271e-02 4.34908783140388906e-03 6.38430429410170397e-05 1.10139813576221697e-03 4.81573862599628721e-04 1.10165175703432383e-03 7.82604782411721114e-03 1.14750567377850876e-04 1.97741364142843762e-03 8.63659081849775566e-04 1.97362081316753606e-03 1.17650623009191331e-02 1.72334488462276331e-04 2.96682921251278150e-03 1.29457308311357227e-03 2.95561751045568316e-03 1.61661312618096749e-02 2.36594806194293579e-04 4.06964484908669665e-03 1.77431586639102148e-03 4.04764184889877011e-03 2.51647966058948032e-04 -4.42367945031308316e-07 -3.13361258652487514e-05 -8.95846505523654649e-06 3.06554591452280604e-05 4.93071428568899961e-01 1.63488498402488240e-02 -1.32549061396283318e-02 -1.40425106853581921e-01 1.13822352778160316e-01 4.04583444913185486e-02 -3.27860292769238740e-02 -6.14445618868064911e-02 4.97813158804431069e-02 -1.78225489807657647e-03 1.44364019515124580e-03 2.95558447006354225e-02 1.91895985150413138e-02 4.77398743735578130e-03 3.09896982481574525e-03 2.58842870543952060e-02 1.67992229884006486e-02 1.65030756631411035e-02 1.07087294808701963e-02 2.13001614979476603e-02 1.38190759566575866e-02 -3.25488416317645498e-03 -2.11133677889626704e-03 3.94612393092265033e-04 -3.19225718870945431e-04 2.58220221094607823e-04 -1.17455235348982298e-19 5.92439044274240696e-20 -2.98800955874679834e-20 -1.20552955844895752e-19 6.07927646699597852e-20 -3.06545257114463469e-20 -1.85476014511213797e-19 6.23416249179165001e-20 -3.14289558327142047e-20 1.83183873519561972e-23 1.02329440488295624e-22 1.02370694548769895e-20 2.06388993865406997e-20 2.22961629715369815e-22 1.80551016454580242e-22 3.22355763219004671e-20 1.93776172820486380e-20 3.44426515679495115e-02 -2.78245955883310268e-02 -1.98107203348164702e-24 -1.10598486180811453e-23 9.34470480033396256e-07 7.29881588207526869e-08 -2.40552290848956519e-23 -1.94684168421501046e-23 -3.20736621163136716e-07 -2.50462742669785276e-08 8.91502577501559825e-29 9.56681352741353423e-30 -8.24615094866147230e-02 -3.50160846113524923e-02 3.00012193109828393e-02 7.35847907364700349e-02 9.36480450569126405e-02 1.41087007633410293e-03 4.68599379569618023e-04 6.80681328025675367e-03 7.32319317327973949e-04 1.71604146866133112e-04 2.53881667122882095e-03 8.42253786809647764e-04 1.22207265456474659e-02 1.31334833209201620e-03 3.07430650129037820e-04 3.81665650132779555e-03 1.26491205073790756e-03 1.83354700069562754e-02 1.96863025609237546e-03 4.60396144340329255e-04 5.24438956663103324e-03 1.73657417135439883e-03 2.51510436646247525e-02 2.69816508932905520e-03 6.30500629500008202e-04 4.64971881668313109e-05 -8.79662028360053341e-06 -4.81442641939822699e-04 -1.67992532798913733e-05 1.88465992440847680e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -7.23402185964119315e-02 2.30267774086733608e-02 -4.05081924114139291e-02 1.55675344005795618e-02 -1.63640688547461638e-01 1.39414216753964499e-04 3.43708462139657436e-03 5.27409151628835577e-05 1.78087106319724764e-05 2.01147153190228602e-03 2.50871532140608817e-04 6.17776647637749074e-03 9.46892878407973001e-05 3.19383086746235928e-05 3.60357259461318224e-03 3.77140450901119594e-04 9.27788201726493199e-03 1.42067870572174740e-04 4.78736061476767977e-05 5.39656969047822357e-03 5.18220973035500381e-04 1.27374312440589922e-02 1.94876663360438244e-04 6.56146030511325213e-05 7.39046281949746163e-03 1.44429780621412884e-06 -1.74742529722090087e-04 -3.28360032129270218e-07 -6.37071179534175626e-08 7.56331456878102035e-05 5.43214285711499989e-01 1.20613215629048892e-01 -8.31676720597189778e-02 -1.92251669883475473e-01 1.32532720730630882e-01 4.46459048277480369e-02 -3.07703574167082251e-02 -5.42326894010824803e-02 3.73692394696817087e-02 -8.94100671124455904e-02 6.15950435856011114e-02 4.39003024347941126e-02 2.06172349209650385e-02 1.83589041302987428e-02 8.62031675443219840e-03 2.69551936558177878e-02 1.26542333386066731e-02 2.64651302286933489e-02 1.24218845065458255e-02 3.16378550889379884e-02 1.48471649975244740e-02 -3.28752138227351581e-02 -1.54252054345417697e-02 2.14776174635762720e-02 -1.47769040532750792e-02 1.01659045059434537e-02 0.00000000000000000e+00 -1.89580494167757023e-18 0.00000000000000000e+00 -7.71538917407332813e-18 1.94536846943871313e-18 -3.92377929106513240e-18 -3.95682164290589459e-18 3.98986399474665601e-18 0.00000000000000000e+00 1.86713589550563010e-22 2.31636856008727827e-22 1.29917637573031694e-20 3.71564205082826229e-20 2.06601761716563858e-22 4.47203509032336596e-23 -3.96718431494816573e-20 -2.23839657468539142e-20 3.03853569380237221e-01 -2.08769390062672477e-01 -1.37308641381721434e-22 -1.70241390329903430e-22 4.56905724203965037e-07 -7.08924908699651478e-07 -1.51573158366756062e-22 -3.27902565086178093e-23 -1.56822929458444203e-07 2.43271346816542030e-07 -1.07297045006007076e-26 6.12714282178320579e-28 -1.17417291713641264e-01 -8.31344198739986974e-03 -3.90067183899393197e-02 8.77541295031859653e-02 2.67199112242264177e-03 4.21460413838679488e-06 1.36372242593615152e-03 1.19094463745237911e-02 1.27801585515762068e-03 2.31996778937379271e-04 7.58404861556688739e-06 2.45113507930140801e-03 2.13818245720438539e-02 2.29200562110353162e-03 4.15624691355505197e-04 1.14012598006847222e-05 3.68115922819291100e-03 3.20804005940498668e-02 3.43557874372209552e-03 6.22423318274860880e-04 1.56662376937404079e-05 5.05379487261069411e-03 4.40051744413146456e-02 4.70873522301334599e-03 8.52392659695452013e-04 -7.59156545200818016e-09 -4.36719169328134187e-05 -1.11420770454859121e-03 -3.87296529361918503e-05 -2.96254025844020867e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +end +case cutoff_boundary 3 +types Fe Ge Fe +cell 9 3.00000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.00000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.00000000000000000e+01 +positions 9 1.00000000000000000e+01 1.00000000000000000e+01 1.00000000000000000e+01 1.59990000000000006e+01 1.00000000000000000e+01 1.00000000000000000e+01 1.60010000000000012e+01 1.00000000000000000e+01 1.00000000000000000e+01 +spins 9 8.00000000000000044e-01 2.00000000000000011e-01 -1.00000000000000006e-01 1.00000000000000006e-01 -6.99999999999999956e-01 4.00000000000000022e-01 -2.00000000000000011e-01 2.99999999999999989e-01 9.00000000000000022e-01 +potential 3 -9.99714607634795416e-02 3.18197839767975998e-01 -1.02090771530833069e-01 +forces 9 -9.95200754950428141e-07 -6.55203319409685477e-12 3.81646374420311849e-12 4.70780812281683878e-02 4.04245292083126873e-01 -2.98532305378178819e-01 -4.70770860274134367e-02 -4.04245292076574836e-01 2.98532305374362372e-01 +virial 27 3.90923019949175488e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -8.74132905764677792e-05 -8.08490544847772510e-04 5.97064587853958126e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.67990234893465461e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +mforces 9 -9.12112167589021992e-03 -2.28028060837119802e-03 1.14014031777208706e-03 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 4.30789954334183378e-03 -1.95001884811354734e-02 1.62414889226849928e-03 +tau 9 2.71729761269576633e-12 -8.66286476291229714e-11 -1.51518914400265684e-10 -0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 1.80374143007024784e-02 4.20193936746135043e-03 2.60766783322454463e-03 +descriptor 255 -9.45621605356385041e-09 5.18272841461248658e-09 -9.95684890003848630e-09 7.72126562865520608e-10 -2.68815677166646850e-09 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 5.76642857139900156e-01 2.63540906009093450e-10 -2.20530530902088999e-10 -1.77856704962899779e-09 1.48793607786217657e-09 -3.12141313462785835e-10 2.61073748283834544e-10 -1.15356679956669135e-09 9.64621428062712695e-10 -2.87296705987175868e-11 2.40187848419744832e-11 6.03433872484186784e-18 4.17363696747962164e-18 9.32811087875630373e-20 6.45048319954575840e-20 6.18363479222332809e-18 4.27522811567955422e-18 3.21665514137886605e-18 2.22351484137479006e-18 4.34879769718400235e-18 3.00557649624128957e-18 -6.64541100065664150e-19 -4.59204668836284621e-19 1.02539779639074342e-19 -8.56151790994484968e-20 7.14783273455082522e-20 -1.30401506647206731e-35 0.00000000000000000e+00 1.32694280396829993e-35 -1.33840667265623106e-35 0.00000000000000000e+00 1.36133441015246367e-35 0.00000000000000000e+00 0.00000000000000000e+00 -1.39572601621625679e-35 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 5.24149455441151082e-10 -4.37037454639009238e-10 0.00000000000000000e+00 0.00000000000000000e+00 3.76679147544312045e-30 7.82420239110866575e-31 0.00000000000000000e+00 0.00000000000000000e+00 -1.29286905929500957e-30 -2.68491659707872405e-31 0.00000000000000000e+00 0.00000000000000000e+00 -2.72226844063625462e-01 -6.55645332435197403e-02 1.43694548132365513e-02 2.15369059060903895e-01 1.72352903361884996e-01 4.62370242821188971e-04 1.27605340811850348e-02 1.85699188870036454e-02 8.06689859238085213e-03 5.72207721524236224e-04 8.32020822076441689e-04 2.29356004727593495e-02 3.33398157624158614e-02 1.44672515947219579e-02 1.02511620522947205e-03 1.25079440189793047e-03 3.44451018009611365e-02 5.00216733977199776e-02 2.16855410829995196e-02 1.53517402441930603e-03 1.71869098228565986e-03 4.72890380657905382e-02 6.86154917941207282e-02 2.97217670572136120e-02 2.10238117909374240e-03 -8.72330326353498565e-06 -1.25001884203299399e-03 -2.16942083853579725e-03 -6.14184905616135617e-04 1.14755074438959742e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.68214732286710716e-01 -2.08682051201021304e-02 -1.33995155927235793e-01 1.85248626253599114e-01 -5.34317316903695702e-02 2.52667168161865505e-03 2.18444869829251091e-03 4.59550540688331410e-03 8.31437615971793338e-03 2.71212721140220081e-03 4.54666683744743734e-03 3.92629667994456345e-03 8.25061781545548788e-03 1.49110801850673071e-02 4.85880467961223670e-03 6.83509988774263621e-03 5.89658374116226042e-03 1.23788839337070945e-02 2.23508134788466470e-02 7.27635627630913561e-03 9.39197083250427681e-03 8.09530988194562262e-03 1.69803037619362732e-02 3.06335760410560293e-02 9.96478200149292226e-03 1.11434424931775358e-04 -8.85372556727694103e-05 2.67072221864289561e-04 -6.42663664536941340e-04 1.18414916258275125e-04 7.85571428567400032e-01 -2.54572496114476889e-02 2.46535007074503640e-02 -1.32157050095929207e-01 1.27953094951257451e-01 1.29612244499829055e-02 -1.25459747547701939e-02 5.71441244797366091e-02 -5.53008958799991596e-02 -3.60775838859445910e-03 3.49063354027657298e-03 3.33173056193565367e-02 3.08636803435337198e-02 5.15031613521020116e-04 4.77007590941334110e-04 3.41416117996242927e-02 3.16149379991962631e-02 1.77600707060412213e-02 1.64426977808605213e-02 2.40109527424034741e-02 2.22259753186073335e-02 4.76985729807846443e-03 4.41451187253451977e-03 9.56795826576277127e-04 -9.24536558699718216e-04 8.93293404755424463e-04 0.00000000000000000e+00 -1.18487808854848139e-19 0.00000000000000000e+00 0.00000000000000000e+00 -1.21585529339919570e-19 0.00000000000000000e+00 0.00000000000000000e+00 -1.24683249835833000e-19 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -6.00073985187597608e-02 5.79048239476312038e-02 0.00000000000000000e+00 0.00000000000000000e+00 1.42224453327682221e-06 1.10902203501515393e-06 0.00000000000000000e+00 0.00000000000000000e+00 -4.88154431646302887e-07 -3.80566800230264436e-07 0.00000000000000000e+00 0.00000000000000000e+00 +end diff --git a/tests_pytest/fixtures/nep_spin3/spin3_o3c3_uniform_oracle.txt b/tests_pytest/fixtures/nep_spin3/spin3_o3c3_uniform_oracle.txt new file mode 100644 index 000000000..1c795ca0e --- /dev/null +++ b/tests_pytest/fixtures/nep_spin3/spin3_o3c3_uniform_oracle.txt @@ -0,0 +1,100 @@ +spin3_oc_oracle_v1 +model_sha256 e5df123b708ee57af52d0a442c433dbc2418ff37f552a9e1b987f869d077c974 +descriptor_dim 121 +spin_descriptor_dim 91 +case zero 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.39999999999999991e+00 1.30000000000000004e+00 8.00000000000000044e-01 6.99999999999999956e-01 2.60000000000000009e+00 1.39999999999999991e+00 1.30000000000000004e+00 5.00000000000000000e-01 2.70000000000000018e+00 3.10000000000000009e+00 2.79999999999999982e+00 2.20000000000000018e+00 +spins 15 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +potential 5 -2.52950417458253085e-01 1.90815041979876143e-01 -2.54141281242850903e-01 1.99907373114162568e-01 -2.53346366808555046e-01 +forces 15 -5.80654546786871402e-03 5.24512572215743347e-03 -1.58117203301252527e-03 7.13166325730548584e-03 1.11158436996078771e-02 -7.01892610514386235e-03 -3.36787857298294921e-03 -2.15004451935478895e-02 6.61307498132944374e-04 -1.55630467286375137e-03 1.59988057999278580e-02 4.30383056902149553e-03 3.59906545640993093e-03 -1.08593300281452712e-02 3.63496007100194739e-03 +virial 45 1.14596450552493512e-02 1.72724690549200927e-03 -2.01629110558683563e-03 5.31351130414067568e-04 -1.05513152451633071e-03 -3.04793533758187423e-03 -7.02355972822654240e-04 -1.60704854960862340e-03 2.42257763727005051e-03 2.75110382885893241e-03 -5.78007879837330986e-04 -4.18743846069741243e-03 1.17523626888569634e-03 6.37081903846917208e-03 -1.99489406889532227e-04 -4.21333793383448386e-03 9.63507270923353795e-05 1.34484111587190834e-02 -4.38134906223314885e-04 1.76594473021381669e-02 5.80046038476074617e-03 1.47850843288538179e-02 -3.12628038153725321e-02 6.98191525227907523e-03 4.38152042055272271e-03 9.72369170918079527e-03 -8.09169364356333333e-03 -3.74651916540500200e-03 -4.80411309068382291e-03 -4.26679589553831569e-03 -4.00346806190364415e-03 -1.62735147164174317e-02 2.66284710413518385e-03 -3.14422524445832300e-03 7.13675272866217780e-04 1.09964149203871445e-02 8.05974337624431637e-03 -9.99720981872034668e-03 3.56974160023106838e-03 -8.48084024786125920e-03 -1.63915251325825739e-02 -3.05391060318054063e-03 2.57807525373199981e-03 -5.58324215076842160e-03 -5.42893779999211335e-03 +mforces 15 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 +tau 15 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +descriptor 605 -2.95852875471916514e-02 6.62278785116065388e-02 -1.77860247854570941e-01 8.56686905962296824e-02 9.49387120620008018e-02 6.89802122490604935e-03 1.68308463394451998e-03 1.74696243553959137e-02 4.52728466232553417e-03 2.29009323905209842e-03 1.28168880344458943e-02 4.44880698551725507e-03 1.40316780373737279e-02 8.76813338115921791e-03 5.20333635639927622e-04 1.09918770242889083e-02 5.27944896542663009e-03 3.76073196261466972e-02 1.14284211413125426e-02 3.76297635364469156e-03 1.08886291401447139e-02 6.73700652926739144e-03 6.82462353954013529e-02 1.47463123481096983e-02 8.35673979775350233e-03 -3.31519548167820714e-04 -5.47652627604176806e-05 3.81299456203965646e-04 2.47419447134496391e-04 -9.27255616380097709e-07 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 8.39226065640130275e-02 1.24212954841887588e-01 -3.39675425477692638e-01 -1.40922116636092554e-01 -4.79561425211357389e-02 2.97785011176694833e-03 2.48899675067480773e-04 3.65487302250709070e-03 1.95522878862403743e-03 1.72150946836502790e-02 6.40726686741707307e-03 2.92243591409527552e-04 2.00881604264009205e-03 3.68468488635544838e-03 1.20520607651244047e-02 1.07719065283846914e-02 4.59797367976337676e-04 4.02459152684220018e-03 4.68318602106494904e-03 2.16006271713723094e-02 1.54267088951266975e-02 4.90613288367886197e-04 1.64411943151868828e-02 5.34869136093873380e-03 2.61971102948285496e-02 1.80542312789496080e-04 1.56427536849164419e-06 -7.14504903775395260e-06 -7.33478544956472011e-05 2.80233410216018609e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -8.40148101505814107e-03 1.09788397080829672e-01 -1.87295009926332273e-01 9.77640784063951579e-02 1.91271838820915169e-01 4.86312494915678781e-03 2.48630233835184450e-03 3.97964410316360533e-03 7.65187963904598247e-04 6.17977950888868644e-04 4.93900992045085818e-03 2.77262595799912959e-03 4.93289696534538174e-03 4.15673342202283001e-03 1.20883683449927266e-03 1.51544933818908920e-02 6.52958732926874844e-03 5.29478895530101270e-03 1.22723440717297811e-02 3.85872175047485312e-03 2.91966971230822256e-02 1.11374424432661330e-02 7.46413332148820018e-03 2.11453552323143563e-02 6.48575979620784684e-03 3.16306104822269181e-05 1.23565792159165982e-05 -5.95513042402913458e-05 6.07016452709123461e-05 -1.32977942762762894e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.11766824226630965e-01 1.78683578262941234e-01 -2.74719737185904644e-01 -5.42764058799548588e-02 -7.27292447615405790e-02 9.11860495216435039e-04 3.60222867628374631e-04 5.25638406491033168e-03 3.29040117096438987e-03 1.62760378732194205e-02 1.40805088618920935e-03 3.80176239623153920e-04 4.93923085118498553e-03 4.35448659087122117e-03 1.52185806821395313e-02 3.35639116101485793e-03 5.68849281703369901e-04 2.56899127582959144e-03 4.54660559673856698e-03 1.06898933307214526e-02 7.09975627370698290e-03 1.09640006046401181e-03 1.82161522012522139e-03 5.95148726784023013e-03 1.25229092351887387e-02 9.67494650989552172e-06 3.86459012451216513e-07 -1.20363235749095470e-04 -8.16230236080278600e-05 -5.80542126753471406e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.00591976784135657e-02 7.13296472728405101e-02 -1.57740913807084465e-01 1.17140085215644341e-01 1.07172358941004908e-01 4.00246719129611350e-03 3.64444051214392068e-03 6.71349187378357352e-03 1.68336250473480678e-03 5.30108146587858985e-04 6.36083269455531286e-03 6.47174904494500925e-03 8.93140053270553326e-03 5.32991389313869704e-03 1.38397660256752938e-03 7.82000270645564176e-03 8.97657496313615348e-03 9.13852222576268074e-03 1.00520784637559736e-02 2.43439970993725207e-03 8.13096108244065231e-03 1.03319112281820800e-02 9.11913919722230452e-03 1.33433766811484056e-02 3.14373652440828140e-03 -1.56128025883313539e-04 -1.60101720362577834e-04 -2.39753364244759971e-04 -7.27929134703983932e-05 1.10970076369464585e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +end +case collinear 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.39999999999999991e+00 1.30000000000000004e+00 8.00000000000000044e-01 6.99999999999999956e-01 2.60000000000000009e+00 1.39999999999999991e+00 1.30000000000000004e+00 5.00000000000000000e-01 2.70000000000000018e+00 3.10000000000000009e+00 2.79999999999999982e+00 2.20000000000000018e+00 +spins 15 0.00000000000000000e+00 0.00000000000000000e+00 8.00000000000000044e-01 0.00000000000000000e+00 0.00000000000000000e+00 -5.99999999999999978e-01 0.00000000000000000e+00 0.00000000000000000e+00 1.10000000000000009e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.99999999999999989e-01 0.00000000000000000e+00 0.00000000000000000e+00 5.00000000000000000e-01 +potential 5 -2.59082400971838989e-01 1.90815041979876143e-01 -2.48399722830992153e-01 1.99907373114162568e-01 -2.55544463173393743e-01 +forces 15 -6.01918212318191485e-03 -1.63367819374724450e-02 8.60018701893248451e-03 1.94697390942628439e-02 1.73447371839132655e-02 -1.22293601522501204e-02 2.21797381607991041e-02 2.37727979043308307e-04 7.38260885482929733e-03 -4.07330655297311224e-03 1.94626679279096687e-02 8.05284426482694507e-03 -3.15569885789069235e-02 -2.07083511533937906e-02 -1.18062799863386074e-02 +virial 45 7.29036480328529302e-04 -1.17915439346576636e-02 -8.03097474508945863e-03 -9.67262074542885736e-03 1.51337113178475757e-02 -1.22584923272414537e-02 -7.14376534228842487e-03 -7.85494087388861634e-04 -2.26211178708755206e-03 1.46910456492263929e-02 4.48412322114217533e-03 -1.15577722898395664e-02 4.02954868182349955e-03 -5.10805790082426159e-05 2.37445834765727696e-03 -8.58263762107895276e-03 -4.82600872048168615e-03 1.57401446775204228e-02 -2.69171712001459590e-02 9.74087314053431741e-03 -2.32132342846486789e-03 6.65046956504909692e-03 -1.54982534895708578e-02 2.71516808602898212e-03 -6.26883375105569910e-03 1.21378382212416584e-02 -1.19035493295558594e-02 -4.83237537256173307e-03 -2.39576127674920791e-03 -3.08508867436189764e-03 -6.78699848257822546e-04 -2.20282618172153652e-02 -2.33280927145735131e-03 -6.88912486203893670e-03 5.78574154850699466e-03 1.64269239216394830e-02 -3.05584902547154473e-02 -1.34751145302581116e-02 -1.67180624237061454e-02 -1.37661210331744086e-02 -1.89786955504735108e-02 -7.63268482075858245e-03 -1.09306984128135186e-02 -7.44941911366956040e-03 -1.30801926435352711e-02 +mforces 15 1.24478370134919320e-04 -1.63762109030766850e-02 1.34122242152172472e-02 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -3.52733172044778810e-03 -1.08411427478641697e-02 7.58739882936699389e-03 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -2.49965401256534159e-03 9.75683262527291006e-04 9.47452356512817201e-03 +tau 15 1.31009687224613487e-02 9.95826961079354639e-05 -0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.19252570226505879e-02 -3.88006489249256717e-03 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.87841631263645503e-04 -1.24982700628267079e-03 0.00000000000000000e+00 +descriptor 605 -2.95852875471916514e-02 6.62278785116065388e-02 -1.77860247854570941e-01 8.56686905962296824e-02 9.49387120620008018e-02 6.89802122490604935e-03 1.68308463394451998e-03 1.74696243553959137e-02 4.52728466232553417e-03 2.29009323905209842e-03 1.28168880344458943e-02 4.44880698551725507e-03 1.40316780373737279e-02 8.76813338115921791e-03 5.20333635639927622e-04 1.09918770242889083e-02 5.27944896542663009e-03 3.76073196261466972e-02 1.14284211413125426e-02 3.76297635364469156e-03 1.08886291401447139e-02 6.73700652926739144e-03 6.82462353954013529e-02 1.47463123481096983e-02 8.35673979775350233e-03 -3.31519548167820714e-04 -5.47652627604176806e-05 3.81299456203965646e-04 2.47419447134496391e-04 -9.27255616380097709e-07 4.80000000000000093e-01 2.23391710731553367e-01 2.42990757037648442e-01 -3.69663853763944963e-02 3.40659970403056789e-01 6.06505787335070087e-02 -7.32060375454880591e-02 -5.86638627564601417e-02 -2.84405149794201423e-02 1.16995176222859411e-02 -6.91733096158779620e-02 -6.85787274041917000e-02 1.32947810065199221e-02 2.34865311783391456e-01 4.17895391852443968e-02 -5.04102334490449389e-02 1.16669355188289567e-01 1.36694042831096374e-01 3.13308229039102864e-03 1.01699463617742798e-02 1.01770675286449730e-02 5.37793726453641117e-04 1.23242966816356631e-01 4.38230455651164585e-02 4.46319901354534296e-03 7.00852565089339768e-02 2.94885926612698419e-02 2.65528847045423417e-03 9.56708784627848252e-02 3.74616995029769572e-03 3.54896718042261011e-03 1.23882377493467366e-01 2.37432659032039764e-02 4.31526831811894843e-03 9.10011359103390094e-02 3.34818678709813897e-02 -1.25878186315247949e-02 3.01428484272395492e-02 -3.23689309237187644e-03 3.18246816421184934e-03 -6.11391091023596144e-03 6.13295863749013168e-02 -1.50234158803837312e-03 7.36959854018239130e-02 -1.25787069421829153e-02 -8.88470531322779105e-04 2.33994956219251045e-03 4.39260874994509398e-03 -5.67342897365595220e-03 8.80495268331667365e-03 -6.14090276450624927e-03 4.08447685133415592e-04 5.35054268113217130e-03 -2.77912858682167994e-02 -3.51792816503194820e-03 -2.95149560568143572e-02 9.75548307210392452e-04 4.91963750926786999e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 6.70143251329559986e-01 4.87113347312835065e-01 -9.78601647866354230e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 4.05701623408589302e-04 2.72299317162012083e-04 -9.76481387726612878e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -5.46128882014869534e-05 -3.89705154790289768e-05 9.90755955758876959e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 8.39226065640130275e-02 1.24212954841887588e-01 -3.39675425477692638e-01 -1.40922116636092554e-01 -4.79561425211357389e-02 2.97785011176694833e-03 2.48899675067480773e-04 3.65487302250709070e-03 1.95522878862403743e-03 1.72150946836502790e-02 6.40726686741707307e-03 2.92243591409527552e-04 2.00881604264009205e-03 3.68468488635544838e-03 1.20520607651244047e-02 1.07719065283846914e-02 4.59797367976337676e-04 4.02459152684220018e-03 4.68318602106494904e-03 2.16006271713723094e-02 1.54267088951266975e-02 4.90613288367886197e-04 1.64411943151868828e-02 5.34869136093873380e-03 2.61971102948285496e-02 1.80542312789496080e-04 1.56427536849164419e-06 -7.14504903775395260e-06 -7.33478544956472011e-05 2.80233410216018609e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -8.40148101505814107e-03 1.09788397080829672e-01 -1.87295009926332273e-01 9.77640784063951579e-02 1.91271838820915169e-01 4.86312494915678781e-03 2.48630233835184450e-03 3.97964410316360533e-03 7.65187963904598247e-04 6.17977950888868644e-04 4.93900992045085818e-03 2.77262595799912959e-03 4.93289696534538174e-03 4.15673342202283001e-03 1.20883683449927266e-03 1.51544933818908920e-02 6.52958732926874844e-03 5.29478895530101270e-03 1.22723440717297811e-02 3.85872175047485312e-03 2.91966971230822256e-02 1.11374424432661330e-02 7.46413332148820018e-03 2.11453552323143563e-02 6.48575979620784684e-03 3.16306104822269181e-05 1.23565792159165982e-05 -5.95513042402913458e-05 6.07016452709123461e-05 -1.32977942762762894e-05 9.07500000000000195e-01 2.90208756328622475e-01 2.95648414886552524e-01 -6.46482531870966326e-02 1.45048119316093294e-01 2.53450441073228665e-02 -3.42678911426203547e-02 -7.98119389901828652e-02 -7.31773151561311286e-02 1.73872150744368847e-02 -6.95527425754443179e-02 -4.98767306064767761e-03 2.68695796862399063e-02 1.89066799645824651e-01 3.30165036279876437e-02 -4.46133241015000473e-02 1.04144974376589941e-01 1.07032530568556106e-01 5.06834326991209474e-03 3.96383588001426260e-03 1.59163054608298766e-04 1.30294413619233054e-06 9.39499400766307668e-02 7.37707817552423761e-02 2.82028696379884973e-03 5.07858690946173114e-02 3.78129552236374372e-02 1.44204331528558329e-03 5.69540713085685407e-02 2.30854398818052982e-02 9.11222627719025791e-04 6.85242021225172526e-02 1.20721426632423110e-02 3.53262949809749621e-03 9.36278478024271943e-02 4.39745111116738377e-02 -1.22827059468763235e-02 4.20321042457212218e-02 -8.55845522007171386e-03 3.13496252740555958e-03 5.20889373137803369e-02 1.06250964973574141e-01 -2.03882532062055581e-02 1.11792230179689658e-01 -2.50277361285277875e-02 4.14240941946349313e-03 3.84482303713856929e-02 6.03687401511910568e-02 -5.74670486382881929e-03 6.12193535495498889e-02 -1.13519759544247582e-02 7.06211022770918389e-04 1.58978176940474079e-02 1.00015673255530301e-02 5.11396135041690750e-03 2.50620097232417266e-03 1.86703316148207699e-03 -1.54019958766683568e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 8.28056210072157461e-01 7.56921098919119850e-01 -1.70478783324804428e-01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.49530999878459200e-05 1.35397274973147314e-05 -5.89059028118039153e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.26937619067442497e-05 -1.58673745630459668e-05 4.20093311152748577e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.11766824226630965e-01 1.78683578262941234e-01 -2.74719737185904644e-01 -5.42764058799548588e-02 -7.27292447615405790e-02 9.11860495216435039e-04 3.60222867628374631e-04 5.25638406491033168e-03 3.29040117096438987e-03 1.62760378732194205e-02 1.40805088618920935e-03 3.80176239623153920e-04 4.93923085118498553e-03 4.35448659087122117e-03 1.52185806821395313e-02 3.35639116101485793e-03 5.68849281703369901e-04 2.56899127582959144e-03 4.54660559673856698e-03 1.06898933307214526e-02 7.09975627370698290e-03 1.09640006046401181e-03 1.82161522012522139e-03 5.95148726784023013e-03 1.25229092351887387e-02 9.67494650989552172e-06 3.86459012451216513e-07 -1.20363235749095470e-04 -8.16230236080278600e-05 -5.80542126753471406e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.00591976784135657e-02 7.13296472728405101e-02 -1.57740913807084465e-01 1.17140085215644341e-01 1.07172358941004908e-01 4.00246719129611350e-03 3.64444051214392068e-03 6.71349187378357352e-03 1.68336250473480678e-03 5.30108146587858985e-04 6.36083269455531286e-03 6.47174904494500925e-03 8.93140053270553326e-03 5.32991389313869704e-03 1.38397660256752938e-03 7.82000270645564176e-03 8.97657496313615348e-03 9.13852222576268074e-03 1.00520784637559736e-02 2.43439970993725207e-03 8.13096108244065231e-03 1.03319112281820800e-02 9.11913919722230452e-03 1.33433766811484056e-02 3.14373652440828140e-03 -1.56128025883313539e-04 -1.60101720362577834e-04 -2.39753364244759971e-04 -7.27929134703983932e-05 1.10970076369464585e-05 1.87500000000000000e-01 3.09265051871420310e-02 1.47721727561798050e-01 -5.44044155885520381e-02 -1.09325078697414188e-02 1.03706532305929966e-01 -1.11122512295827078e-01 -1.63225387542137272e-03 -1.90285224464045860e-02 1.09828242622702372e-02 4.97647076721685036e-04 -6.02895447967638064e-03 8.54318555568653326e-03 -2.94426982328782356e-03 2.79125028440513033e-02 -2.98905491934977861e-02 5.72432583981067906e-03 1.29329858186517571e-01 1.73726508950092021e-02 1.15240870211705715e-03 2.08520233535034842e-02 2.77753222952729049e-03 3.91689586988171624e-03 8.48003909935093197e-02 1.41522958608049764e-02 2.80545751368467284e-03 5.78697891595255226e-02 9.16657775761629823e-03 2.60594087211211750e-03 4.47322172528318018e-02 1.03125513095134146e-02 -5.50391879552229236e-04 2.46811984258870770e-02 9.64029044875978035e-03 6.59478177072250109e-04 2.08997572016350174e-03 -3.85178750155466788e-04 1.18887392264548815e-02 -4.18101744267778026e-03 2.73678463123645061e-03 1.01187763457376420e-03 5.91920055131356197e-03 -2.57370997521666348e-03 2.64580453487881090e-02 -9.91811476572143462e-03 2.39657597348903739e-03 7.87714748800721529e-04 4.26856762972697371e-03 -1.96567602928153550e-03 1.87789594928634423e-02 -7.88961704422327589e-03 2.13477731384450033e-03 4.03650211362424117e-04 1.61061060956641617e-03 -9.58683616243363409e-04 6.53667738853745423e-03 -4.35685952854067415e-03 1.53799348822099280e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.34263709295135394e-02 2.31412137610664398e-01 -1.06948582561993188e-01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -8.71735249074043808e-05 -5.40063466210023043e-05 1.56917085028294839e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.75078991838333930e-05 1.16314078720521975e-05 -1.67957507874852598e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +end +case noncollinear 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.39999999999999991e+00 1.30000000000000004e+00 8.00000000000000044e-01 6.99999999999999956e-01 2.60000000000000009e+00 1.39999999999999991e+00 1.30000000000000004e+00 5.00000000000000000e-01 2.70000000000000018e+00 3.10000000000000009e+00 2.79999999999999982e+00 2.20000000000000018e+00 +spins 15 8.00000000000000044e-01 1.00000000000000006e-01 2.00000000000000011e-01 2.00000000000000011e-01 9.00000000000000022e-01 -1.00000000000000006e-01 -2.99999999999999989e-01 4.00000000000000022e-01 6.99999999999999956e-01 5.00000000000000000e-01 -2.00000000000000011e-01 5.99999999999999978e-01 -4.00000000000000022e-01 -2.99999999999999989e-01 8.00000000000000044e-01 +potential 5 -2.28124770632560814e-01 1.90815041979876143e-01 -2.38169761645910472e-01 1.99907373114162568e-01 -2.39964210865800387e-01 +forces 15 2.53324043515348440e-03 -7.13790280919783006e-03 -8.99757903550551380e-03 1.26172372199196397e-02 5.01861274014984288e-03 -1.43331766844381273e-02 -6.55941871271734436e-03 6.36480353837182156e-03 4.24191342996662214e-03 7.97409547462370021e-03 1.30430993209420323e-02 2.05215887153706797e-02 -1.65651544169794843e-02 -1.72886127902658546e-02 -1.43274642539366250e-03 +virial 45 6.48055312113381306e-03 -6.20444330973332972e-03 -4.02560046261155480e-03 -1.06108697627649799e-02 9.10687839074760669e-03 -1.01173242750629624e-02 -5.66275991968252790e-03 -9.20796334212132779e-04 -3.70867991808660358e-04 1.24697561073022177e-02 -4.66332102640241910e-03 -9.46274259410926147e-03 -5.94215148229503692e-05 1.43818532984681564e-02 9.93892532660199668e-03 -5.56937003149867577e-03 5.71303191729549773e-03 2.02335186853102242e-02 -1.46275739557324667e-02 1.12544084730804884e-02 1.69965430576015687e-03 3.45457125961849514e-03 -1.38030537409587380e-02 8.53586206928753401e-03 -3.47077253906096297e-03 1.31251413231365174e-02 -8.87534264725321938e-03 -3.15592682243131303e-03 -1.14201804325285722e-02 2.03148057066377882e-04 -1.38423526810112184e-02 -1.39566479809444428e-02 -9.64501544382047847e-03 1.07983127765360724e-02 -5.81574632669243623e-03 3.71529523950019508e-02 -1.39294463618393448e-02 -1.62430039929936237e-02 -6.60577157202456126e-03 -1.94561517632661253e-02 -2.16808131668222819e-02 -9.06507711778486644e-03 -7.56484820887985774e-03 -9.13249821492626533e-03 -1.04094546267182557e-02 +mforces 15 -2.53692800637252622e-02 -2.25225242656808995e-02 -2.22979564473707245e-02 -0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -1.02913498103237959e-04 -2.29149481280099473e-02 -2.18976044103608401e-02 -0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 -1.12761587319857356e-02 3.92607516449621028e-03 -1.97561742202939580e-02 +tau 15 2.27470920839910763e-03 1.27645091451515265e-02 -1.54810914061721937e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 7.28142192546262640e-03 -6.64132077178051800e-03 6.91564983764427887e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 2.78599213449121910e-03 -1.69233966737061745e-02 -4.95327768539420479e-03 +descriptor 605 -2.95852875471916514e-02 6.62278785116065388e-02 -1.77860247854570941e-01 8.56686905962296824e-02 9.49387120620008018e-02 6.89802122490604935e-03 1.68308463394451998e-03 1.74696243553959137e-02 4.52728466232553417e-03 2.29009323905209842e-03 1.28168880344458943e-02 4.44880698551725507e-03 1.40316780373737279e-02 8.76813338115921791e-03 5.20333635639927622e-04 1.09918770242889083e-02 5.27944896542663009e-03 3.76073196261466972e-02 1.14284211413125426e-02 3.76297635364469156e-03 1.08886291401447139e-02 6.73700652926739144e-03 6.82462353954013529e-02 1.47463123481096983e-02 8.35673979775350233e-03 -3.31519548167820714e-04 -5.47652627604176806e-05 3.81299456203965646e-04 2.47419447134496391e-04 -9.27255616380097709e-07 5.17500000000000071e-01 -2.14735916374606400e-02 -1.57562970243320416e-01 -2.83786770788579902e-03 2.30780963309825005e-01 -1.54856977079819214e-01 -1.27607317292643824e-01 1.30684204521144213e-02 -4.90244676218137901e-02 -6.67395409944588573e-03 -4.21952801203660174e-02 -4.38939849938116897e-02 -1.84170869243749057e-02 -2.58069161274542252e-03 -6.33578321657783800e-02 -1.02670524965282998e-02 8.77988582619579905e-02 6.45844305141472508e-02 1.19807534743633318e-02 3.63060114648282792e-02 3.71653030155463804e-02 2.21875950200932197e-03 5.28484481280746821e-02 6.07661997558224809e-02 1.01451412505567419e-02 4.75811222251294810e-02 6.71613023371942924e-02 3.79351522477349183e-03 5.53721511583721918e-02 8.61671141643646221e-02 4.82600413373348094e-03 -5.41252097926535770e-03 1.69679890199173275e-02 -1.03917572336715029e-03 8.01023443749997351e-04 1.66070032375949662e-03 -1.89669795295554296e-05 2.05338894660337112e-02 2.00861671087310427e-03 5.42630603060541283e-04 -1.50281198197602919e-05 4.26630339433670212e-03 1.27463836436955257e-04 2.28111534432868628e-02 -1.29497973219799378e-03 -5.49858539450581501e-04 2.86506921334779910e-05 2.63598908757463465e-04 -1.11068910542844006e-04 2.06344433463649581e-03 -1.39689316911415905e-03 -3.49346219190238387e-04 2.85832001698930415e-05 -1.96436975126150363e-03 -6.40157637690343486e-05 -1.01213922038965801e-02 -3.90689101406306854e-04 -2.24571346022129801e-05 2.69158929928854604e-05 2.20447966935061844e-05 1.71150536160113275e-05 3.71756202749949508e-03 2.26002837046679643e-03 1.15873593494991733e-03 -4.60647827235257558e-06 -3.75964145997886231e-06 -2.90296874981064867e-06 -2.84648025104945388e-04 -1.96207744223060538e-04 -1.22837454304948414e-04 -4.66765820509584817e-02 -3.56518860083695377e-01 -3.36604877876354796e-03 -3.34454178312935926e-06 -2.57214142580966369e-06 -1.79126460411776176e-06 -6.08586154771968086e-05 -7.08699575367891070e-06 4.58719202654218653e-05 9.45646555234612878e-07 7.39227927032147475e-07 5.30613384524384550e-07 3.38485944949955885e-05 1.72156724199960847e-05 4.98771767353696697e-06 -1.83729520524066773e-07 -5.13135835607022026e-08 8.31015847310005392e-09 3.23713490637090203e-18 5.85700694579015283e-18 1.41872268613859013e-19 8.39226065640130275e-02 1.24212954841887588e-01 -3.39675425477692638e-01 -1.40922116636092554e-01 -4.79561425211357389e-02 2.97785011176694833e-03 2.48899675067480773e-04 3.65487302250709070e-03 1.95522878862403743e-03 1.72150946836502790e-02 6.40726686741707307e-03 2.92243591409527552e-04 2.00881604264009205e-03 3.68468488635544838e-03 1.20520607651244047e-02 1.07719065283846914e-02 4.59797367976337676e-04 4.02459152684220018e-03 4.68318602106494904e-03 2.16006271713723094e-02 1.54267088951266975e-02 4.90613288367886197e-04 1.64411943151868828e-02 5.34869136093873380e-03 2.61971102948285496e-02 1.80542312789496080e-04 1.56427536849164419e-06 -7.14504903775395260e-06 -7.33478544956472011e-05 2.80233410216018609e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -8.40148101505814107e-03 1.09788397080829672e-01 -1.87295009926332273e-01 9.77640784063951579e-02 1.91271838820915169e-01 4.86312494915678781e-03 2.48630233835184450e-03 3.97964410316360533e-03 7.65187963904598247e-04 6.17977950888868644e-04 4.93900992045085818e-03 2.77262595799912959e-03 4.93289696534538174e-03 4.15673342202283001e-03 1.20883683449927266e-03 1.51544933818908920e-02 6.52958732926874844e-03 5.29478895530101270e-03 1.22723440717297811e-02 3.85872175047485312e-03 2.91966971230822256e-02 1.11374424432661330e-02 7.46413332148820018e-03 2.11453552323143563e-02 6.48575979620784684e-03 3.16306104822269181e-05 1.23565792159165982e-05 -5.95513042402913458e-05 6.07016452709123461e-05 -1.32977942762762894e-05 5.54999999999999938e-01 -3.81905297272675873e-02 -3.66203123106284903e-03 -2.69131441644936339e-02 9.80146552995194986e-02 -4.68605129052662023e-02 -6.84476527126860745e-02 3.76196042113289826e-04 -3.32720862767793418e-02 1.07079483029806424e-02 3.45825764038205086e-02 -1.64518729636016700e-02 1.13244240274381503e-02 -3.53193815214531857e-03 2.45357992001830096e-02 -1.86015242341797740e-02 4.41258883748872691e-02 3.93250443899177682e-02 4.37572070952345869e-03 2.05865216223070110e-04 1.36126211969476085e-03 5.24960208952220627e-05 3.84367400440093834e-02 5.17171172057564674e-02 4.91962072950928673e-03 3.82314705077718073e-02 3.38473079737949614e-02 3.09161799124711310e-03 5.05077912888299216e-02 5.33889338935758656e-02 4.08628219362796013e-03 -5.89621273498283291e-03 1.91118090407865551e-02 2.23740928769515252e-03 9.45030233379795005e-04 1.63998600935380090e-03 -1.89042137915900024e-04 9.77535194893970789e-03 -3.32901217665321171e-03 1.59391786682152648e-03 1.60615203164786902e-03 -1.45891173144484004e-03 2.01370986694411440e-03 -1.01438146276168501e-02 3.63667650953925685e-03 -3.74308978336137534e-04 1.24159411636417909e-03 6.88954666778120541e-04 5.53850041912822000e-04 -4.05035457655913891e-03 1.52888711871679208e-03 -9.47901179960829892e-05 4.98904063545836229e-04 1.89326967675602009e-03 -6.90904207878074018e-04 2.51025676460949919e-03 -7.67879044123683939e-04 1.20322824515168615e-04 8.34501631411409728e-06 6.71292617463090402e-06 5.06123213243544949e-06 -1.40247132114429754e-03 -8.26532259305907957e-04 -3.98051121409732488e-04 -6.16836431461717534e-06 -4.96670692484476411e-06 -3.75111594941622745e-06 1.47174993965034761e-03 9.02741048091982093e-04 4.69982343121027170e-04 -9.03705761571150373e-02 2.74860197349986865e-03 -7.08109124456581390e-02 -1.67538774555006764e-06 -1.32767658447059688e-06 -9.76139761865537637e-07 9.25197953128691300e-06 8.21847416432776284e-06 -1.12785504574138942e-06 1.51656322476950933e-06 1.20190001414087167e-06 8.83885295704733888e-07 3.81036214332825827e-06 9.08392501164289839e-07 -1.72457344558318758e-06 -1.06427086331895198e-09 -3.22778890579934894e-10 -3.08088223662678987e-12 4.97747971629476339e-19 8.59644563582407625e-19 2.01889390621557149e-20 1.11766824226630965e-01 1.78683578262941234e-01 -2.74719737185904644e-01 -5.42764058799548588e-02 -7.27292447615405790e-02 9.11860495216435039e-04 3.60222867628374631e-04 5.25638406491033168e-03 3.29040117096438987e-03 1.62760378732194205e-02 1.40805088618920935e-03 3.80176239623153920e-04 4.93923085118498553e-03 4.35448659087122117e-03 1.52185806821395313e-02 3.35639116101485793e-03 5.68849281703369901e-04 2.56899127582959144e-03 4.54660559673856698e-03 1.06898933307214526e-02 7.09975627370698290e-03 1.09640006046401181e-03 1.82161522012522139e-03 5.95148726784023013e-03 1.25229092351887387e-02 9.67494650989552172e-06 3.86459012451216513e-07 -1.20363235749095470e-04 -8.16230236080278600e-05 -5.80542126753471406e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.00591976784135657e-02 7.13296472728405101e-02 -1.57740913807084465e-01 1.17140085215644341e-01 1.07172358941004908e-01 4.00246719129611350e-03 3.64444051214392068e-03 6.71349187378357352e-03 1.68336250473480678e-03 5.30108146587858985e-04 6.36083269455531286e-03 6.47174904494500925e-03 8.93140053270553326e-03 5.32991389313869704e-03 1.38397660256752938e-03 7.82000270645564176e-03 8.97657496313615348e-03 9.13852222576268074e-03 1.00520784637559736e-02 2.43439970993725207e-03 8.13096108244065231e-03 1.03319112281820800e-02 9.11913919722230452e-03 1.33433766811484056e-02 3.14373652440828140e-03 -1.56128025883313539e-04 -1.60101720362577834e-04 -2.39753364244759971e-04 -7.27929134703983932e-05 1.10970076369464585e-05 6.67500000000000093e-01 1.31592917056219758e-02 9.27613620230827718e-02 -2.79526699421046264e-02 -6.18087431030642648e-02 -8.51479121452627524e-02 -9.88432488615374194e-02 -1.21692022008737678e-02 -5.49887860449946933e-02 1.75619218180579524e-02 8.65895817906016385e-03 -9.02080255188325054e-03 3.24579805235427135e-02 -1.47296880044508836e-02 -5.56123326254052107e-03 -2.33631971627110413e-02 3.48569383777921123e-03 2.08875641759931861e-02 1.00808543132236191e-02 1.21896775310007975e-03 8.10160422294330801e-03 2.66532133732734228e-03 1.06044471401113647e-03 1.52741334789389411e-02 3.31723025482632888e-03 3.41736546786991372e-03 2.51064582939111158e-02 7.61968580873552750e-03 3.67126169019563707e-03 3.75124125475985379e-02 6.40771029033069053e-03 -1.67008935071498617e-03 -8.84244428804957169e-03 1.71853301940379948e-03 1.36760390227835880e-03 4.02447922583524988e-03 -1.02994952065615524e-04 1.73582987610229680e-02 -3.30697148021273602e-03 1.96246352509556318e-03 -1.11612256820426705e-03 -2.02547868158953464e-03 -5.43119608924456866e-04 -2.74602023352289292e-03 -1.16384540236891417e-03 -6.56445023615084789e-04 -7.86226416279122938e-04 -1.69039714692441096e-03 -1.28027744416059569e-04 -3.55523356523278905e-03 2.53167601487886622e-04 -8.65219013499711844e-04 -2.47005386855223322e-04 -1.00586357079697508e-03 4.48632384089560419e-04 -4.04557799278698789e-03 2.12719036868207808e-03 -1.03625093226136517e-03 -2.67452205846324586e-06 -2.10304018744044295e-06 -1.52471087303253299e-06 -2.01696929746177176e-03 -1.24558750773670819e-03 -6.56263617393820233e-04 1.92185497720717687e-06 1.51060776769793916e-06 1.09460409682679342e-06 1.27362264127459839e-03 7.85610420409961680e-04 4.13119245834286020e-04 4.13334443753480552e-02 2.61585987387966790e-01 -7.30803458366383468e-02 2.30134012501053038e-06 1.82057040599402989e-06 1.33451193724063665e-06 -1.53414742461579771e-05 -8.37404099440177996e-06 4.43171349531862224e-06 -1.61017953434250512e-06 -1.27358204304875114e-06 -9.33400076179230787e-07 1.16748561947446266e-05 6.82545183671949298e-06 -2.72865373694614778e-06 3.06373703084182452e-10 7.73792688104515173e-11 -1.60147048260810273e-11 5.38469078115848526e-20 9.37317611440536090e-20 2.21550680010283341e-21 +end +case chiral_soc 5 +types Fe Ge Fe Ge Fe +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 15 1.00000000000000000e+00 1.00000000000000000e+00 1.00000000000000000e+00 2.50000000000000000e+00 1.10000000000000009e+00 1.10000000000000009e+00 4.99999999999999944e-01 2.70000000000000018e+00 1.59999999999999987e+00 1.60000000000000009e+00 6.99999999999999956e-01 2.60000000000000009e+00 3.00000000000000000e+00 3.09999999999999964e+00 2.30000000000000027e+00 +spins 15 1.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.00000000000000000e+00 5.99999999999999978e-01 -2.00000000000000011e-01 6.99999999999999956e-01 -4.00000000000000022e-01 8.00000000000000044e-01 2.99999999999999989e-01 +potential 5 -2.24024773315132764e-01 2.04243155506178692e-01 -2.35245301586490929e-01 2.05724475837031240e-01 -2.44687174847666195e-01 +forces 15 1.69400908876271832e-03 -9.22167026275781676e-04 -1.54541776873150256e-02 2.16756659402500725e-02 1.90143653140429636e-02 -2.47434235136005445e-02 5.62058582221029116e-03 2.13618812951975323e-05 8.12551746380985561e-03 -3.86011717941742508e-03 1.30288249926011415e-02 4.41198351869289962e-02 -2.51301436718056673e-02 -3.11423851616635175e-02 -1.20477514498232852e-02 +virial 45 4.22230565113896825e-03 -2.20488601188799059e-02 -7.48368778287752251e-03 -2.04482367658954355e-02 2.68799556976584506e-03 -7.36469077798266713e-03 -7.89693459352634394e-03 -4.52240622737878906e-03 -4.12454264419159344e-04 5.25050215261668902e-03 3.79657913001631153e-03 -1.62876403367162824e-02 1.24120323870189481e-03 5.01930279844080285e-03 -2.90746382101795316e-03 -1.53801164925935225e-02 -3.89208431278084167e-03 2.37696065594444755e-02 -2.45485921228922599e-02 2.26126913063997050e-02 -2.41955137778096258e-03 1.67246146365207619e-02 -1.37669080027051915e-02 1.25370363759342105e-02 -4.83982538614671776e-03 1.32258536894727906e-02 -3.38790016067245202e-03 9.45920967984523707e-03 -1.48759588309761129e-03 -7.87746560985630104e-04 -6.35598313603417085e-03 -1.08518656609142318e-02 -1.21739177507057192e-02 5.54211597358798130e-03 -4.65197073935685705e-03 4.98162515645756976e-02 -1.72565770127004608e-02 -2.88294227317880056e-02 -1.18228697314345186e-02 -3.10543020384772064e-02 -5.04584293122548044e-02 -1.72881552898187622e-02 -1.07306956743854591e-02 -1.78841194717756433e-02 -1.24548761576865688e-02 +mforces 15 -2.50936100042227703e-02 -1.81399459336387958e-02 -1.89924180003054298e-02 0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -9.94960840241587013e-03 -1.67876676572168461e-02 -2.99554328664774529e-02 -0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 -5.22283448702065816e-03 -1.02937651313687838e-02 -1.42785936634094619e-02 +tau 15 0.00000000000000000e+00 1.89924180003054298e-02 -1.81399459336387958e-02 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 1.67876676572168461e-02 -9.94960840241587013e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -8.33474539131693476e-03 -7.27828781146998283e-03 8.29577364216404003e-03 +descriptor 605 -4.07951056317612804e-02 7.25742801603690008e-02 -1.75156846253149368e-01 9.32956828576613217e-02 1.01283242511029770e-01 6.43953155385846437e-03 2.55380070080721191e-03 2.48397675019688541e-02 6.58312850506214894e-03 2.45423136171683690e-03 1.22907571102995154e-02 5.34884320108765417e-03 2.26871486849321222e-02 1.07267652967193931e-02 9.09642212205097464e-04 1.07027090279758832e-02 3.94722518052224337e-03 1.83343662443361567e-02 6.48701044322846660e-03 4.16135781465501453e-03 1.10624852688494171e-02 5.68495912220371487e-03 4.02787113393940702e-02 8.77863404561620916e-03 7.94822152583341338e-03 -3.94772725050928958e-04 -1.20408196828559002e-04 -4.17089920649645757e-04 1.18747200741891446e-04 -8.84747615028152462e-06 7.50000000000000000e-01 -2.14556902652343999e-02 -1.39268721448519706e-01 9.20598250267486325e-03 2.58605783546434764e-01 -2.05840229946555597e-01 -1.42338612316490920e-01 -4.16054024065875844e-03 -2.85493525885909712e-02 -2.75644008137015846e-02 -3.24208305751792353e-02 -1.12467192279823269e-01 -1.42304795586211622e-02 8.45822813714861206e-04 -7.29312394090598920e-02 -2.10117895111599576e-02 6.92111886544511390e-02 4.50512096812540480e-02 1.49789994344082331e-02 7.42332437960805010e-03 2.78854489488704824e-02 5.11485138959131766e-03 5.70836552675593745e-02 5.61800008267136497e-02 1.06692744493349732e-02 4.40351229552131684e-02 7.69258453818591759e-02 5.83991808043590570e-03 5.01519673296543927e-02 1.11243279724248037e-01 6.68466948283487870e-03 -4.22805113313205489e-03 1.45533125788903477e-02 -2.81548251595025237e-03 4.21538461304848380e-04 2.02741327466438980e-03 -3.65184671851602569e-04 2.58691455134894659e-02 2.45415639775914060e-03 1.42882675809785013e-03 3.78634297257842941e-04 3.18424285969439065e-03 3.07554492026259352e-05 7.60047431026659743e-03 -4.82783724019049919e-03 -1.33532520701765828e-03 1.89139097566189671e-04 1.59023178763770018e-03 1.53557335170839847e-05 3.79389028978276968e-03 -2.40931499222704019e-03 -6.66233068948120341e-04 -6.26964102897967771e-05 -5.27014383954356393e-04 -5.08785230137914264e-06 -1.25675835234560513e-03 7.97930104401029568e-04 2.20598654121030092e-04 -2.16062769449400841e-05 -1.57621566647519103e-05 -9.84840555327692444e-06 8.73023763696220700e-03 5.27397107292246464e-03 2.66918905915275624e-03 6.14353467541980417e-06 4.77433432241581775e-06 3.38931416052353117e-06 -8.39458165228349515e-04 -4.66946794024596492e-04 -1.98492420081196455e-04 -6.52035591621685368e-02 -4.21838267494001717e-01 2.77936980830756630e-02 -4.13603671839931111e-06 -3.44603795605926537e-06 -2.74840063598261634e-06 -4.77339000911521365e-05 2.99439915231303285e-05 9.99288634166898117e-05 -2.03092836499216853e-06 -1.57136054004525687e-06 -1.10690779834470859e-06 -1.50934406815300290e-05 -1.14547922198415457e-05 2.38122967194592091e-05 -2.21597805681314926e-07 -5.51104284841413209e-08 1.61049923673682726e-08 8.82450810172041848e-18 1.56864668835927385e-17 3.75294807155029187e-19 5.26064979799123131e-02 2.06969673594376263e-01 -2.71334147679693272e-01 -2.32532745055919129e-02 -1.00415954684414749e-01 3.56949050185662985e-03 1.69104984985856495e-04 4.37896525352369365e-03 6.95282933616987384e-03 1.47563111940506794e-02 7.04980854710581233e-03 5.35380100014887879e-04 3.68503043372081941e-03 7.17931408035873877e-03 9.12828268600088255e-03 9.34133619634763997e-03 9.06071537992835549e-04 5.77727607536480774e-03 9.98924477271939150e-03 1.65774246902786783e-02 1.37070467582236719e-02 1.24955595900824007e-03 1.53904939928255664e-02 1.92837984475114146e-02 2.18301157605374496e-02 2.02944898202574831e-04 3.13244727298141538e-06 6.15335602569868557e-06 -1.83647346061773312e-04 1.43717095127411610e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.65095547741277056e-02 1.14603198343876861e-01 -1.94581455900163097e-01 1.43102654899766119e-01 2.12277263506710917e-01 7.26684974600826008e-03 1.90694689171451979e-03 3.15664709919001195e-03 2.59706252684030069e-04 2.80960741861350583e-04 6.64113377333903042e-03 2.15673494738152869e-03 4.72646526036752355e-03 2.65820866084326380e-03 1.09716143248929062e-03 1.29331642529171252e-02 7.47349824937135285e-03 5.62428639297778751e-03 8.50128608425756646e-03 4.89021597692943389e-03 2.28390239979064519e-02 1.42347057557624616e-02 6.19831696053204685e-03 1.36613618595651243e-02 9.14621490538803164e-03 1.54057025306583447e-05 1.85117379040633898e-05 -9.71169998620503562e-05 -1.50255853039382769e-06 3.00303736163038499e-06 7.50000000000000000e-01 -4.08677088654591097e-02 -5.59774652707008130e-02 -1.60565108893118667e-02 1.02127425924590398e-01 -9.28078892871214006e-03 -8.39375921505726708e-02 -2.72151014836367854e-02 -4.66453736747055731e-02 1.13420963034708520e-02 -2.28507055054729472e-02 -4.39013816240134706e-04 2.43057661130415652e-02 -3.11121047392904429e-02 -5.66017241723322170e-02 -4.59106520507177041e-03 4.97299071169093054e-02 4.76239823775646224e-03 4.25343160987919598e-03 3.36460641571178316e-03 3.60358212874964016e-05 7.42896461006035535e-05 2.92195552859043986e-02 1.38370007989962757e-02 1.04312289721274851e-02 4.27137702238457664e-02 3.02827120668972792e-02 9.42550687491792777e-04 4.68196908830051592e-02 4.95235687693364804e-02 4.81825976530428357e-03 -5.30613282856884534e-03 3.61475239779069377e-03 1.28968094913705766e-03 2.68986740892996311e-03 5.75782321716141431e-03 -7.55909159953750361e-05 1.42314508788481259e-02 -1.15190909740706484e-03 5.38385674480259245e-04 1.65686112955060086e-04 -1.93889783497236401e-03 1.23868616677324595e-03 -9.22771207077002949e-03 2.79327995552959693e-03 -1.03134900770399722e-04 6.97141699368630877e-05 -8.15610412857749973e-04 5.20934798150523128e-04 -3.87982106536207023e-03 1.17416469234976682e-03 -4.33429415728007995e-05 -4.54254528887741577e-05 5.31326701786362572e-04 -3.39284593687703517e-04 2.52636182841427031e-03 -7.64393747709845792e-04 2.82105723473840518e-05 1.16757693467224146e-05 9.27182881774295434e-06 6.83905539861398080e-06 -4.00262031440325444e-03 -2.46615693488557060e-03 -1.29369382298868008e-03 -7.65466110284076352e-06 -6.07218989382390190e-06 -4.47139935490915949e-06 4.36217471617802045e-03 2.71321954002305601e-03 1.44788599009615555e-03 -1.24196427143106455e-01 -1.69553053427195566e-01 -4.84760660576406474e-02 -5.10678472907798203e-06 -4.04452834829411939e-06 -2.97058525097167305e-06 2.60684521752864735e-05 1.83963248600041262e-05 -4.86498030307950190e-06 3.31508159910121587e-06 2.62554133186385523e-06 1.92865715336570283e-06 1.10150926481319303e-06 8.22808461312692532e-08 -1.40656856698995421e-06 4.87608132468467377e-09 1.39600963774754549e-09 -1.90492356570974158e-10 -1.86342926522679581e-18 -3.37343581310686711e-18 -8.18895025847363963e-20 7.40184830267154314e-02 2.17581791952024928e-01 -2.57805720014052886e-01 -1.56276409788698445e-02 -1.17737433564288882e-01 1.37387590451212068e-03 8.22308260248586788e-05 5.41398235453010180e-03 6.89115885896402370e-03 1.69193365385175987e-02 2.83801467097777446e-03 3.87957726586072313e-04 3.73512321262609850e-03 8.52379652940165634e-03 1.04659122009255166e-02 5.65824233258071466e-03 1.05608344790731950e-03 2.92905408454098570e-03 1.13285265545884604e-02 6.39424395974050926e-03 8.82606030464207041e-03 1.75061160442347395e-03 8.38091602710684322e-03 2.01303514067790665e-02 1.61519710301800921e-02 4.91146748176832571e-05 1.56342591975869189e-06 -6.29291828379758861e-05 -1.92750490764715754e-04 -2.97730509545786760e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.75158772103998920e-03 7.86685367335085428e-02 -1.66755997668440042e-01 1.11335738452193009e-01 1.06147865219759621e-01 4.41986258534713024e-03 2.59002163619436723e-03 6.27133566483656368e-03 1.61264145976879351e-03 3.24507099866732209e-04 5.75837348993144850e-03 4.76959704811152560e-03 8.71446617571954019e-03 4.40919240502090151e-03 1.26408170277035343e-03 5.51503800920148234e-03 6.76665074998512601e-03 8.83872094841488612e-03 7.10783384175080104e-03 2.36227081739227938e-03 4.75386570527142494e-03 7.85157969495365628e-03 7.15648134930950332e-03 7.59370579971314560e-03 2.81236969610510921e-03 -1.46578389512628875e-04 -1.06047101915559050e-04 -2.75048005452757074e-04 -5.74356748446849433e-05 6.81766262728661734e-06 6.67500000000000093e-01 -5.49911554869678895e-02 -7.86878930121269193e-02 1.43942186923328806e-02 -6.89570889972512258e-02 -8.06888493168836374e-02 -1.30736632294624538e-01 -1.17279291081278259e-02 -5.74932889262422600e-02 -1.48271372708618301e-02 -1.59363032206865096e-02 -6.23622108039429898e-02 2.89058278382064125e-02 -3.85933210330572374e-02 -8.29794176137787498e-02 -1.30784625223205470e-02 5.78219786147364523e-03 2.24137767389773895e-02 1.43664225653541040e-02 1.59391286835274025e-03 6.54013228950195771e-03 3.77510019004521262e-03 2.10644949583120274e-03 3.42787029748958458e-03 6.71395021966074684e-03 5.21045635428458824e-03 3.22097442610226395e-02 9.53133054894760717e-03 5.46202169498949657e-03 3.68398949129954689e-02 8.64146518873014358e-03 3.92489974360944825e-03 2.45237722895346837e-02 -1.16327467502041907e-03 4.37733033207254700e-03 9.57401838121673364e-03 -8.86022209540072341e-04 2.32000585294878728e-02 -2.45064759745060616e-03 1.61290924523572977e-03 8.13155748564241818e-04 -2.29693621537304564e-03 -4.77517593608773412e-04 -1.31150989892429952e-02 5.37801235174349148e-04 -1.30985614531181432e-03 8.61035769130154326e-04 -7.19912335039735282e-04 -1.05528377738051127e-03 -6.41119861753716280e-03 -1.16829680063461339e-03 -9.08757263672732248e-04 9.27718933011341374e-04 1.46953277603832188e-03 -1.64807852954971840e-03 2.72451406694738637e-03 -3.16658744438344042e-03 -2.65929120779304453e-04 -9.12095524935488836e-06 -7.09420162322366947e-06 -5.04318853171087098e-06 -1.71559212789269009e-03 -1.06744826735068556e-03 -5.70090969406930473e-04 6.51358713482658886e-06 5.06475493504497733e-06 3.59918204211595888e-06 1.42771983616987405e-03 8.89377573870458863e-04 4.76023149039066196e-04 -1.68522354450464429e-01 -2.41574756319723222e-01 4.29703702522897038e-02 -2.65482659308016467e-06 -2.13341588436797504e-06 -1.60626016230024003e-06 -1.74176464816184012e-06 7.25911845152999233e-07 3.30404318814203346e-06 1.83866848541626968e-06 1.47792309546773042e-06 1.11332994625183708e-06 2.40387766655431621e-06 1.25234245210306920e-06 -4.98116749168275617e-07 9.82178071109587620e-11 2.81833623724645458e-11 -1.48042265596458127e-12 -4.68320367395049869e-20 -8.14455819597160305e-20 -1.94797779092072749e-21 +end +case strained 5 +types Fe Ge Fe Ge Fe +cell 9 1.42099999999999991e+01 0.00000000000000000e+00 5.60000000000000012e-02 1.56000000000000000e-01 1.28309999999999995e+01 0.00000000000000000e+00 -8.99999999999999967e-02 1.34999999999999981e-01 1.51200000000000010e+01 +positions 15 1.02099999999999991e+00 9.95999999999999996e-01 1.01200000000000001e+00 2.44679999999999964e+00 1.29030000000000022e+00 8.16000000000000059e-01 7.33299999999999952e-01 2.57880000000000020e+00 1.41399999999999992e+00 1.30929999999999991e+00 5.17800000000000038e-01 2.72680000000000033e+00 3.16689999999999960e+00 2.78339999999999987e+00 2.22999999999999998e+00 +spins 15 8.00000000000000044e-01 1.00000000000000006e-01 2.00000000000000011e-01 2.00000000000000011e-01 9.00000000000000022e-01 -1.00000000000000006e-01 -2.99999999999999989e-01 4.00000000000000022e-01 6.99999999999999956e-01 5.00000000000000000e-01 -2.00000000000000011e-01 5.99999999999999978e-01 -4.00000000000000022e-01 -2.99999999999999989e-01 8.00000000000000044e-01 +potential 5 -2.27804809327155078e-01 1.90662696596788583e-01 -2.37959306341920168e-01 1.99451221902896630e-01 -2.39817367735215947e-01 +forces 15 1.25190778761540868e-03 -6.87163244712705751e-03 -8.34230234088604097e-03 1.39628784583265587e-02 5.14042230595965297e-03 -1.34372134429996317e-02 -4.43447192584646606e-03 6.34463833514740949e-03 4.47416010146974019e-03 8.59209704331565308e-03 1.27572572976328014e-02 2.00518177888420676e-02 -1.93724113634111544e-02 -1.73706854916128028e-02 -2.74646210642613773e-03 +virial 45 6.14374113917907569e-03 -6.52427944632710029e-03 -4.54624692105115146e-03 -1.06779718945533703e-02 8.31186725495671602e-03 -1.02633235118599446e-02 -5.86084674684675486e-03 -1.11938794411376428e-03 -8.58536831820387331e-04 1.49055206707430256e-02 -4.13143034728168448e-03 -9.34164144577005751e-03 4.03561616501718146e-04 1.40085275117843040e-02 1.02032587258854245e-02 -5.54555712684078918e-03 5.99631476142645486e-03 1.96171173687528996e-02 -1.74756803505859357e-02 1.13806128274174766e-02 8.65295269337811035e-04 3.15080541089918925e-03 -1.42971861092479370e-02 8.48477045776066009e-03 -4.30115285034393929e-03 1.31992217013426269e-02 -9.57549481118050508e-03 -3.71038110870846151e-03 -1.19717010888473613e-02 6.76698980109483039e-04 -1.44512428891788239e-02 -1.22068770465954997e-02 -1.00372432697479023e-02 1.14658441326590047e-02 -6.09040597872713158e-03 3.75532536604730183e-02 -1.77732866388357474e-02 -1.68471769876903411e-02 -8.21279463650449043e-03 -2.00697481546876291e-02 -2.14100954568190692e-02 -9.75813934535707701e-03 -9.13953833140690106e-03 -9.72407081597067430e-03 -1.12643668919269156e-02 +mforces 15 -2.58412272414072081e-02 -2.27358446713159731e-02 -2.21650198444596457e-02 -0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 6.81868944110041418e-04 -2.33565054773998623e-02 -2.31621363142145743e-02 -0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 -1.06544834528657963e-02 4.15777318253355427e-03 -2.11144979056861470e-02 +tau 15 2.33066694981722998e-03 1.25637704272862742e-02 -1.56045530129120587e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 7.08469930849407129e-03 -6.47133263338734322e-03 6.73420406557594196e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.00813082567900035e-03 -1.69693859245670965e-02 -4.85945430887316059e-03 +descriptor 605 -2.81584845555954630e-02 6.31993988525440670e-02 -1.74240127725626831e-01 7.68335611073342195e-02 9.09737177966246924e-02 6.69032463535330999e-03 1.56025200462312028e-03 1.74311044778442600e-02 4.60722092472272936e-03 2.09736164022152494e-03 1.27217918645159533e-02 4.08607211671482059e-03 1.38942133003410496e-02 8.81450197602351784e-03 4.44651302639619700e-04 1.11456586230062448e-02 4.79493966976240853e-03 3.69278724809870909e-02 1.16498140583489364e-02 3.44612178418956562e-03 1.08763171282771440e-02 6.12602672388378594e-03 6.72493743073657724e-02 1.49034796892757743e-02 7.79331209581890765e-03 -3.37320034963586716e-04 -4.87936099979496997e-05 3.71027074353255063e-04 2.54628575216144968e-04 -7.42677775029611166e-07 5.17500000000000071e-01 -2.37279185910536337e-02 -1.57900255140137363e-01 -2.91121618578743567e-03 2.33084147905814165e-01 -1.62819142109084242e-01 -1.28688480235027713e-01 1.29029751896569071e-02 -4.82156665214893351e-02 -6.91398474374583290e-03 -4.30810783539641654e-02 -4.57143972013640335e-02 -1.91855005292034392e-02 -2.90745408343382351e-03 -6.37235102457410219e-02 -1.01796883292300036e-02 9.06059004079128455e-02 6.50572574815955346e-02 1.20544553927359951e-02 3.62111493603775592e-02 3.73758216244356734e-02 2.30148297573584725e-03 5.40845729255100133e-02 6.16920627228318350e-02 1.02386792166392036e-02 4.99696980233617014e-02 6.70048484887774548e-02 3.74131311462553347e-03 5.70506769784901377e-02 8.68574100757475986e-02 4.80941932543145663e-03 -6.03022923750235439e-03 1.76521893822759630e-02 -1.02707835252735741e-03 8.16774682308486983e-04 1.79561819556826744e-03 -2.60567257009375337e-05 2.06378369331067651e-02 2.00876238829665382e-03 5.36840609685818992e-04 1.49517473972996564e-04 4.76939347943776144e-03 1.49226486501337775e-04 2.28923366555831946e-02 -1.27287363294242102e-03 -5.43092450943097002e-04 6.54911950860803335e-05 4.19087729305321383e-04 -1.15714055999680720e-04 2.06905817113843494e-03 -1.43225290872800730e-03 -3.58677935859064623e-04 -4.78130845004735581e-05 -2.14956738256904525e-03 -8.36996382387904443e-05 -1.01971951835896687e-02 -4.44002456848093083e-04 -4.07407674400012842e-05 2.54998901450280382e-05 2.09679613436710583e-05 1.63814379219592591e-05 4.09506239104246751e-03 2.49588033433295218e-03 1.28557471314353884e-03 -4.66053971235846323e-06 -3.81369657597810238e-06 -2.95701401931754752e-06 -2.46385963484248120e-04 -1.72863150100410984e-04 -1.10831642060757625e-04 -5.21182666179645995e-02 -3.57364110403399549e-01 -3.65243388844255310e-03 -4.24930874736498627e-06 -3.28350311286636505e-06 -2.30709465748038574e-06 -7.22850477725587936e-05 -1.36226958255335355e-05 4.80822156353532943e-05 1.10596603603889270e-06 8.65223082982584130e-07 6.21918901274838458e-07 4.01382584941951118e-05 2.08506952643714746e-05 4.06622579386524415e-06 -1.75135497869673042e-07 -4.92748215394049427e-08 7.64863238948711326e-09 3.45821681289019552e-18 6.26645997890049145e-18 1.52466349890183857e-19 8.77351403009525438e-02 1.23993084805332554e-01 -3.40364431776452758e-01 -1.44401938376598954e-01 -5.10081541460933527e-02 3.00706304451940892e-03 2.73545408828628595e-04 3.72226495138064340e-03 1.85784776918831366e-03 1.70809960957148364e-02 6.40185935258637522e-03 3.25301491961206969e-04 1.95745518578393542e-03 3.59005202049765375e-03 1.22727597581771038e-02 1.06044510857350796e-02 4.79866043287734362e-04 3.79742341253665747e-03 4.81706091231448152e-03 2.21363050555264396e-02 1.54025213529019375e-02 5.13631487251901657e-04 1.60096873799686346e-02 5.67906570745943615e-03 2.63462123534773662e-02 1.80492988356124840e-04 1.89169334029229732e-06 -1.10156272393718706e-05 -7.22395154908781845e-05 2.70562246602944298e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.67666277673567214e-03 1.07743441056911055e-01 -1.86062249212281983e-01 9.07642019271904243e-02 1.83112755238829389e-01 4.58126337141965580e-03 2.42375700051930413e-03 4.09564155843027567e-03 8.96778046149935529e-04 5.63612746270282343e-04 4.85804087511424246e-03 2.62835493217478209e-03 4.73553982121985902e-03 4.24059836091352470e-03 1.11356538858656826e-03 1.51178701471394450e-02 6.21149666892809992e-03 4.87243561454657904e-03 1.22061294386195170e-02 3.56618623997462031e-03 2.86955400059827059e-02 1.06013840240294123e-02 7.32977306357661829e-03 2.11185378707666079e-02 5.93245329321685951e-03 2.48866662746735948e-05 1.22020897219577883e-05 -5.81218712647830387e-05 6.32153797285454661e-05 -1.15607379732780942e-05 5.54999999999999938e-01 -4.07811584449467787e-02 -6.37232992993389240e-03 -2.76709516674045405e-02 9.63460595169322170e-02 -5.37601983398739505e-02 -6.99810486286894795e-02 2.04287112616318746e-03 -3.19444877202343519e-02 1.08158875571320087e-02 3.69703885625268444e-02 -1.39352486081737517e-02 1.12737275862543809e-02 -4.87020657932343056e-03 2.30229690047286766e-02 -1.92350376918286360e-02 4.57512167621362126e-02 3.77724826293837496e-02 4.51928701528474773e-03 2.87472365992031591e-04 1.68123290273612495e-03 7.84748292287188880e-05 3.96120653436565218e-02 5.14796307054461028e-02 5.31600192111112910e-03 3.94689718682646670e-02 3.29110034765390455e-02 3.20377928203182359e-03 5.22472311767753911e-02 5.33687073444825549e-02 4.39352309924602880e-03 -5.98420666223044729e-03 1.82431737456541058e-02 2.36003186801909959e-03 9.61035408211682505e-04 1.44027523927823522e-03 -8.82425504002695775e-05 9.34570260673715791e-03 -3.33776857603896573e-03 1.71302556687988913e-03 1.95277510914537104e-03 -1.03844066900199579e-03 2.08672821295848758e-03 -9.64853607387191128e-03 3.78383298112628611e-03 -4.24879557602457990e-04 1.34494835745835079e-03 8.56741696386209171e-04 5.63540591375682109e-04 -3.87869765888205998e-03 1.59099605466170367e-03 -1.06393064053002549e-04 3.74325266881368193e-04 1.75320838208357943e-03 -7.16761412665365642e-04 2.29924294019938791e-03 -7.89366607907292868e-04 1.39390946139630325e-04 9.15901281295032628e-06 7.37335288003752076e-06 5.56624246739086098e-06 -1.70577471412636694e-03 -1.01581823943158928e-03 -4.99603439677729494e-04 -6.32265681100235112e-06 -5.09279808830511188e-06 -3.84867816853578867e-06 1.41773076878679493e-03 8.69446443497533358e-04 4.52494597877235141e-04 -9.69871649489900400e-02 -4.11076000862760707e-03 -7.29145500642576910e-02 -2.00571265353455124e-06 -1.58957714615763272e-06 -1.16886310776346642e-06 1.07503040755228267e-05 9.29921300963874661e-06 -1.55845353760947017e-06 1.56602921420713260e-06 1.24114225130155635e-06 9.12794876056425327e-07 3.88364795945499008e-06 8.31288577495408343e-07 -1.77041319255633719e-06 -1.11178750066144171e-09 -3.33610077229218738e-10 -8.64700510416021879e-13 5.55633426513696338e-19 9.57714701309973660e-19 2.24656496070462156e-20 1.13728748585068276e-01 1.76583054895257635e-01 -2.77227055065579986e-01 -5.98654909530829810e-02 -7.34488980583219847e-02 8.46204070506416926e-04 3.74609217225292744e-04 5.38745856757624417e-03 3.17604347727756201e-03 1.64085735498280712e-02 1.32988977112489712e-03 3.92543191297994398e-04 4.98549131406519908e-03 4.29250485196029392e-03 1.52669037204236600e-02 3.33120949185276329e-03 5.87293774791910984e-04 2.51852539994608078e-03 4.61300073820710647e-03 1.08287420510473457e-02 7.09937585585637947e-03 1.11986010921955753e-03 1.84079887562701690e-03 6.12832827447749862e-03 1.29639665013123965e-02 7.74431255336571052e-06 2.64676582909553350e-07 -1.21842785522439850e-04 -8.02511166375263529e-05 -5.84546969461603250e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.78142475341600270e-02 6.88492939960179406e-02 -1.56780867278377395e-01 1.13077656619485462e-01 1.02372301231614310e-01 3.85709235401085785e-03 3.40254404146333360e-03 6.88992530907192244e-03 1.69735746821853863e-03 4.51790586139187570e-04 6.15515628577307117e-03 6.12091203270774802e-03 8.86805907341970887e-03 5.11716125331815319e-03 1.23489287513073743e-03 7.59715046724635575e-03 8.63517326954924870e-03 8.69723217467765174e-03 9.57479410977241617e-03 2.23856194209367610e-03 7.90227191749903919e-03 1.01222438352679359e-02 8.53798406982168509e-03 1.28279387368375186e-02 2.96427209416804446e-03 -1.50014685647376837e-04 -1.47152246718222326e-04 -2.43944939054006952e-04 -7.69371703876373477e-05 9.19036773821222304e-06 6.67500000000000093e-01 1.06468946830997890e-02 9.04501770105478331e-02 -2.94372032430747672e-02 -6.21358740693425046e-02 -8.87499489166363870e-02 -9.98903983783878124e-02 -1.14556969148303309e-02 -5.30156230973029205e-02 1.82586577948813042e-02 8.69062860936667403e-03 -7.76230527162243174e-03 3.27632168285132905e-02 -1.59042210349377641e-02 -6.72288744699780453e-03 -2.40063706866874248e-02 3.54335807298296291e-03 2.06536118475471528e-02 1.02695827837283715e-02 1.01874809177298579e-03 8.27509912398750359e-03 2.68111091152419033e-03 1.23002944294108496e-03 1.45008062010863782e-02 3.49998027781224345e-03 3.40827977854981333e-03 2.44593736631939299e-02 7.72455935991345818e-03 3.63940097903891341e-03 3.62078215846474150e-02 6.54437774952186611e-03 -1.65156305958105731e-03 -8.99118754765097956e-03 1.90630603240741874e-03 1.37717694447142200e-03 3.79506403912522076e-03 -1.46325558396893255e-05 1.66976384193624969e-02 -3.30034355399152178e-03 2.08058158785063554e-03 -1.23229329566749740e-03 -2.24323664847811454e-03 -5.38842103299888272e-04 -2.81219756214886110e-03 -1.29441189712470989e-03 -6.28360549139319853e-04 -8.56901282485856403e-04 -1.81906290699003210e-03 -1.21719870687603943e-04 -3.43397258782987590e-03 1.40540844085769223e-04 -8.55293981417571043e-04 -2.53517508421041466e-04 -1.01363367947320611e-03 4.58441614828777432e-04 -3.72863777864637430e-03 2.06616670243885657e-03 -1.06238821628189305e-03 -2.85088642408027075e-06 -2.24134482280917544e-06 -1.62449986994583862e-06 -1.86454232364009699e-03 -1.15180463239550682e-03 -6.07170999213114135e-04 2.00690718292141198e-06 1.57746164799031560e-06 1.14304917046644809e-06 1.18100129928339222e-03 7.28758767359347537e-04 3.83479941585168388e-04 3.48143138255869108e-02 2.55364642778155904e-01 -7.69491070255694798e-02 2.18646870114925569e-06 1.73009887775473051e-06 1.26870860651273605e-06 -1.16939799072132366e-05 -6.61158992383183582e-06 3.00420172070483757e-06 -1.53019055592409783e-06 -1.21059840650590974e-06 -8.87602800117520289e-07 1.03379671478781338e-05 6.10262579142452263e-06 -2.37876625317595402e-06 1.64476255550436585e-10 4.13307395815368519e-11 -7.73560598102089873e-12 3.77461414041318370e-20 6.52048821770076464e-20 1.53415849864411533e-21 +end +case random_multitype 8 +types Ge Fe Ge Ge Fe Fe Ge Fe +cell 9 1.30000000000000000e+01 4.00000000000000022e-01 -2.00000000000000011e-01 0.00000000000000000e+00 1.40000000000000000e+01 2.99999999999999989e-01 0.00000000000000000e+00 0.00000000000000000e+00 1.35000000000000000e+01 +positions 24 1.05195795123286806e+00 7.54513157485344976e+00 1.92678016605364433e+00 6.46852031811661554e+00 3.67791605244682529e+00 1.05287067051035566e+00 4.81735914385441433e+00 2.66519633158947888e+00 4.46326047297769435e+00 1.31815556951734236e+00 7.47518901279024117e+00 5.42123896216220835e+00 6.89722237837808461e+00 4.40524688937426134e+00 2.81634767538512243e+00 7.91697690449841840e+00 5.61941046163939095e+00 7.59164543829853056e+00 7.22363391762259788e+00 1.69287733412652353e+00 7.21909484608720842e+00 1.96643034124545912e+00 3.58552152099393107e+00 3.24131466612851726e+00 +spins 24 3.42956689606492948e-01 -1.44334109384587284e+00 -9.20576318816501371e-01 -7.93035969575581312e-01 -8.50622373758950362e-03 -1.58959621466146922e-01 5.74721063246211528e-01 4.25502328712981936e-01 8.60292342154923562e-01 -5.68052435501097297e-01 6.94785435747145463e-01 1.51775094776792541e+00 -3.21782166655971369e-01 7.04734259188120715e-01 7.16111647147331332e-01 7.38660791723244614e-02 -3.32854884286343966e-01 4.08657239828918162e-01 1.49528411107386322e-01 -7.40695736034854835e-01 1.30976057471167306e-01 -4.33378437932692290e-02 2.65331202826330936e-01 -1.14193824659042251e-01 +potential 8 2.15707550850646079e-01 -2.39243708245063635e-01 2.13930079194878303e-01 2.16123856077828747e-01 -2.22692869522951531e-01 -2.45915586883055370e-01 2.15142543361219962e-01 -2.38647190951458171e-01 +forces 24 -1.27497026653884140e-03 6.14047269750988330e-03 -2.72506232647476551e-03 -1.69200261234356362e-03 1.55983750965942329e-03 -1.22037912576581850e-02 -7.14595287999865653e-04 5.55960519405456714e-03 -1.91489186409325458e-04 -4.62575181887213524e-04 2.15573185569425474e-03 1.77580971298767817e-03 2.84592438249260324e-03 -5.49108723345446536e-03 8.63782887829340693e-03 4.83473118648464369e-04 5.32802158442059921e-03 1.47091244836340890e-03 2.34496261611789848e-04 -5.65645130865102819e-03 3.33426327263953081e-04 5.80249586016627281e-04 -9.59613029923323500e-03 2.90236540363382782e-03 +virial 72 1.32928067479604799e-03 -6.50547351216865764e-03 2.20123934163264038e-03 -5.72507586626981591e-03 2.81621284105233113e-02 -9.12378326531726284e-03 1.99884551481617576e-03 -9.36923517864027798e-03 4.33531717741324554e-03 7.18252232298197124e-03 -3.19360969321048102e-04 -3.84299027037034472e-03 5.08221118443183493e-03 -1.65808964738135508e-03 -1.18831325592465850e-03 6.16911716928174401e-03 -6.89757343966047702e-03 6.58531893050857617e-03 -1.27287217556451664e-02 -5.84344850287038531e-03 -3.12727166866942630e-04 -4.23148761554301318e-03 -8.21551369298133098e-03 1.68343739414516299e-03 -2.22071339658652450e-03 2.66591830858296580e-03 5.26056570658662952e-03 5.63994303356280370e-04 -2.72427684236802243e-03 -1.29796279283863041e-03 -3.33957750746669609e-03 1.63317430444313259e-02 8.36403204641635901e-03 -1.76889113754939925e-03 9.12057205932670714e-03 6.02075206413093828e-03 1.07391424231257325e-03 1.09622205320022894e-03 3.27893422938232764e-03 -5.18098812779296922e-05 -4.12536920026499235e-04 9.00490359264479075e-03 1.93441576402508158e-03 1.05052546485017335e-02 6.78862237084532950e-03 -1.31610387006423648e-03 -7.12444784591900141e-04 -1.64540270100005235e-04 -5.38252218619317225e-04 2.91313528777296504e-03 5.63747873292621128e-04 2.30818925413196036e-04 1.80156826778377858e-04 5.94096279152956340e-03 2.04295706911326305e-03 2.57177881178411848e-03 2.04996028479104532e-03 2.15521592524687200e-03 1.91421843342348685e-02 -1.32192398287312753e-03 2.01530603694554484e-03 2.64246002807818313e-04 4.08195132551184697e-03 1.18055348230593164e-02 3.18888709557975164e-03 -2.96265912536976565e-03 3.17484455699001055e-03 -1.14955471568859349e-02 -3.37504390830732854e-03 -3.03501046378502936e-03 -3.44988379837386436e-03 -1.03238671345116202e-03 +mforces 24 -0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.00482987461051800e-02 -3.37276530326194399e-03 -2.30411236373809052e-03 -0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -3.71209245193277956e-03 -2.67527948181797530e-02 -3.66866044282681686e-02 -2.38232134226207346e-03 7.99474996778776030e-03 -1.19675073720977940e-02 -0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 -3.03469230728452017e-03 -7.32963251766426994e-03 2.11259798570382143e-03 +tau 24 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -5.16534200618170539e-04 -3.42451774744775925e-03 2.76019727973972600e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -6.69631903084190287e-03 -1.44633677002954427e-02 1.12246110048471858e-02 7.16330826577101193e-04 -8.95600170715900350e-05 -2.02426460627981006e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.76460605902089155e-04 4.38098562734600284e-04 1.12284902921221596e-03 +descriptor 968 2.37719222057580044e-03 -2.99906325609654960e-02 -2.16017565199805028e-02 -1.16534633892441987e-02 4.73460364149649385e-02 6.83626793813359450e-06 2.05631489053119274e-04 2.46589620084678395e-04 7.06102462191989010e-04 4.29227558277706510e-05 6.82773828384617992e-06 2.79888611290948850e-04 3.29134407513013213e-04 1.26005283295708070e-03 4.26903823385560785e-05 9.06207977680329591e-06 3.96840649058695111e-04 4.64831135264215812e-04 1.85996296470102929e-03 5.65136356822470000e-05 1.86456469230911245e-05 6.36798406581165488e-04 7.55916172497554575e-04 2.48811178397884830e-03 1.16241548684341614e-04 2.40971986575800220e-09 1.46612693474465706e-06 -1.82006902289143867e-06 -1.54999903684554831e-05 -3.62323508848412576e-08 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.60099171507750704e-02 3.24416719979410961e-02 -7.51081816592389651e-02 7.99152204142680178e-02 1.50076363347157765e-01 3.57932497842947291e-03 1.14294619758008266e-03 1.34504651303172390e-04 7.97937050349042292e-04 1.13036887921281028e-03 6.60997169354674702e-03 2.23614141375210124e-03 5.29365659820023771e-04 1.80515258813278745e-03 1.87742536526626239e-03 1.00703002885755722e-02 3.53076105182778240e-03 1.08479396941008510e-03 3.07729364003061926e-03 2.65081509673313967e-03 1.36546658142334149e-02 4.80174601378355586e-03 1.50635114716126859e-03 4.21031711362863936e-03 3.56057917161735132e-03 -1.89661747949615639e-04 -3.67154727261115007e-05 -1.40860207302204525e-06 2.48895758195537395e-05 2.79106579637402326e-05 4.90684924604712802e-01 3.29558427837877838e-02 6.08029701250999283e-02 -5.29704186100694689e-03 1.79457065681244338e-01 5.35971407844187536e-02 -2.81695515765541769e-02 -6.20429600705766360e-02 -6.34003824773168578e-02 9.84906216398705701e-03 -1.76479548071190387e-02 -8.08694739702929496e-06 2.80408752294716932e-03 -2.49766051200395623e-03 -2.57740547824416091e-02 4.55942637621973104e-04 4.53147272823950162e-02 1.69709990573894375e-02 1.10314818783395540e-03 2.98140149983275697e-02 9.22434441014459428e-03 7.28147477699553044e-04 2.14749057759748251e-02 2.44290777612596946e-02 5.30044493795896773e-04 2.93793223811367604e-02 1.07219972502262499e-02 7.15899866539807125e-04 3.68260270290762665e-02 2.59925454338027391e-02 9.04728717959139882e-04 8.86034356798537023e-03 2.77423719774476558e-03 2.18457816020940191e-04 1.08908404734076188e-03 1.36387300944735353e-03 -1.73109647162045238e-04 3.68583414409750501e-03 -2.23194337790241787e-04 2.77063543867860558e-05 7.94876577492078379e-04 2.13086938187740261e-03 -1.28504410558386131e-04 2.74373048207289961e-03 -3.39618260918800048e-04 2.08870120859418039e-05 4.84911002624957305e-04 1.31286521464141020e-03 -7.85489755609553497e-05 1.69850088323323387e-03 -2.09107954994340622e-04 1.27874967257250033e-05 2.02204947716053689e-05 7.11251296012232342e-05 -3.47748372853599271e-06 1.07839617277562393e-04 -1.12198633019870031e-05 5.95796442875540674e-07 2.04197087713052631e-06 1.63283607673405957e-06 1.21879035853762944e-06 3.64306496057149951e-04 2.28853410976208793e-04 1.24221451292161155e-04 -1.48632865045593541e-06 -1.18814959870189621e-06 -8.86515896785678819e-07 -3.33583547469829315e-06 -2.54583533847693621e-06 -1.79924995745242478e-06 9.52729389860015458e-02 1.81021923401928325e-01 -1.52469359648549387e-02 9.81901747326394149e-07 7.77128093652873397e-07 5.70101711377750240e-07 7.68986850713522887e-05 4.86872144310311961e-05 -1.45550434004809837e-05 -6.99820663892027495e-07 -5.53805015658561846e-07 -4.06234353634778104e-07 -2.27613988060332388e-05 -1.40788558543701044e-05 5.57699871337748703e-06 7.47296091876327361e-11 2.12441739550837678e-11 -2.72543138263259909e-12 9.69379734478748666e-22 1.68202031757513959e-21 4.96047964125142207e-23 8.50592177763960927e-02 1.58712836398742091e-01 -1.46439356427428474e-01 5.71593780112633204e-02 -4.56234365645059037e-02 6.88060470874719420e-04 5.04995812060434900e-04 4.85353729281682786e-04 1.06009364805334549e-04 1.08632154537354722e-03 7.98477150831466368e-04 9.71420988510107719e-04 8.75583564942259947e-04 5.80782563983342080e-04 1.28116844353826954e-03 2.43996935667836106e-03 2.37788078232772362e-03 2.20118107821855183e-03 7.17865062959440110e-04 3.72165427423465194e-03 3.29909672926593589e-03 3.73546576386185039e-03 3.39122170861034427e-03 1.89559790590834568e-03 5.05652594164515256e-03 -5.47029943647658735e-06 -1.06352577146321434e-05 8.91531026189480800e-06 -2.11449196265185506e-06 9.67005132626895478e-06 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.76296021500916028e-03 -3.23039543099431017e-02 -1.36227676979040011e-02 -1.28751931666684968e-02 4.84825539493953031e-02 3.88719630921547743e-06 1.77637912334415880e-04 2.16773761943986630e-04 7.29338830364222751e-04 1.95889759431299159e-05 7.48365388246549481e-06 3.05573186913327924e-04 3.56967262644198029e-04 1.23903444790051352e-03 1.92437982901261806e-05 1.14160202761299898e-05 4.46446199701221679e-04 5.11828407482573270e-04 1.79986667208500832e-03 1.94415627353664624e-05 1.49695743680313131e-05 6.08373505581039000e-04 7.08889065115438522e-04 2.46086621732446650e-03 3.72103498706191345e-05 7.17212240422973738e-09 1.87545367712954742e-06 -2.33999219862482858e-06 -1.50949754118569874e-05 -1.23625312796747255e-08 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.96240343930878305e-02 3.83214827299449695e-02 -8.41280856661260623e-02 1.10296700429977926e-01 1.75013530195716416e-01 3.70097291476226796e-03 1.53749615858758421e-03 1.34982621492777408e-03 1.01225343111018711e-03 1.20384384583738474e-03 5.93060421452018885e-03 3.27700036735063902e-03 2.81917805515915923e-03 1.84046122149041547e-03 2.46981133004479112e-03 1.03447106683987097e-02 3.29605215551470859e-03 2.95902957779916155e-03 2.54940763568613140e-03 2.68397468377243060e-03 1.44602452200120260e-02 3.99208150288022506e-03 3.63706699140790542e-03 3.39232206185113502e-03 3.33554047341066365e-03 -1.52480650120832877e-04 -4.75480668349959111e-05 -4.09326036607035915e-05 2.71736134575225179e-05 3.49968942368959052e-05 8.34757522523478457e-01 7.48122681794658947e-03 -4.22177948829474126e-02 -2.71757754361540843e-02 8.21987889974093305e-02 -2.91251776533399016e-02 -5.04690755620954973e-02 -5.02023624080173772e-02 -1.68935192737354606e-02 1.88066391199805359e-02 7.27500272563622874e-02 7.91380126480899782e-02 -2.08891552802141327e-03 -1.30296806904430015e-02 -5.12925599267065324e-02 -1.53161094439374264e-02 3.90572926823454861e-02 4.95099370810568665e-02 9.79253758763382227e-04 5.34318577379548198e-03 4.42157753711099662e-03 2.26684670080141900e-06 1.96523345357557180e-02 1.00288923073816455e-02 3.45357326470667469e-03 2.02270037127334247e-02 2.30433475905301721e-02 7.43315076682552704e-04 1.94936863063048700e-02 1.49437929959258288e-02 2.04802195052629886e-03 9.31727486133738375e-03 2.33903460349475199e-02 5.98870813583320225e-04 1.57754367859167573e-03 2.80421475071563828e-03 4.96901894381007194e-04 7.64986321096937545e-03 2.10333972013529479e-03 7.40225170465077013e-04 -1.54276930753374938e-03 -3.47787026820365122e-03 -8.76394124244518819e-04 -4.78584076901189103e-03 -1.50641246130106906e-04 5.38350546529558637e-04 -6.39210500157060815e-05 -9.28224368241375986e-05 1.76009696650202073e-04 -4.55659848403513752e-04 2.26256359267070016e-04 1.04112559091276404e-04 7.68632270415912098e-04 1.55852669957954140e-03 3.69900397023141406e-04 1.76081326437527120e-03 1.42567795302687902e-04 -8.67597756671092382e-05 1.41792717904317177e-05 1.12413204216818697e-05 8.26813739691830675e-06 -4.60142176835851794e-03 -2.85341845688271171e-03 -1.51401052831511723e-03 2.17544954569792127e-06 1.72401469638042376e-06 1.26735437796518592e-06 -6.95855109275343763e-04 -4.30562560596872690e-04 -2.27598669443971989e-04 2.04635249493733285e-03 -1.82820853290307311e-01 -9.56559108637792671e-02 4.81453468269220342e-06 3.79649044508934033e-06 2.76725051098413032e-06 1.93284601514916193e-05 1.88889377301392183e-05 -4.75537172443837741e-06 7.61532669102500050e-07 6.00060914931079654e-07 4.36870215908458936e-07 -1.40119712880825373e-05 -9.73787732188106734e-06 3.08969403815411003e-06 1.30670717607349831e-09 3.36091211824465115e-10 -6.46212773282962489e-11 -1.06499787492048687e-19 -1.85170260796754449e-19 -4.36228627261911999e-21 -3.45563363319349726e-03 1.76236395822740206e-02 -1.56989089136424648e-02 1.09569522127656010e-02 1.88977312192282407e-02 4.11483851803155721e-06 6.58898538613803002e-06 1.38665955711906371e-04 3.52412048124491967e-05 2.31812053482141236e-06 7.24995357946953524e-06 1.16020740791075282e-05 2.44021095245845635e-04 6.19803878383997010e-05 4.07465631346277937e-06 1.06985801469431501e-05 1.71115081874396149e-05 3.59705170027253384e-04 9.13156080504415969e-05 6.00008976320116924e-06 1.44607182205229758e-05 2.31172877106876301e-05 4.85718180063102883e-04 1.23246865449159256e-04 8.09442088388458912e-06 6.90597988577757167e-09 1.38848879130327341e-08 -1.33025245675649117e-06 -1.69147374102978566e-07 2.83235037819195573e-09 2.12436983482618136e-01 -5.35471851593970639e-03 -2.20923814441651954e-02 3.17022839438011817e-03 -8.18763336444384635e-03 -3.79033769528163006e-02 8.89070289071456320e-03 -2.06135741392958342e-04 -4.08855111727857330e-03 5.29025410517813561e-04 6.81313981341425995e-04 1.91676143081788300e-03 -5.43329853995953003e-04 -1.83163107132523805e-03 -7.59660449421541584e-03 1.02401002456211005e-03 2.97534317995163148e-04 4.75374980073987267e-03 6.50164641840382009e-05 1.49961511440248682e-04 3.42947844861004724e-03 2.29761609122967347e-07 1.07006488194072717e-04 1.22855365506325436e-03 1.95400642172499184e-05 1.56450207927382595e-04 2.76474723319791293e-03 5.94488679706332780e-05 1.46208378202866479e-04 2.79548966212052677e-03 4.90951932713726914e-05 8.22829410790768581e-05 1.50710143114788308e-03 2.05195252737511491e-05 3.73978334873790647e-05 1.66576110607064292e-04 -1.79845547803173574e-05 7.61647195802781494e-04 -7.73253182743966204e-05 9.48954899548711373e-06 1.19851539628875538e-05 3.62412478046052734e-05 -1.12990106904897512e-05 7.61368965036056091e-05 -4.39148683930457791e-05 7.93335468310104867e-06 9.63570046421630841e-06 2.93642523775145731e-05 -8.48647941768207006e-06 6.31313938377543629e-05 -3.26572058896172678e-05 5.83664305738834001e-06 4.52413715098942331e-06 1.41244406865379991e-05 -3.29273470858663972e-06 3.21138501758862501e-05 -1.23353123496257558e-05 2.12711668007683847e-06 1.03747115864456242e-08 8.15468584546680789e-09 5.90806098259378093e-09 7.77814250479599427e-05 4.78414620590189268e-05 2.50284134026348665e-05 -1.09902752861939779e-08 -8.64225576651241284e-09 -6.26707807686391300e-09 -1.66746155074185825e-05 -9.99781691143671775e-06 -4.98912323241855350e-06 -8.35976144894156302e-03 -3.20165075733412074e-02 5.57272230783618840e-03 2.84116127370386478e-09 2.23061488391739238e-09 1.61335682991934807e-09 -4.45657650868048609e-07 -2.61005902502084063e-07 9.96882715174706017e-08 -2.96748477227095833e-09 -2.33072079234593467e-09 -1.68718008464205437e-09 2.73225386806844950e-07 1.41415288344704331e-07 -9.92645163767186316e-08 -2.22402251163570242e-13 -5.44719898531941991e-14 1.54169893020076745e-14 8.30542302829598075e-23 1.46683788653316349e-22 3.50010918619901266e-24 5.81261583680448175e-03 -2.00545734473527981e-03 -3.74217217227897012e-02 -7.42278471360278882e-03 3.72619647726768893e-02 2.87666445814832567e-05 1.57133932542428804e-04 1.31445224735629574e-04 2.13041110426678295e-04 8.71593160996297309e-05 3.49659373537748212e-05 1.30937605365570684e-04 1.09499025439593523e-04 4.64516174930165564e-04 1.06391353789438207e-04 6.72448124566043485e-05 3.38119164345387945e-04 2.82537425026661891e-04 5.95094285861506346e-04 2.03164926406667208e-04 1.16635783769405087e-04 6.95261046258567801e-04 5.80623501183071553e-04 6.56506119628497923e-04 3.50442304785542362e-04 4.40538913038835852e-08 -4.87966708259020416e-07 3.69906185322006920e-07 -3.04908470095544653e-06 -2.33259143782632450e-07 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -5.24633390578011383e-03 4.89475176445238191e-02 -4.55335257379540503e-02 4.15277750940928406e-02 5.11523307054397511e-02 3.67026908401016591e-05 1.28304744741381015e-04 9.29989644520033904e-04 1.71313171292063749e-05 5.44968824062828301e-05 5.93081308192571285e-05 2.48156654027505738e-04 1.90585503157994583e-03 3.07689947278162515e-05 8.84611471949416930e-05 9.35303986576830715e-05 4.27466255330458372e-04 3.42155932367916270e-03 5.69057381273158793e-05 1.24487907727064388e-04 1.35367638262720759e-04 4.88905796339720710e-04 3.61944605536554343e-03 3.48812517970711766e-05 1.87250937551174118e-04 -1.58334087472312922e-07 1.33662996097100012e-06 -2.76405272421582573e-05 -4.94440698411265879e-08 -2.84111261937438828e-07 6.39892841161330828e-02 4.41432425691249460e-03 1.60066273816553938e-02 -3.80424577236152580e-03 -9.64988464565454396e-02 -3.70614366136080065e-01 6.93885034633175551e-02 2.72677482281497756e-03 1.24805479970444555e-02 3.91343449924075500e-03 -1.01165358034474833e-03 -3.39623426012857031e-03 1.17839155371179580e-03 -1.12939307355095614e-03 -4.70896433465008233e-03 1.50213693206470086e-03 1.28245027993102679e-03 1.45170278359617669e-02 1.53597406589257466e-03 7.93080289723913524e-04 6.24730782906976478e-03 2.07327744032356168e-04 1.16342540885242310e-03 1.80492828114069588e-02 3.43850883869236518e-04 1.40083933374649796e-03 1.97390662620061420e-02 1.87722868131804570e-03 1.23762103205496063e-03 1.70324369872412451e-02 3.16930797274676086e-03 6.06450666058664246e-05 7.05427842144293977e-04 -3.12702497915360136e-04 2.45848563636761323e-05 9.65607377341725086e-05 -2.95239453574869995e-05 3.85155702807460918e-04 -1.18385294029858254e-04 3.71494171055425552e-05 9.00998766669350152e-06 2.46992686696930861e-05 1.02925902432584050e-06 5.52243573292206409e-05 1.50147209174401572e-05 -1.29908950279618240e-05 -4.66414883657601763e-06 -1.86806411313364810e-05 5.62733532839708453e-06 -7.21356970802319294e-05 1.98023334343397204e-05 -4.83193182813573460e-06 -5.63488610304350544e-06 -1.78200762524051457e-05 5.12961692810819277e-06 -4.95572254356769687e-05 1.28887905747738138e-05 -3.26968559169990771e-06 -5.86267573692923672e-07 -4.59906745717178447e-07 -3.32032222595375491e-07 4.81571201264714937e-04 3.00876944749675353e-04 1.61787602986115670e-04 -3.35972914732029530e-07 -2.63445041036106107e-07 -1.90078503568830972e-07 1.40018158278681340e-04 8.51577045146131905e-05 4.36264923805211265e-05 1.87024318590904605e-02 7.26617271105447493e-02 -1.94521504604314756e-02 -5.07651885948630518e-08 -4.03889409415806766e-08 -2.98984850798710841e-08 1.91864160337809769e-06 1.33107282040611792e-06 -2.70843815266418415e-07 -1.57327078257541977e-08 -1.25251075661113145e-08 -9.28332802634259543e-09 6.51091874086072396e-06 2.81436749739085557e-06 -3.29368316470824049e-06 3.63687322676510871e-11 5.19385786789234581e-12 -6.45726342715278586e-12 1.43222096429215804e-20 2.52247374599590307e-20 6.01141208333834388e-22 +end +case pbc_wrap 4 +types Fe Ge Fe Ge +cell 9 1.40000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.30000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.50000000000000000e+01 +positions 12 2.50000000000000000e-01 1.10000000000000009e+00 1.19999999999999996e+00 1.34499999999999993e+01 1.39999999999999991e+00 1.00000000000000000e+00 6.79999999999999982e+00 2.00000000000000011e-01 1.44000000000000004e+01 6.50000000000000000e+00 1.25000000000000000e+01 4.50000000000000011e-01 +spins 12 6.99999999999999956e-01 -1.00000000000000006e-01 2.99999999999999989e-01 -2.00000000000000011e-01 8.00000000000000044e-01 4.00000000000000022e-01 5.00000000000000000e-01 2.00000000000000011e-01 -5.99999999999999978e-01 -4.00000000000000022e-01 2.99999999999999989e-01 9.00000000000000022e-01 +potential 4 -2.44307725566190653e-01 2.09775527219412200e-01 -2.40506590442669588e-01 2.10930603521767290e-01 +forces 12 1.63895560988528907e-04 2.82366274688379678e-03 2.13763508176373915e-03 -1.63895560988528907e-04 -2.82366274688379678e-03 -2.13763508176373915e-03 6.37749165219563593e-03 5.70019637816257443e-04 -9.65101915633677539e-03 -6.37749165219563593e-03 -5.70019637816257443e-04 9.65101915633677539e-03 +virial 36 -7.70703246270185334e-03 2.89013717351319262e-03 -1.92675811567546984e-03 2.89013717351319262e-03 -1.08380144006744658e-03 7.22534293378300756e-04 -1.92675811567546117e-03 7.22534293378297395e-04 -4.81689528918866918e-04 7.83814891149267612e-03 -6.31206976006153109e-04 3.63686618108646255e-03 -2.93930584180975138e-03 2.36702616002307307e-04 -1.36382481790742237e-03 1.95953722787316686e-03 -1.57801744001538115e-04 9.09216545271614661e-04 3.89011038972254331e-04 9.07692424268593222e-04 -1.36153863640289265e-03 9.07692424268593113e-04 2.11794898996005027e-03 -3.17692348494008148e-03 -1.36153863640289287e-03 -3.17692348494008278e-03 4.76538522741013285e-03 1.52423645668643519e-03 -7.36686532923716076e-04 -1.53376711049813853e-03 3.55655173226835080e-03 -1.71893524348867193e-03 -3.57878992449565730e-03 -5.33482759840253010e-03 2.57840286523300941e-03 5.36818488674349094e-03 +mforces 12 -1.40005738480958042e-02 6.27500051927484554e-03 -3.63718426366924346e-03 0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 -1.22514652733064014e-02 4.57223734464565473e-03 1.23014863983181445e-02 0.00000000000000000e+00 -0.00000000000000000e+00 -0.00000000000000000e+00 +tau 12 -1.51878172941552936e-03 -1.65414316986027088e-03 2.99244297868281111e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 5.20363968645102138e-03 1.20013596482476843e-03 4.73641172698410773e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +descriptor 484 1.32323775964721009e-02 5.73079475144103109e-02 -8.33764214485616939e-02 -7.36506994980744723e-03 4.20875873242987641e-02 5.97083177864349722e-08 6.28222256221522301e-04 6.33540057757323461e-03 1.36606606145634564e-03 4.09499648212181561e-03 1.05200369434412074e-07 1.10619173175890918e-03 1.11488892844939375e-02 2.40256554089290008e-03 7.19794463611487557e-03 1.55241626245617427e-07 1.63148491776624114e-03 1.64342886489121688e-02 3.53969603771582151e-03 1.05992531896607345e-02 2.09832088221074935e-07 2.20410181420092888e-03 2.21915986711464924e-02 4.77745755194775631e-03 1.42989221424908927e-02 -1.20711422480023252e-11 1.29266068113577836e-05 -4.10809440839918596e-04 -4.08222268360331281e-05 2.10292244036169526e-04 4.42500000000000004e-01 -7.42962460999334307e-04 5.58187615088683985e-03 -1.19092153760289570e-02 6.40584197650983286e-03 -4.81162599207504565e-02 1.02635783422504123e-01 -1.85231251623480453e-03 1.39103194265131538e-02 -2.96655763009903255e-02 2.82288046521909008e-03 -2.11946894349221669e-02 4.51914115553100487e-02 8.21513558197155903e-05 -6.16687627150635772e-04 1.31465364540579396e-03 6.93770280808692644e-05 3.87783863035596468e-03 1.74816888962267859e-02 1.12400505009477356e-05 6.28153505785229672e-04 2.83128825063890888e-03 6.11199448795616190e-05 3.41513098013401361e-03 1.53905320018381149e-02 3.90768771902499923e-05 2.18310349663585271e-03 9.83675083340063844e-03 5.05705444635999430e-05 2.82478335235803726e-03 1.27261336792455527e-02 -7.74755138490326152e-06 -4.32700912808232864e-04 -1.94910784245287184e-03 9.41609654793634178e-07 -7.06039499683995201e-06 1.50345310910181519e-05 5.32944360399332677e-05 -1.13475899448052639e-04 2.41605169474398723e-04 0.00000000000000000e+00 8.66797049328666327e-22 -1.74488787134385874e-21 -7.02472657612153934e-21 1.41398033323800376e-20 -5.69206140554889852e-20 0.00000000000000000e+00 9.00678367218838182e-22 -1.81265050712420283e-21 0.00000000000000000e+00 2.93638088372455745e-20 -5.90890184004599960e-20 0.00000000000000000e+00 9.34559685109010226e-22 -3.76082628580909384e-21 -1.51336553247285841e-20 1.52240055048655400e-20 -6.12574227454309947e-20 1.23815089837370866e-22 -7.03981099158812944e-24 -2.87659027300306718e-24 -2.03908915871446249e-20 -9.31577086391693216e-21 -1.46891512828478755e-21 2.45981669798980917e-22 2.58545453265326266e-23 4.25924485703896859e-23 -1.10013104814702122e-20 2.27303887026616778e-20 9.12265703562822546e-21 -1.70832271598025790e-03 1.27922463872484470e-02 -2.72040505518147194e-02 -1.34707912989899311e-23 7.65553790049133986e-25 3.12672855761202668e-25 1.40925564024501087e-06 3.99888925152877093e-08 -1.37061001368508645e-06 -2.66886627571673224e-23 -2.80394364809490472e-24 -4.61716459292459643e-24 -4.84704194566631861e-07 -1.37516771974407472e-08 4.71259611004583525e-07 2.87919812940854448e-29 -1.85099233281533357e-32 -3.47481334594016438e-30 3.25851103247555246e-27 -1.69687058691755231e-28 1.86487776348051366e-27 2.47944173917764724e-03 9.19900957191343710e-02 -1.11356132631238794e-01 -2.18086185570416993e-02 4.69421717339399240e-03 2.49750562651046223e-04 1.74696613261722606e-06 4.04372630355156592e-04 7.39860270502511511e-04 6.11022467440762874e-03 4.40036705628163796e-04 3.07610797361274373e-06 7.11605466822136097e-04 1.30122754758287191e-03 1.07401945551417032e-02 6.49351462896428379e-04 4.53684801674458519e-06 1.04895916960661773e-03 1.91709650203090456e-03 1.58153538476793858e-02 8.77694834460122464e-04 6.12918626189431913e-06 1.41643373872893386e-03 2.58746713385887492e-03 2.13357025516200255e-02 -3.26554616143427163e-06 1.89557638758133054e-09 -6.62448201504290935e-06 -1.62709795488327313e-05 -3.83291091427599500e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 9.28208622979889014e-03 5.02208930048131524e-02 -6.47045121388184902e-02 4.77069976285119379e-02 -1.07043462036130049e-02 4.24621160965767298e-06 1.47504316912644819e-03 9.48409344825217222e-03 1.25246229631354551e-03 1.36478666515660449e-03 7.48142045519432740e-06 2.59729823564190795e-03 1.66898851183393503e-02 2.20276518046465209e-03 2.39894195240309511e-03 1.10401501851729876e-05 3.83066766522728586e-03 2.46021269520950263e-02 3.24533048052097137e-03 3.53253524808211416e-03 1.49224007996665663e-05 5.17515145778261586e-03 3.32208189499962891e-02 4.38015819650329312e-03 4.76556655210420323e-03 7.23933317276802873e-09 4.65073568324781574e-05 -7.52442005960403046e-04 -3.58373699673046855e-05 4.04613260252878327e-05 4.87500000000000044e-01 -3.77730988177376534e-02 9.20695404169212112e-02 8.88005481939274470e-03 6.04379369396461988e-02 -1.47280519636897228e-01 -1.42019822493496678e-02 -1.40862643698270625e-02 3.43193229801791941e-02 3.30865219739744088e-03 1.71703137301635889e-02 -4.18247000202336891e-02 -4.03142330965122492e-03 2.84013766793336821e-02 -6.91687499272213430e-02 -6.66580738390779894e-03 4.89390949064563534e-03 2.87918813908899437e-02 2.65251064680964562e-04 2.05281517550071199e-03 1.20750085158812734e-02 1.11224171932663139e-04 3.02277142233090207e-03 1.77774632383747751e-02 1.63722924404008515e-04 2.97608341411592040e-03 1.75000643414473488e-02 1.61142622631198305e-04 3.56728551717501062e-03 2.09732366373861605e-02 1.93094644786909051e-04 -3.71632442098838002e-03 -2.18462568762160560e-02 -2.01102991107545033e-04 2.43389809229397139e-03 -5.92080177309931618e-03 -5.69951798700820723e-04 1.44995134429146480e-02 1.39563518623356361e-03 1.34329443972633675e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.79833000348711407e-18 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 9.22294648032090299e-19 0.00000000000000000e+00 -1.86771894252618642e-18 -2.34910470697964596e-19 -2.95445092002299980e-20 -4.75603353011430647e-19 0.00000000000000000e+00 0.00000000000000000e+00 -1.93710788156525876e-18 -2.43584088077848639e-19 0.00000000000000000e+00 1.54919176553467609e-22 3.64948931869505373e-23 5.56056822646583978e-25 -1.97953443733570477e-20 -2.23626913746707935e-20 -5.27921687965483745e-21 9.87264536986784423e-24 -2.60427081620102535e-23 -1.31865039141035429e-23 -6.76772463207037399e-20 -3.43594843687139160e-20 -8.67740877440054527e-21 -1.03859381619528693e-01 2.52314766280022584e-01 2.42563887034139732e-02 -1.14612932143155765e-22 -2.69870691194164438e-23 -4.10998521086606058e-25 -3.37733158457905168e-06 -9.68434278768968648e-07 2.12188129986114154e-06 -7.28394266323704983e-24 1.92055802727584491e-23 9.72033717096775629e-24 1.16161095172429305e-06 3.33032368512729238e-07 -7.29570735647793864e-07 -1.07665071340616112e-26 -4.12065113444913892e-29 1.69014225354238996e-28 -4.86688564800859199e-25 1.08872267502319023e-26 5.40029755286663093e-26 -1.66822439889124895e-02 3.79279855849453951e-02 -1.09668720108231713e-01 -7.09077404375997502e-03 8.55130576903905155e-03 2.90281997293919541e-03 8.66555940236016865e-05 3.46545512332374032e-04 2.87763482371105478e-04 4.13467528629723243e-03 5.11449233333069117e-03 1.52585650492719995e-04 6.09842661363620099e-04 5.06103362186671973e-04 7.26768971084910086e-03 7.54733192968500954e-03 2.25043435327971662e-04 8.98953256375927077e-04 7.45641288578970628e-04 1.07019555225087264e-02 1.02013387620519848e-02 3.04028948523483793e-04 1.21387729738672758e-03 1.00637726155277784e-03 1.44374727210050870e-02 1.29397613970773129e-04 6.62230939668935998e-07 5.25556866558733716e-06 -3.94677764384472601e-06 -2.13356102003463722e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +end +case cutoff_boundary 3 +types Fe Ge Fe +cell 9 3.00000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.00000000000000000e+01 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 3.00000000000000000e+01 +positions 9 1.00000000000000000e+01 1.00000000000000000e+01 1.00000000000000000e+01 1.59990000000000006e+01 1.00000000000000000e+01 1.00000000000000000e+01 1.60010000000000012e+01 1.00000000000000000e+01 1.00000000000000000e+01 +spins 9 8.00000000000000044e-01 2.00000000000000011e-01 -1.00000000000000006e-01 1.00000000000000006e-01 -6.99999999999999956e-01 4.00000000000000022e-01 -2.00000000000000011e-01 2.99999999999999989e-01 9.00000000000000022e-01 +potential 3 -2.41173890573297106e-01 1.96033810073553028e-01 -2.35343843814397380e-01 +forces 9 2.81283400046087367e-07 6.96414291103183066e-12 -7.10919084245109804e-12 2.20111399828398696e-01 1.92336998350165955e+00 3.19949872902054100e+00 -2.20111681111798796e-01 -1.92336998350862376e+00 -3.19949872901343202e+00 +virial 27 4.68723316390599029e-08 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.14920308787767943e-05 -3.84674000879642536e-03 -6.39899741538096489e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.53449684551036924e-04 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +mforces 9 -2.03158435938014179e-02 -5.07896151520073787e-03 2.53948077747545098e-03 0.00000000000000000e+00 0.00000000000000000e+00 -0.00000000000000000e+00 -2.36850593838235784e-04 -1.12620716866020498e-02 -3.56891279575153389e-02 +tau 9 3.97501641628945384e-12 -2.62600218887599551e-10 -4.93400306774592326e-10 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -5.70873869312755956e-04 -7.35099112595748085e-03 2.32346951547188077e-03 +descriptor 363 1.07844106097966972e-09 -3.89629016507981818e-09 -3.79888779998491183e-09 4.17289124927709505e-09 4.21724053107505758e-09 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 5.17500000000000071e-01 9.15277947533432856e-10 8.88227889498799120e-10 -6.42670201455065991e-10 -6.20050408685794334e-09 -6.01590155726109808e-09 4.35179536413859038e-09 -1.09215104282746409e-09 -1.05940892671830335e-09 7.66196421994481429e-10 -4.05020571937020265e-09 -3.92798420827825608e-09 2.84026843578128606e-09 -1.01204742216209174e-10 -9.81317275298206302e-11 7.09441131476371397e-11 8.27280136211851677e-17 7.71512204669131827e-17 3.99998225698682989e-17 1.28271828689834760e-18 1.19603799132641769e-18 6.19990283649996301e-19 8.52788184274361371e-17 7.95026762913834054e-17 4.12049722223564919e-17 4.44846376745883543e-17 4.14649070414445949e-17 2.14871913473979096e-17 6.03023912517387871e-17 5.62002455396231238e-17 2.91186447826627405e-17 -9.23849801917139384e-18 -8.60876552700650275e-18 -4.45975033250255552e-18 1.42903596220938897e-18 1.38407407937415949e-18 -9.99495928194127140e-19 1.34949192229865769e-18 -9.74434960564762505e-19 7.03584479198310040e-19 1.95802877685788734e-34 1.97086830969207387e-34 0.00000000000000000e+00 -1.99654737574563209e-34 0.00000000000000000e+00 0.00000000000000000e+00 2.03506597463337684e-34 2.04790550746756294e-34 0.00000000000000000e+00 -2.07358457352112159e-34 0.00000000000000000e+00 0.00000000000000000e+00 2.11210317240886635e-34 2.12494270524305245e-34 0.00000000000000000e+00 -4.30124354259322219e-34 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 1.98679827602409021e-09 1.92171400804415155e-09 -1.38591411625472365e-09 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -7.59908354567993241e-27 -6.09188885723812891e-27 2.11556353054854856e-29 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 2.61365472967911134e-27 2.09492396058226614e-27 -7.27398484256865243e-30 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -1.08630968761495514e-02 1.60250309639391825e-01 -2.09226623489906782e-01 -7.08586385203858055e-02 -1.94593082412113745e-03 5.31331996213305069e-03 8.68713848242109652e-05 2.19857025418428251e-03 1.00651833292420318e-04 2.71662288262761002e-02 9.36156374290992438e-03 1.52965621111492828e-04 3.86899234672725230e-03 1.77021180101833293e-04 4.77512036743543491e-02 1.38146319016248208e-02 2.25603841192456865e-04 5.70318131107298842e-03 2.60805026598926913e-04 7.03155030279205145e-02 1.86725244383688788e-02 3.04786045061214341e-04 7.70113714733205394e-03 3.52003372785370373e-04 9.48591268851934483e-02 3.20438779171653830e-04 6.64706122159245730e-07 -8.39826970398914875e-05 8.16435110757862315e-07 -3.59324630507203580e-03 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -4.28999228068277921e-02 6.25725018381955989e-02 -1.71013333754003100e-01 -7.96702376776866894e-02 -4.93146495298464882e-02 2.37825404042296799e-05 7.01075309879171374e-04 2.63868026665855793e-02 1.13105531870767999e-03 4.24528291553960484e-05 4.19025711888705070e-05 1.23447347407442212e-03 4.64348762007150903e-02 1.98924093808002704e-03 7.46210931416116949e-05 6.18346050513502810e-05 1.82068333771804387e-03 6.84484471399693234e-02 2.93074554959575021e-03 1.09882459435545980e-04 8.35786419920769228e-05 2.45970490076251281e-03 9.24275154856752518e-02 3.95556915327360727e-03 1.48236928034415505e-04 9.59585063271369891e-08 1.52391790119813020e-05 -3.49188111808185209e-03 -3.07549417152712105e-05 -2.21974411267062641e-07 7.05000000000000071e-01 -8.97526001982814313e-03 -4.40095934688019136e-02 8.14170591271878852e-03 -4.67711110080994419e-02 -2.29287468828079821e-01 4.24084461827330186e-02 4.60371125607484614e-03 2.25640945575733901e-02 -4.17252261061412839e-03 2.03674431038392660e-02 9.98063269642142786e-02 -1.84523644495384886e-02 -1.29014420461175767e-03 -6.32085383925543726e-03 1.16838766669535897e-03 4.70710594315001084e-03 1.12073258411576754e-01 3.79862004350840733e-03 7.29848404108208548e-05 1.73741742594304711e-03 5.88779491243901577e-05 4.85224309727412192e-03 1.15489086633921975e-01 3.91306819180637939e-03 2.53111241538752068e-03 6.02337489121221731e-02 2.04055094465372452e-03 3.43112002600444400e-03 8.16389501428226722e-02 2.76527895887585147e-03 6.83354563186208230e-04 1.62571131989367873e-02 5.50581594811965815e-04 1.37414081468487077e-04 6.72475284423840560e-04 -1.24165893292960274e-04 3.31295999814917213e-03 -6.11650107030213617e-04 1.12919967820698428e-04 -2.75568052182434046e-20 -1.10950022314069290e-19 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.84603070277444926e-20 -2.86410073907289100e-20 -1.15286831004011287e-19 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.95445092002299980e-20 -2.97252095632144154e-20 -1.19623639693953309e-19 0.00000000000000000e+00 0.00000000000000000e+00 -1.21792044038924320e-19 -3.06287113727154974e-20 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.30905367916306135e-02 -1.12849053643184219e-01 2.08089314756241262e-02 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 -2.01646995275909336e-04 -1.13530924236380631e-04 5.57458959194240394e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 6.93551557579704211e-05 3.90418569713814930e-05 -1.91672240562848996e-05 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 0.00000000000000000e+00 +end diff --git a/tests_pytest/integrate_temperature.cu b/tests_pytest/integrate_temperature.cu new file mode 100644 index 000000000..078ce0b51 --- /dev/null +++ b/tests_pytest/integrate_temperature.cu @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Exercise the production driver without advancing atoms or allocating GPU arrays. +#include +#include +#include +#include "integrate/ensemble.cuh" +#include "integrate/spin_integrator.cuh" +#define private public +#include "integrate/integrate.cuh" +#undef private +#include "force/force.cuh" +#include "model/atom.cuh" +#include +#include +#include + +class LatticeProbe final : public Ensemble +{ +public: + void compute1(double, int, int, const std::vector&, Box&, Atom&, + GPU_Vector&) override {} + void compute2(double, int, int, const std::vector&, Box&, Atom&, + GPU_Vector&, Force&) override {} +}; + +class SpinProbe final : public Spin_Integrator +{ +public: + double first = 0.0, second = 0.0; + void compute1(double, Atom&) override { first = temperature; } + void compute2(double, Atom&) override { second = temperature; } +}; + +int main() +{ + int failures = 0; + // A non-temperature-driving ensemble deliberately leaves its base target + // unusable. The driver's initial-temperature cache must never read it. + for (const auto type : {EnsembleType::NVT_BER, EnsembleType::MTTK}) { + for (const bool with_spin : {false, true}) { + if (with_spin && type == EnsembleType::MTTK) continue; + Integrate integrate; + integrate.type = type; + integrate.temperature = integrate.temperature1 = 300.0; + integrate.temperature2 = 600.0; + integrate.ensemble_.reset(new LatticeProbe); + integrate.ensemble_->temperature = std::numeric_limits::quiet_NaN(); + if (with_spin) integrate.spin_integrator.reset(new SpinProbe); + Atom atom; + Box box = {}; + Force force; + std::vector group; + GPU_Vector thermo; + for (int phase = 1; phase <= 2; ++phase) { + if (phase == 1) integrate.compute1(0.1, 2, 4, group, box, atom, thermo); + else integrate.compute2(0.1, 2, 4, group, box, atom, thermo, force); + if (integrate.get_temperature() != 300.0) { + fprintf(stderr, "Initial temperature changed in phase %d (type %d, spin %d).\n", + phase, int(type), int(with_spin)); + ++failures; + } + if (type == EnsembleType::NVT_BER && integrate.get_target_temperature_of_step() != 450.0) + ++failures; + } + if (with_spin) { + const auto& spin = static_cast(*integrate.spin_integrator); + if (spin.first != 450.0 || spin.second != 450.0) ++failures; + } + } + } + printf("Temperature cache and Spin target checks: %s\n", failures ? "FAIL" : "PASS"); + return failures ? 1 : 0; +} diff --git a/tests_pytest/response_fitness.cu b/tests_pytest/response_fitness.cu new file mode 100644 index 000000000..d02dcf906 --- /dev/null +++ b/tests_pytest/response_fitness.cu @@ -0,0 +1,101 @@ +// Fixed-parameter model loss probe, independent of the SNES lifecycle. +#include "spin_test_access.cuh" +#include "main_nep/nep_spin/spin_policy.cuh" +#include +#include +#include +static void check_response_loss() { + Dataset dataset; + Spin_Data magnetic; + magnetic.labels.resize(3); + dataset.Nc = dataset.N = 3; + dataset.Na_sum_cpu = {0, 1, 2}; + dataset.structures.resize(3); + magnetic.mforce_cpu.resize(9); + magnetic.mforce.resize(9); + std::vector mf(9, 0.0f); + for (int i = 0; i < 3; ++i) { + dataset.structures[i].num_atom = 1; + auto& frame = magnetic.labels[i]; + frame.has_spin_response = 1; + frame.spin_response_group = "rotation"; + frame.spin_response_coordinate = i - 1; + frame.spin_tangent_x = {1}; + frame.spin_tangent_y = frame.spin_tangent_z = {0}; + frame.mfx = {float(i - 1)}; + frame.mfy = frame.mfz = {0}; + mf[i] = i - 1; + } + magnetic.mforce.copy_from_host(mf.data()); + fitness_spin::ResponseLoss exact; + assert(exact.value() == 0); + exact.append(0, dataset, magnetic); + assert(exact.value() == 0); + for (int i = 0; i < 3; ++i) mf[i] += 1; + magnetic.mforce.copy_from_host(mf.data()); + fitness_spin::ResponseLoss shifted; + shifted.append(0, dataset, magnetic); + const double expected = 0.25 * (1.0 / std::sqrt(2.0 / 3.0) - 0.5); + assert(std::abs(shifted.value() - expected) < 1.0e-7); + + // Adding a much stronger, perfectly reproduced group must not hide the + // existing weak group's error; equal groups imply exactly half its loss. + for (int i = 0; i < 3; ++i) { + auto& frame = magnetic.labels[i]; + frame.spin_response_group = "strong"; + frame.mfx[0] = 100.0f * (i - 1); + mf[i] = frame.mfx[0]; + } + magnetic.mforce.copy_from_host(mf.data()); + shifted.append(0, dataset, magnetic); + assert(std::abs(shifted.value() - 0.5 * expected) < 1.0e-7); + + // A genuinely zero-response reference uses the documented finite floor. + fitness_spin::ResponseLoss zero; + for (int i = 0; i < 3; ++i) { + magnetic.labels[i].mfx[0] = 0.0f; + mf[i] = 0.0f; + } + magnetic.mforce.copy_from_host(mf.data()); + zero.append(0, dataset, magnetic); + assert(zero.value() == 0.0f); +} + +int main() { + check_response_loss(); + ParameterInput input; + NEP_Spin_Model model(input); + auto& p = *model.model_parameters; + model.prepare_data(); + model.prepare_training(); + std::mt19937 rng(9876); + std::vector mu(p.number_of_variables), sigma(mu.size()); + snes_spin::initialize_search(p, rng, mu, sigma); + std::vector scaler(p.dim); + p.q_scaler_gpu[0].copy_to_host(scaler.data()); + printf("SCALER"); for (float x : scaler) printf(" %.9g", x); printf("\n"); + printf("BASELINE"); for (double x : p.energy_reference) printf(" %.17g", x); printf("\n"); + std::vector population; + for (int i=0;inum_batches, population.data()); + for (int i=0;i +#include +static void check_initialization(Parameters&) {} + +static void check_initialization(Spin_Parameters& para) { + std::mt19937 rng(12345678), same_rng(12345678); + std::vector mu(para.number_of_variables), sigma(mu.size()); + auto same_mu = mu; + auto same_sigma = sigma; + snes_spin::initialize_search(para, rng, mu, sigma); + snes_spin::initialize_search(para, same_rng, same_mu, same_sigma); + assert(mu == same_mu && sigma == same_sigma && rng == same_rng); + // initial_para controls the scaler reference, never the SNES distribution. + const float saved_initial_para = para.initial_para; + para.initial_para = 0.5f; + same_rng.seed(12345678); + snes_spin::initialize_search(para, same_rng, same_mu, same_sigma); + assert(mu == same_mu && sigma == same_sigma && rng == same_rng); + para.initial_para = saved_initial_para; + for (std::size_t i = 0; i < mu.size(); ++i) { + assert(std::isfinite(mu[i]) && std::isfinite(sigma[i]) && sigma[i] > 0); + } + const int spin_offset = para.number_of_variables_ann + + para.number_of_variables_descriptor - para.number_of_variables_descriptor_spin - + para.number_of_variables_spin_projection; + for (int i = 0; i < para.number_of_variables_descriptor_spin; ++i) { + assert(sigma[spin_offset + i] == para.sigma0 * 0.1f); + } + std::vector types(mu.size(), para.num_types); + snes_spin::assign_variable_types(para, spin_offset, types); + for (int i = 0; i < para.number_of_variables_descriptor_spin; ++i) { + assert(types[spin_offset + i] == (i % (para.num_types * para.num_types)) / para.num_types); + } + assert(std::all_of(types.begin(), types.begin() + spin_offset, + [&](int type) { return type == para.num_types; })); + +} + +class SearchProbe : public SNES { +public: + using SNES::SNES; + const std::vector& center() const { return mu; } + void dump(Parameters& p) { output_mu_and_sigma(p, "restored.restart"); } +}; +template void dump_magnetic(NEP&, Dataset&, Dump&) {} +template void dump_magnetic(NEP_Spin_Model& model, Dataset& data, Dump& dump) { + dump("MF", model.magnetic(data).mforce, 3 * data.N); +} +template +void evaluate(Model& model, const std::vector& parameters, const char* filename) { + auto& p=*model.model_parameters; + auto& training=*model.training; + std::vector population; + for(int d=0;d::type; + std::vector host(count);values.copy_to_host(host.data());out< void probe(Model& model) { + auto& p=*model.model_parameters; + check_initialization(p); + Fitness fitness(model); + SearchProbe search(p,model);search.dump(p); + model.prepare_training(); + std::vector elite=search.center(); + if(std::ifstream("nep.txt").good()) model.read_model(elite.data()); + gpuSetDevice(0);p.q_scaler_gpu[0].copy_to_host(p.q_scaler_cpu.data()); + std::ofstream scalers("scaler.txt");scalers< +#include + +using Vec = std::array; + +static Vec spin(double x, bool changing_radius) +{ + const double r = changing_radius ? 4.0 + 0.1*x + 0.02*x*x : 4.154; + return {{r*std::cos(x), r*std::sin(x), 0.0}}; +} + +int main() +{ + const double pi = std::acos(-1.0); + // Uniform and nonuniform grids, including one-sided endpoints. + for (auto xs : {std::array{{-pi/2, -pi/3, -pi/6}}, + std::array{{-0.4, 0.0, 0.7}}}) { + for (bool radial : {false, true}) { + for (double x : xs) { + Vec tangent = {{0,0,0}}, cart = {{0,0,0}}; + const Vec current = spin(x, radial); + for (int j = 0; j < 3; ++j) { + const double a=xs[(j+1)%3], b=xs[(j+2)%3]; + const double w=(2*x-a-b)/((xs[j]-a)*(xs[j]-b)); + Vec delta; + assert(fitness_spin::rotation_displacement(current, spin(xs[j],radial), delta)); + for (int d=0; d<3; ++d) { + tangent[d] += w*delta[d]; + cart[d] += w*spin(xs[j],radial)[d]; + } + } + const double r=radial ? 4.0+0.1*x+0.02*x*x : 4.154; + const double dr=radial ? 0.1+0.04*x : 0.0; + Vec exact={{dr*std::cos(x)-r*std::sin(x), dr*std::sin(x)+r*std::cos(x),0}}; + for (int d=0;d<3;++d) assert(std::abs(tangent[d]-exact[d])<1e-12); + if (!radial) { + // Arbitrarily large longitudinal magnetic force must not create a + // response for a constant-magnitude rotation. + double projection=0; + for (int d=0;d<3;++d) projection += tangent[d]*current[d]; + assert(std::abs(projection)<1e-11); + if (x==xs.front()) { + double old_projection=0; + for (int d=0;d<3;++d) old_projection += cart[d]*current[d]; + assert(std::abs(old_projection)>0.01); // reproduces the old defect + } + } + } + } + } + Vec delta; + assert(!fitness_spin::rotation_displacement({{1,0,0}},{{-1,0,0}},delta)); + assert(fitness_spin::rotation_displacement({{0,0,0}},{{1,2,3}},delta)); + assert((delta==Vec{{1,2,3}})); + puts("rotation response analytic tests passed"); +} diff --git a/tests_pytest/spin_analytic_model.py b/tests_pytest/spin_analytic_model.py new file mode 100644 index 000000000..48976bf0b --- /dev/null +++ b/tests_pytest/spin_analytic_model.py @@ -0,0 +1,19 @@ +"""Small analytic potential for independent Spin runtime tests.""" +from spin_fixtures import FIXTURE + +def analytic_model(onsite): + """E_i = tanh(0.1 |S_i|^2), or zero, using the actual Spin3 ANN path.""" + lines = (FIXTURE / 'nep4_spin3_o3c2_uniform.nep').read_text().splitlines() + start = next(i+1 for i, s in enumerate(lines) if s.startswith('ANN ')) + # This fixture has 2 types, 30 neurons, 360 structural, 72 spin and 16 projection weights. + dim, remainder = divmod(len(lines)-start-569, 61) + assert remainder == 0 and dim > 30 + values = [0.0] * (len(lines)-start) + values[-dim:] = [1.0] * dim + if onsite: + for t in range(2): + offset = t * 30 * (dim+2) + values[offset+30] = 0.1 # 5 radial + 5 * (4 + q222) structural channels + values[offset+30*dim+30] = 1.0 + lines[2] = 'spin_baseline 0 0' + return '\n'.join(lines[:start] + [str(x) for x in values]) + '\n' diff --git a/tests_pytest/spin_checkpoint_helpers.py b/tests_pytest/spin_checkpoint_helpers.py new file mode 100644 index 000000000..11cbb70e1 --- /dev/null +++ b/tests_pytest/spin_checkpoint_helpers.py @@ -0,0 +1,17 @@ +"""Checkpoint trajectory parser shared by Spin integration tests.""" +import re +import numpy as np + +def frames(path): + lines=path.read_text().splitlines();n=int(lines[0]);result=[] + # Keep all post-checkpoint steps, not just the endpoint. + for start in range(0,len(lines),n+2): + h=lines[start+1];props=re.search(r'Properties=([^\s]+)',h)[1].split(':') + raw=[line.split() for line in lines[start+2:start+2+n]];offset=0;v={} + for i in range(0,len(props),3): + key,kind,width=props[i],props[i+1],int(props[i+2]);key={'forces':'force','energy_atom':'potential'}.get(key,key) + if kind!='S':v[key]=np.array([r[offset:offset+width] for r in raw],float) + offset+=width + v['cell']=np.array(re.search(r'Lattice="([^"]+)"',h)[1].split(),float) + v['time']=np.array([float(re.search(r'Time=([^\s]+)',h)[1])]);result.append(v) + return result diff --git a/tests_pytest/spin_fixtures.py b/tests_pytest/spin_fixtures.py new file mode 100644 index 000000000..bae60f9bf --- /dev/null +++ b/tests_pytest/spin_fixtures.py @@ -0,0 +1,95 @@ +"""Frozen Spin model/oracle loaders; independent of runtime and integrators.""" +import hashlib +from pathlib import Path + +FIXTURE = Path(__file__).parent / "fixtures" / "nep_spin3" + +def selective_type_model(): + """Return the production C=2 fixture with Fe DOFs and Fe/Ge environments.""" + return (FIXTURE / "nep4_spin3_o3c2_uniform.nep").read_text() + +def write_xyz(path, case): + lattice = " ".join(f"{value:.17g}" for value in case["cell"]) + lines = [ + str(len(case["types"])), + f'Lattice="{lattice}" ' + 'Properties=species:S:1:pos:R:3:spin:R:3 pbc="T T T"', + ] + for symbol, position, spin in zip( + case["types"], case["positions"], case["spins"]): + values = position + spin + lines.append(symbol + " " + " ".join(f"{value:.17g}" for value in values)) + path.write_text("\n".join(lines) + "\n") + +def reshape(values, width): + if len(values) % width: + raise ValueError(f"cannot reshape {len(values)} values with width {width}") + return [values[index:index + width] for index in range(0, len(values), width)] + +def read_text_oracle(path, model): + lines = path.read_text().splitlines() + if lines[0] != "spin3_oc_oracle_v1": + raise ValueError(f"{path}: unsupported oracle format") + model_sha256 = lines[1].split() + if model_sha256[:1] != ["model_sha256"]: + raise ValueError(f"{path}: missing model hash") + actual_hash = hashlib.sha256(model.encode()).hexdigest() + if actual_hash != model_sha256[1]: + raise ValueError( + f"{path}: model hash mismatch: {actual_hash} != {model_sha256[1]}") + descriptor_dim = int(lines[2].split()[1]) + spin_descriptor_dim = int(lines[3].split()[1]) + if descriptor_dim - spin_descriptor_dim != 30 or spin_descriptor_dim not in (55, 91): + raise ValueError( + f"{path}: unexpected descriptor dimensions " + f"{descriptor_dim}/{spin_descriptor_dim}") + + cases = {} + current = None + for line in lines[4:]: + fields = line.split() + if fields[0] == "case": + current = {"atom_count": int(fields[2])} + cases[fields[1]] = current + elif fields[0] == "types": + current["types"] = fields[1:] + elif fields[0] == "end": + current = None + else: + if current is None: + raise ValueError(f"{path}: data outside a case: {fields[0]}") + count = int(fields[1]) + values = [float(value) for value in fields[2:]] + if len(values) != count: + raise ValueError( + f"{path}: {fields[0]} count mismatch: {len(values)} != {count}") + current[fields[0]] = values + + for name, case in cases.items(): + atom_count = case.pop("atom_count") + if len(case["types"]) != atom_count: + raise ValueError(f"{path}: {name} type count mismatch") + case["positions"] = reshape(case["positions"], 3) + case["spins"] = reshape(case["spins"], 3) + case["force"] = reshape(case.pop("forces"), 3) + case["mforce"] = reshape(case.pop("mforces"), 3) + case["atom_virial"] = reshape(case.pop("virial"), 9) + case.pop("tau") + case.pop("descriptor") + return {"cases": cases} + +def load_fixture(name): + fixtures = { + "o3c2_uniform": ("nep4_spin3_o3c2_uniform.nep", "spin3_o3c2_uniform_oracle.txt"), + "o3c2_typewise": ("nep4_spin3_o3c2_uniform.nep", "spin3_o3c2_typewise_oracle.txt"), + "o3c3_uniform": ("nep4_spin3_o3c3_uniform.nep", "spin3_o3c3_uniform_oracle.txt"), + } + if name not in fixtures: + raise ValueError(f"unknown fixture: {name}") + model_name, oracle_name = fixtures[name] + model = (FIXTURE / model_name).read_text() + if name == "o3c2_typewise": + # Identical parameters; the frozen oracle hash also checks this header edit. + model = model.replace("spin_cutoff 6.0\n", "spin_cutoff 4.0 6.0\n", 1) + oracle = read_text_oracle(FIXTURE / oracle_name, model) + return model, oracle diff --git a/tests_pytest/spin_mforce_split.cu b/tests_pytest/spin_mforce_split.cu new file mode 100644 index 000000000..e6fec3416 --- /dev/null +++ b/tests_pytest/spin_mforce_split.cu @@ -0,0 +1,122 @@ +// Independent numerical oracle for the native Spin3 magnetic-loss reductions. +// Link against the NEP objects except main_nep/main.o; run with a valid nep.in. +#include "main_nep/nep_spin/spin_data.cuh" +#include "main_nep/parameter_input.cuh" +#include +#include +#include +#include +#include + +template void upload(GPU_Vector& target, const std::vector& values) +{ + target.resize(values.size()); + target.copy_from_host(values.data()); +} + +int main() +{ + ParameterInput input; + Spin_Parameters para(input); + assert(para.num_types == 2 && para.spin_dof_type_active[0] && !para.spin_dof_type_active[1]); + Dataset data; + Spin_Data mag; + // Unequal active counts, an inactive atom, an unlabeled frame, and an + // inactive-only frame; all errors are nonzero so masking failures are visible. + const std::vector sizes{2, 3, 1, 1}, starts{0, 2, 5, 6}; + const std::vector types{0, 1, 0, 0, 0, 0, 1}; + const std::vector labeled{1, 1, 0, 1}; + const std::vector> axes{ + {0, 0, 2}, {1, 0, 0}, {0, 0, 0}, {1e-30, 0, 0}, {1, 2, 2}, {0, 0, 1}, {1, 0, 0}}; + const std::vector> errors{ + {3, 4, 5}, {70, 80, 90}, {0, 0, 6}, {7, 0, 0}, {2, -1, 3}, {60, 70, 80}, {80, 90, 100}}; + data.N = 7; data.Nc = 4; + data.structures.resize(4); mag.labels.resize(4); + data.weight_cpu = {2, .5f, 3, 4}; + data.error_cpu.resize(4); data.error_gpu.resize(4); + data.has_type.assign(3 * 4, 0); + std::vector spins(21); + std::vector predicted(21), reference(21, .25f); + for (int c = 0; c < 4; ++c) { + auto& frame = data.structures[c]; + frame.num_atom = sizes[c]; + for (int a = starts[c]; a < starts[c] + sizes[c]; ++a) { + frame.type.push_back(types[a]); + data.has_type[types[a] * 4 + c] = data.has_type[2 * 4 + c] = 1; + mag.labels[c].sx.push_back(axes[a][0]); + mag.labels[c].sy.push_back(axes[a][1]); + mag.labels[c].sz.push_back(axes[a][2]); + for (int d = 0; d < 3; ++d) { + spins[d * 7 + a] = axes[a][d]; + predicted[d * 7 + a] = reference[d * 7 + a] + errors[a][d]; + } + } + } + upload(data.Na, sizes); upload(data.Na_sum, starts); upload(data.type, types); + upload(mag.spin, spins); upload(mag.mforce, predicted); upload(mag.mforce_ref_gpu, reference); + upload(mag.has_mforce_gpu, labeled); mag.has_mforce_cpu = labeled; + upload(mag.spin_dof_type_active_gpu, para.spin_dof_type_active); + for (bool weighted : {false, true}) { + const auto torque = mag.get_rmse_tau(para, data, weighted, 0); + const auto full = mag.get_rmse_mforce(para, data, weighted, 0); + const auto parallel = mag.get_rmse_mforce_parallel(para, data, weighted, 0); + const auto perp = mag.get_rmse_mforce_perp(para, data, weighted, 0); + for (int type = 0; type <= 2; ++type) { + double p = 0, t = 0, raw = 0, cross2 = 0; + int count = 0, torque_count = 0; + for (int c = 0; c < 4; ++c) { + if (!labeled[c] || !data.has_type[type * 4 + c]) continue; + const double w = weighted ? data.weight_cpu[c] * data.weight_cpu[c] : 1; + for (int a = starts[c]; a < starts[c] + sizes[c]; ++a) { + if (types[a] != 0) continue; + const auto& e = errors[a]; const auto& s = axes[a]; + const double norm2 = e[0]*e[0] + e[1]*e[1] + e[2]*e[2]; + const double length = std::hypot(std::hypot(s[0], s[1]), s[2]); + const double dot = length == 0 ? 0 : (e[0]*s[0] + e[1]*s[1] + e[2]*s[2]) / length; + const double projected = length == 0 ? norm2 / 3 : dot * dot; + // Torque uses two transverse degrees of freedom per nonzero spin. + if (length * length > 1e-20) { + for (int d = 0; d < 3; ++d) { + double cross = s[(d+1)%3]*e[(d+2)%3] - s[(d+2)%3]*e[(d+1)%3]; + cross2 += w * cross * cross; + } + ++torque_count; + } + p += w * projected; t += w * (norm2 - projected); raw += w * norm2; + ++count; + } + } + assert(count > 0); + const double expected_torque = torque_count ? std::sqrt(cross2 / (2 * torque_count)) : 0; + assert(std::abs(torque[type] - expected_torque) < 2e-6); + assert(std::abs(parallel[type] - std::sqrt(p / count)) < 2e-6); + assert(std::abs(perp[type] - std::sqrt(t / (2 * count))) < 2e-6); + assert(std::abs(full[type] - std::sqrt(raw / (3 * count))) < 2e-6); + assert(std::abs(3 * full[type]*full[type] - parallel[type]*parallel[type] - 2 * perp[type]*perp[type]) < 3e-5); + } + } + // Simultaneously rotate spins and errors: the projected losses must be invariant. + const auto p0 = mag.get_rmse_mforce_parallel(para, data, false, 0); + const auto t0 = mag.get_rmse_mforce_perp(para, data, false, 0); + for (int a = 0; a < 7; ++a) { + spins[a] = -axes[a][1]; spins[7+a] = axes[a][0]; + predicted[a] = reference[a] - errors[a][1]; + predicted[7+a] = reference[7+a] + errors[a][0]; + } + upload(mag.spin, spins); upload(mag.mforce, predicted); + const auto p1 = mag.get_rmse_mforce_parallel(para, data, false, 0); + const auto t1 = mag.get_rmse_mforce_perp(para, data, false, 0); + for (int type = 0; type <= 2; ++type) { + assert(std::abs(p0[type]-p1[type]) < 1e-6); + assert(std::abs(t0[type]-t1[type]) < 1e-6); + } + // No labels / no active atoms must yield finite zeros, not 0/0. + mag.has_mforce_cpu.assign(4, 0); upload(mag.has_mforce_gpu, mag.has_mforce_cpu); + for (auto value : mag.get_rmse_mforce_parallel(para, data, false, 0)) assert(value == 0); + for (auto value : mag.get_rmse_tau(para, data, false, 0)) assert(value == 0); + mag.has_mforce_cpu = labeled; upload(mag.has_mforce_gpu, labeled); + para.spin_dof_type_active.assign(2, 0); upload(mag.spin_dof_type_active_gpu, para.spin_dof_type_active); + for (auto value : mag.get_rmse_mforce_perp(para, data, true, 0)) assert(value == 0); + for (auto value : mag.get_rmse_tau(para, data, true, 0)) assert(value == 0); + puts("spin magnetic split numerical oracle passed"); +} diff --git a/tests_pytest/spin_model_format.py b/tests_pytest/spin_model_format.py new file mode 100644 index 000000000..a98de1594 --- /dev/null +++ b/tests_pytest/spin_model_format.py @@ -0,0 +1,38 @@ +"""Independent legacy-to-block fixture conversion for Spin3 compatibility tests.""" + + +def block_model(legacy, *, legacy_name=False): + lines = legacy.splitlines() + header = lines[0].split() + count = int(lines[1].split()[2]) + fields = dict((line.split()[0], line.split()[1:]) for line in lines[2:2 + count]) + cursor = 2 + count + while not lines[cursor].startswith('ANN '): + tokens = lines[cursor].split() + fields[tokens[0]] = tokens[1:] + cursor += 1 + fields['ann'] = lines[cursor].split()[1:] + fields['energy_reference'] = fields.pop('spin_baseline') + fields['spin_mode' if legacy_name else 'spin_version'] = ['3' if legacy_name else '1'] + C = int(fields['spin_compress'][0]) + T = int(header[1]) + nr, na = map(int, fields['n_max']) + br, ba = map(int, fields['basis_size']) + descriptor_count = T * T * ((nr + 1) * (br + 1) + (na + 1) * (ba + 1) + C * 9) + 4 * C * C + body = lines[cursor + 1:] + neurons = int(fields['ann'][0]) + dim, remainder = divmod(len(body) - descriptor_count - 2 * neurons * T - 1, neurons * T + 1) + assert remainder == 0 + ann_count = (dim + 2) * neurons * T + 1 + values = body[:-dim] + offset = ann_count + for basis_count in ((nr + 1) * (br + 1), (na + 1) * (ba + 1)): + old = values[offset:offset + T * T * basis_count] + values[offset:offset + len(old)] = [old[b * T * T + pair] + for pair in range(T * T) for b in range(basis_count)] + offset += len(old) + result = ['nep ' + ' '.join(header[1:]), 'format_version 1', + 'model nep_spin3' if legacy_name else 'model nep_spin'] + result += [key + ' ' + ' '.join(value) for key, value in fields.items()] + result += [f'@ parameters {len(values)}', *values, f'@ q_scaler {dim}', *body[-dim:]] + return '\n'.join(result) + '\n' diff --git a/tests_pytest/spin_runtime_helpers.py b/tests_pytest/spin_runtime_helpers.py new file mode 100644 index 000000000..d704ba7c2 --- /dev/null +++ b/tests_pytest/spin_runtime_helpers.py @@ -0,0 +1,52 @@ +"""Fixed-spin model evaluation helpers.""" +import os, shutil, subprocess +from pathlib import Path +from spin_fixtures import FIXTURE +ROOT = Path(__file__).resolve().parents[1] +GPUMD = Path(os.environ.get("GPUMD_COMMAND", ROOT / "src/gpumd")) + +def base_model(): + lines = (FIXTURE / "model_large_box.xyz").read_text().splitlines() + lines[1] = lines[1].replace( + "Properties=species:S:1:pos:R:3:spin:R:3", + "Properties=species:S:1:pos:R:3:vel:R:3:spin:R:3") + for index in range(2, len(lines)): + fields = lines[index].split() + lines[index] = " ".join(fields[:4] + ["0", "0", "0"] + fields[4:]) + return "\n".join(lines) + "\n" + +def run_case(root, name, run_input, model_text=None): + case = root / name + case.mkdir() + shutil.copy(FIXTURE / "nep4_spin3_o3c2_uniform.nep", case / "nep.txt") + (case / "model.xyz").write_text(model_text or base_model()) + (case / "run.in").write_text(run_input) + result = subprocess.run( + [str(GPUMD)], cwd=case, capture_output=True, text=True, check=False) + return case, result + +def read_last_frame(path): + lines = path.read_text().splitlines() + number_of_atoms = int(lines[0]) + values = [ + [float(value) for value in line.split()[1:]] + for line in lines[-number_of_atoms:] + ] + return { + "spin": [row[4:7] for row in values], + "mforce": [row[7:10] for row in values], + } + +def evaluate(root, name, model_text): + case, result = run_case( + root, + name, + "potential nep.txt\n" + "ensemble nve\n" + "time_step 0\n" + "dump_xyz 1 state.xyz mass spin mforce\n" + "run 1\n", + model_text) + if result.returncode != 0: + raise AssertionError(result.stdout + result.stderr) + return read_last_frame(case / "state.xyz") diff --git a/tests_pytest/spin_test_access.cuh b/tests_pytest/spin_test_access.cuh new file mode 100644 index 000000000..19b8d98f9 --- /dev/null +++ b/tests_pytest/spin_test_access.cuh @@ -0,0 +1,20 @@ +#pragma once +// Test-only inspection of model-owned buffers; do not expose these through Potential. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define private public +#include "main_nep/nep_spin/nep_spin.cuh" +#include "main_nep/nep/nep.cuh" +#undef private +#include "main_nep/parameter_input.cuh" +#include "main_nep/nep_spin/spin_init.cuh" diff --git a/tests_pytest/test_spin_lattice_restart.py b/tests_pytest/test_spin_lattice_restart.py new file mode 100644 index 000000000..5d4bced30 --- /dev/null +++ b/tests_pytest/test_spin_lattice_restart.py @@ -0,0 +1,67 @@ +"""Spin lattice checkpoint ownership, run-block lifetime and constrained restart.""" +import os +from pathlib import Path +import re +import shutil +import subprocess + +import numpy as np +import pytest + +from spin_analytic_model import analytic_model +from validate_spin_multigpu import structure, write_xyz +from spin_checkpoint_helpers import frames + +GPUMD = Path(os.environ.get('GPUMD_COMMAND', Path(__file__).parents[1] / 'src/gpumd')).resolve() + + +def prepare(path, source=None): + path.mkdir() + (path / 'nep.txt').write_text(analytic_model(False)) + if source is not None: + shutil.copyfile(source, path / 'model.xyz') + else: + pos, spin, cell, velocity = structure((4, 4, 4)) + write_xyz(path / 'model.xyz', pos, spin, cell, velocity) + return path + + +def run(path, commands): + (path / 'run.in').write_text('potential nep.txt\ntime_step 0.1\n' + commands) + result = subprocess.run([str(GPUMD)], cwd=path, capture_output=True, text=True) + assert result.returncode == 0, result.stdout + result.stderr + return result.stdout + + +def state(path, kind): + header = (path / 'restart.xyz').read_text().splitlines()[1] + payload = re.search(kind + r'_state=([^\s]+)', header) + return np.array(payload[1].split(','), float) if payload else None + + +@pytest.mark.parametrize('mode', ['tspin']) +@pytest.mark.parametrize('kind', ['nhc', 'mttk']) +def test_spin_lattice_checkpoint_consumed_once(tmp_path, mode, kind): + prefix = 'nvt_' + mode + ' 300 350 100' if kind == 'nhc' else ( + 'npt_' + mode + ' temp 300 350 iso 0 .01 tperiod 100 pperiod 1000') + options = {'tspin': ' mass_factor 1'}[mode] + ensemble = prefix + options + ' seed 731' + original = prepare(tmp_path / 'original') + run(original, f'ensemble {ensemble}\ndump_restart 6\nrun 10\n') + assert np.array_equal(state(original, kind)[:3], [1, 6, 10]) + resumed = prepare(tmp_path / 'resumed', original / 'restart.xyz') + log = run(resumed, f'ensemble {ensemble}\ndump_restart 4\nrun 4\n' + f'ensemble {ensemble}\ndump_restart 3\nrun 3\n') + # A new run block creates a fresh lattice protocol, without consuming the old + # endpoint again or resetting the execution clock to the loaded checkpoint. + assert log.count('Restored ') == 1 + assert np.array_equal(state(resumed, kind)[:3], [1, 3, 3]) + header = (resumed / 'restart.xyz').read_text().splitlines()[1] + clock = float(re.search(kind + r'_time=([^\s]+)', header)[1]) + assert abs(clock - 13 * .1 / 10.18051) < 1e-12 + switched = prepare(tmp_path / 'switched', original / 'restart.xyz') + other = 'nvt_tspin 300 350 100 mass_factor 1 seed 731' if kind == 'mttk' else ( + 'npt_tspin temp 300 350 iso 0 .01 mass_factor 1 seed 731') + log = run(switched, f'ensemble {other}\ndump_restart 3\nrun 3\n') + assert state(switched, kind) is None + assert 'Discarding ' in log and 'Restored ' not in log diff --git a/tests_pytest/test_spin_model_format.py b/tests_pytest/test_spin_model_format.py new file mode 100644 index 000000000..eaf67798d --- /dev/null +++ b/tests_pytest/test_spin_model_format.py @@ -0,0 +1,101 @@ +"""Exercise the production Spin3 block codec without CUDA.""" +import shutil +import subprocess +from pathlib import Path + +import pytest +from spin_model_format import block_model +from spin_fixtures import load_fixture + +ROOT = Path(__file__).resolve().parents[1] +FIXTURES = Path(__file__).parent / 'fixtures' / 'nep_spin3' + + +@pytest.fixture(scope='module') +def codec(tmp_path_factory): + compiler = shutil.which('c++') + if not compiler: + pytest.skip('C++ compiler unavailable') + root = tmp_path_factory.mktemp('spin-codec') + main = root / 'main.cpp' + main.write_text('''#include "utilities/nep_spin_model_file.cuh" +#include +int main(int argc, char** argv) { + try { + if (!is_nep_spin_model_file(argv[1])) return 2; + std::cout << read_nep_spin_model_input(argv[1]); + } + catch (const std::exception& error) { std::cerr << error.what(); return 1; } +} +''') + binary = root / 'codec' + subprocess.run([compiler, '-std=c++14', '-pedantic-errors', '-I' + str(ROOT / 'src'), '-x', 'c++', + str(main), str(ROOT / 'src/utilities/nep_spin_model_file.cu'), + str(ROOT / 'src/utilities/nep_file.cu'), '-o', str(binary)], check=True) + return binary + + +@pytest.mark.parametrize('fixture', ['o3c2_uniform', 'o3c2_typewise', 'o3c3_uniform']) +@pytest.mark.parametrize('legacy_name', [False, True], ids=['versioned', 'old-block']) +def test_legacy_and_blocks(codec, tmp_path, fixture, legacy_name): + legacy, _ = load_fixture(fixture) + old = tmp_path / "legacy.nep" + old.write_text(legacy) + assert subprocess.check_output([codec, old], text=True) == legacy + new = tmp_path / 'new.nep' + new.write_text(block_model(legacy, legacy_name=legacy_name)) + normalized = subprocess.check_output([codec, new], text=True) + old_lines, new_lines = legacy.splitlines(), normalized.splitlines() + old_start = next(i + 1 for i, x in enumerate(old_lines) if x.startswith('ANN ')) + new_start = next(i + 1 for i, x in enumerate(new_lines) if x.startswith('ANN ')) + assert [float(x) for x in new_lines[new_start:]] == pytest.approx( + [float(x) for x in old_lines[old_start:]], rel=6e-8, abs=1e-15) + old_ref = next(x.split()[1:] for x in old_lines if x.startswith('spin_baseline ')) + new_ref = next(x.split()[1:] for x in new_lines if x.startswith('spin_baseline ')) + assert new_ref == old_ref + + +@pytest.mark.parametrize('edit', [ + lambda s: s.replace('energy_reference', 'unknown_reference'), + lambda s: s.replace('spin_version 1', 'spin_version 2'), + lambda s: s.replace('spin_version 1', 'spin_version 0'), + lambda s: s.replace('spin_version 1', 'spin_version -1'), + lambda s: s.replace('spin_version 1', 'spin_version 1.0'), + lambda s: s.replace('spin_version 1', 'spin_version 1 2'), + lambda s: s.replace('spin_version 1\n', ''), + lambda s: s.replace('spin_version 1', 'spin_version 1\nspin_version 1'), + lambda s: s + 'spin_mode 3\n', + lambda s: s.replace('model nep_spin\n', 'model nep_spin3\n'), + lambda s: s.replace('format_version 1', 'format_version 2'), + lambda s: s + '@ unexpected 1\n1\n', + lambda s: s.replace('spin_scaler 1', 'spin_scaler 1\nspin_scaler 1'), +]) +def test_reject_invalid_blocks(codec, tmp_path, edit): + model = block_model(next(FIXTURES.glob('*.nep')).read_text()) + path = tmp_path / 'invalid.nep' + path.write_text(edit(model)) + result = subprocess.run([codec, path], capture_output=True, text=True) + assert result.returncode != 0 + + +@pytest.mark.parametrize('edit', [ + lambda s: s.replace('spin_mode 3', 'spin_mode 2'), + lambda s: s.replace('spin_mode 3\n', ''), + lambda s: s + 'spin_version 1\n', +]) +def test_reject_invalid_old_blocks(codec, tmp_path, edit): + legacy, _ = load_fixture('o3c2_uniform') + path = tmp_path / 'invalid-old.nep' + path.write_text(edit(block_model(legacy, legacy_name=True))) + result = subprocess.run([codec, path], capture_output=True, text=True) + assert result.returncode != 0 + + +def test_reject_flexible_zbl(codec, tmp_path): + legacy, _ = load_fixture('o3c2_uniform') + model = block_model(legacy).replace('model nep_spin\n', 'model nep_spin\nzbl 0 0\n') + path = tmp_path / 'flexible-zbl.nep' + path.write_text(model) + result = subprocess.run([codec, path], capture_output=True, text=True) + assert result.returncode != 0 + assert 'NEP-spin does not support flexible ZBL' in result.stderr diff --git a/tests_pytest/test_spin_tspin.py b/tests_pytest/test_spin_tspin.py new file mode 100644 index 000000000..fa3b8b420 --- /dev/null +++ b/tests_pytest/test_spin_tspin.py @@ -0,0 +1,504 @@ +"""TSPIN parser, initialization, splitting, and restart regression tests.""" + +import json +import math +import os +import re +import shutil +import subprocess +from pathlib import Path + +import numpy as np +import pytest +from spin_runtime_helpers import base_model as _model_with_zero_lattice_velocity + +from spin_fixtures import load_fixture, selective_type_model + + +FIXTURE = Path(__file__).parent / "fixtures" / "nep_spin3" +GPUMD = Path(os.environ.get("GPUMD_COMMAND", Path(__file__).parents[1] / "src" / "gpumd")) +K_B = 8.617343e-5 +PI = 3.14159265358979 +TIME_UNIT_CONVERSION = 1.018051e1 +MASK64 = (1 << 64) - 1 + + +def _prepare_case(case_dir, run_input, model_text=None): + case_dir.mkdir() + shutil.copy(FIXTURE / "nep4_spin3_o3c2_uniform.nep", case_dir / "nep.txt") + (case_dir / "model.xyz").write_text( + model_text if model_text is not None else _model_with_zero_lattice_velocity()) + (case_dir / "run.in").write_text(run_input) + return subprocess.run( + [str(GPUMD)], + cwd=case_dir, + capture_output=True, + text=True, + check=False) + + +def _read_spin_frame(path): + lines = path.read_text().splitlines() + number_of_atoms = int(lines[0]) + values = np.array([ + [float(value) for value in line.split()[1:]] + for line in lines[-number_of_atoms:] + ]) + return { + "mass": values[:, 3], + "spin": values[:, 4:7], + "mforce": values[:, 7:10], + "spin_velocity": values[:, 10:13] * TIME_UNIT_CONVERSION, + } + + +def _read_last_lattice(path): + comments = [ + line for line in path.read_text().splitlines() + if re.search(r'\bLattice="', line) + ] + values = re.search(r'Lattice="([^"]+)"', comments[-1]).group(1) + return np.array([float(value) for value in values.split()]) + + +def _splitmix64(value): + value = (value + 0x9E3779B97F4A7C15) & MASK64 + value = ((value ^ (value >> 30)) * 0xBF58476D1CE4E5B9) & MASK64 + value = ((value ^ (value >> 27)) * 0x94D049BB133111EB) & MASK64 + return (value ^ (value >> 31)) & MASK64 + + +def _uniform_01(state): + state = _splitmix64(state) + return state, (state >> 11) / 9007199254740992.0 + + +def _gaussian(seed, atom_index, component): + state = seed + state ^= (atom_index * 0xD1B54A32D192ED03) & MASK64 + state ^= (component * 0x9E3779B97F4A7C15) & MASK64 + state, u1 = _uniform_01(state) + while u1 <= 0.0: + state, u1 = _uniform_01(state) + state, u2 = _uniform_01(state) + return math.sqrt(-2.0 * math.log(u1)) * math.cos(2.0 * PI * u2) + + +def _initial_spin_velocity(seed, mass, temperature, mass_factor): + number_of_atoms = len(mass) + velocity = np.array([ + [0.5 * _gaussian(seed, atom + 1, component) for component in range(3)] + for atom in range(number_of_atoms) + ]) + twice_kinetic_energy = np.sum( + mass[:, None] * mass_factor * velocity * velocity) + target = 3.0 * number_of_atoms * K_B * temperature + return velocity * math.sqrt(target / twice_kinetic_energy) + + +def _nhc(position, velocity, mass, twice_kinetic_energy, + thermal_energy, degrees_of_freedom, half_time_step): + weights = ( + 0.784513610477560, + 0.235573213359357, + -1.17767998417887, + 1.31518632068391, + -1.17767998417887, + 0.235573213359357, + 0.784513610477560, + ) + factor = 1.0 + for weight in weights: + dt2 = half_time_step * weight / 4.0 + dt4 = dt2 * 0.5 + dt8 = dt4 * 0.5 + for _ in range(4): + acceleration = velocity[-2] ** 2 / mass[-2] - thermal_energy + velocity[-1] += dt4 * acceleration + for index in range(len(velocity) - 2, -1, -1): + scale = math.exp(-dt8 * velocity[index + 1] / mass[index + 1]) + if index == 0: + acceleration = ( + twice_kinetic_energy - + degrees_of_freedom * thermal_energy) + else: + acceleration = ( + velocity[index - 1] ** 2 / mass[index - 1] - + thermal_energy) + velocity[index] = scale * ( + scale * velocity[index] + dt4 * acceleration) + for index in range(len(position) - 1, -1, -1): + position[index] += dt2 * velocity[index] / mass[index] + local_factor = math.exp(-dt2 * velocity[0] / mass[0]) + twice_kinetic_energy *= local_factor * local_factor + factor *= local_factor + for index in range(len(velocity) - 1): + scale = math.exp(-dt8 * velocity[index + 1] / mass[index + 1]) + if index == 0: + acceleration = ( + twice_kinetic_energy - + degrees_of_freedom * thermal_energy) + else: + acceleration = ( + velocity[index - 1] ** 2 / mass[index - 1] - + thermal_energy) + velocity[index] = scale * ( + scale * velocity[index] + dt4 * acceleration) + acceleration = velocity[-2] ** 2 / mass[-2] - thermal_energy + velocity[-1] += dt4 * acceleration + return factor + + +@pytest.mark.parametrize("pressure_control", [False, True], ids=["nvt", "npt"]) +def test_tspin_one_step_matches_public_formula_and_gpumd_nhc_oracle( + tmp_path, pressure_control): + # Obtain the initial magnetic force from a fixed-spin run. This keeps the + # integrator oracle independent of the NEP_Spin derivative implementation. + static_model = _model_with_zero_lattice_velocity() + lines = static_model.splitlines() + lines[1] = lines[1].replace(":spin:R:3", ":spin:R:3:spin_vel:R:3") + for index in range(2, len(lines)): + lines[index] += " 0 0 0" + static_result = _prepare_case( + tmp_path / "static", + "potential nep.txt\n" + "ensemble nve\n" + "time_step 0\n" + "dump_xyz 1 state.xyz mass spin mforce spin_velocity\n" + "run 1\n", + "\n".join(lines) + "\n") + assert static_result.returncode == 0, static_result.stdout + static_result.stderr + initial = _read_spin_frame(tmp_path / "static" / "state.xyz") + + temperature = 300.0 + coupling = 100.0 + mass_factor = 1.5 + seed = 24681357 + time_step_fs = 0.1 + ensemble = ( + f"ensemble npt_tspin temp {temperature} {temperature} iso 0 0 " + f"tperiod {coupling} pperiod 1000 mass_factor {mass_factor} seed {seed}\n" + if pressure_control else + f"ensemble nvt_tspin {temperature} {temperature} {coupling} " + f"mass_factor {mass_factor} seed {seed}\n" + ) + result = _prepare_case( + tmp_path / "tspin", + "potential nep.txt\n" + + ensemble + + f"time_step {time_step_fs}\n" + "dump_xyz 1 state.xyz mass spin mforce spin_velocity\n" + "run 1\n") + assert result.returncode == 0, result.stdout + result.stderr + actual = _read_spin_frame(tmp_path / "tspin" / "state.xyz") + + dt = time_step_fs / TIME_UNIT_CONVERSION + number_of_atoms = len(actual["mass"]) + velocity = _initial_spin_velocity( + seed, actual["mass"], temperature, mass_factor) + position_nhc = np.zeros(4) + velocity_nhc = np.array([1.0, -1.0, 1.0, -1.0]) + thermal_energy = K_B * temperature + mass_nhc = np.full(4, thermal_energy * (dt * coupling) ** 2) + mass_nhc[0] *= 3.0 * number_of_atoms + + twice_kinetic_energy = np.sum( + actual["mass"][:, None] * mass_factor * velocity * velocity) + factor = _nhc( + position_nhc, velocity_nhc, mass_nhc, twice_kinetic_energy, + thermal_energy, 3.0 * number_of_atoms, 0.5 * dt) + velocity *= factor + velocity += ( + 0.5 * dt * initial["mforce"] / + (actual["mass"][:, None] * mass_factor)) + expected_spin = initial["spin"] + dt * velocity + + velocity += ( + 0.5 * dt * actual["mforce"] / + (actual["mass"][:, None] * mass_factor)) + twice_kinetic_energy = np.sum( + actual["mass"][:, None] * mass_factor * velocity * velocity) + factor = _nhc( + position_nhc, velocity_nhc, mass_nhc, twice_kinetic_energy, + thermal_energy, 3.0 * number_of_atoms, 0.5 * dt) + expected_velocity = velocity * factor + + np.testing.assert_allclose(actual["spin"], expected_spin, rtol=0.0, atol=2.0e-7) + np.testing.assert_allclose( + actual["spin_velocity"], expected_velocity, rtol=0.0, atol=2.0e-7) + + +@pytest.mark.parametrize( + "ensemble", + [ + "nvt_tspin 300 300 100 mass_factor", + "nvt_tspin 300 300 100 mass_factor 0", + "nvt_tspin 300 300 100 mass_factor nan", + "nvt_tspin 300 300 100 seed 0", + "nvt_tspin 300 300 100 seed nope", + "nvt_tspin 300 300 100 seed 1 seed 2", + "nvt_tspin 300 300 100 mass_factor 1 mass_factor 2", + "nvt_tspin 300 300 100 mass_factor X 0.001 Fe 0", + "nvt_tspin 300 300 100 mass_factor Fe -1 Ge 0.001", + "nvt_tspin 300 300 100 mass_factor Fe 0 Ge 0", + "nvt_tspin 300 300 100 lattice maybe", + "nvt_tspin 300 300 100 lattice off lattice on", + "nvt_tspin 300 300 100 future 1", + "npt_tspin temp 300 300 iso 0 0 mass_factor", + "npt_tspin temp 300 300 iso 0 0 seed 1 seed 2", + "npt_tspin temp 300 300 iso 0 0 future 1", + ], +) +def test_tspin_parser_fails_closed(tmp_path, ensemble): + result = _prepare_case( + tmp_path / "case", + "potential nep.txt\n" + f"ensemble {ensemble}\n" + "run 1\n") + assert result.returncode != 0 + + +def test_element_mass_factor_requires_every_present_element(tmp_path): + directory = tmp_path / "missing_element" + directory.mkdir() + (directory / "nep.txt").write_text(selective_type_model()) + (directory / "model.xyz").write_text( + '2\nLattice="16 0 0 0 16 0 0 0 16" ' + 'Properties=species:S:1:pos:R:3:vel:R:3:spin:R:3 pbc="T T T"\n' + 'Fe 0 0 0 0 0 0 1 0.2 -0.1\n' + 'Ge 3 0 0 0 0 0 0.4 -0.3 0.7\n') + (directory / "run.in").write_text( + "potential nep.txt\n" + "ensemble nvt_tspin 300 300 100 mass_factor Fe 0.001\n" + "run 1\n") + result = subprocess.run( + [str(GPUMD)], cwd=directory, + capture_output=True, text=True, check=False) + assert result.returncode != 0 + + +def test_npt_tspin_composes_mttk_pressure_and_spin_integrators(tmp_path): + initial_lattice = _read_last_lattice(FIXTURE / "model_large_box.xyz") + initial_spin = np.array([ + [float(value) for value in line.split()[-3:]] + for line in (FIXTURE / "model_large_box.xyz").read_text().splitlines()[2:] + ]) + result = _prepare_case( + tmp_path / "npt", + "potential nep.txt\n" + "ensemble npt_tspin temp 300 300 iso 0 0 tperiod 100 pperiod 1000 " + "mass_factor 1.5 seed 2468\n" + "time_step 0.1\n" + "dump_xyz 1 state.xyz mass spin mforce spin_velocity\n" + "run 1\n") + assert result.returncode == 0, result.stdout + result.stderr + assert "Integrate spins with TSPIN" in result.stdout + assert "Use Nose-Hoover thermostat and Parrinello-Rahman barostat" in result.stdout + + actual = _read_spin_frame(tmp_path / "npt" / "state.xyz") + final_lattice = _read_last_lattice(tmp_path / "npt" / "state.xyz") + assert np.max(np.abs(actual["spin"] - initial_spin)) > 1.0e-10 + assert np.all(np.isfinite(final_lattice)) + assert np.max(np.abs(final_lattice - initial_lattice)) > 0.0 + + +def test_nvt_tspin_lattice_off_only_integrates_spins(tmp_path): + lines = (FIXTURE / "model_large_box.xyz").read_text().splitlines() + lines[1] = lines[1].replace( + "Properties=species:S:1:pos:R:3:spin:R:3", + "Properties=species:S:1:pos:R:3:vel:R:3:spin:R:3") + initial_position = [] + initial_velocity = [] + initial_spin = [] + for index in range(2, len(lines)): + fields = lines[index].split() + velocity = [0.01 * index, -0.02 * index, 0.03 * index] + initial_position.append([float(value) for value in fields[1:4]]) + initial_velocity.append(velocity) + initial_spin.append([float(value) for value in fields[4:7]]) + lines[index] = " ".join( + fields[:4] + [str(value) for value in velocity] + fields[4:]) + + result = _prepare_case( + tmp_path / "spin_only", + "potential nep.txt\n" + "ensemble nvt_tspin 300 300 100 lattice off " + "mass_factor 0.001 seed 2468\n" + "time_step 0.01\n" + "dump_xyz 5 state.xyz velocity spin spin_velocity\n" + "run 5\n", + "\n".join(lines) + "\n") + assert result.returncode == 0, result.stdout + result.stderr + + rows = np.array([ + [float(value) for value in line.split()[1:]] + for line in (tmp_path / "spin_only" / "state.xyz").read_text().splitlines() + [-len(initial_position):] + ]) + np.testing.assert_allclose(rows[:, 0:3], initial_position, rtol=0.0, atol=0.0) + np.testing.assert_allclose(rows[:, 3:6], initial_velocity, rtol=0.0, atol=0.0) + assert np.max(np.abs(rows[:, 6:9] - np.array(initial_spin))) > 1.0e-12 + + +def test_tspin_integrates_coordinates_excluded_by_potential_response_mask(tmp_path): + directory = tmp_path / "potential_mask" + directory.mkdir() + (directory / "nep.txt").write_text(selective_type_model()) + (directory / "model.xyz").write_text( + '2\nLattice="16 0 0 0 16 0 0 0 16" ' + 'Properties=species:S:1:pos:R:3:vel:R:3:spin:R:3:spin_vel:R:3 ' + 'pbc="T T T"\n' + 'Fe 0 0 0 0 0 0 1 0.2 -0.1 0.08 -0.03 0.04\n' + 'Ge 3 0 0 0 0 0 0.4 -0.3 0.7 0.15 -0.05 0.1\n') + (directory / "run.in").write_text( + "potential nep.txt\n" + "ensemble nvt_tspin 300 300 100 mass_factor 1.5 seed 97531\n" + "time_step 0.1\n" + "dump_xyz 1 state.xyz mass spin mforce spin_velocity\n" + "run 1\n") + result = subprocess.run( + [str(GPUMD)], cwd=directory, + capture_output=True, text=True, check=False) + assert result.returncode == 0, result.stdout + result.stderr + + actual = _read_spin_frame(directory / "state.xyz") + initial_excluded_spin = np.array([0.4, -0.3, 0.7]) + assert np.max(np.abs(actual["mforce"][1])) <= 1.0e-12 + assert np.max(np.abs(actual["spin"][1] - initial_excluded_spin)) > 1.0e-12 + assert np.max(np.abs(actual["spin_velocity"][1])) > 1.0e-12 + + +def test_element_mass_factor_zero_freezes_only_selected_spins(tmp_path): + directory = tmp_path / "element_mass" + directory.mkdir() + (directory / "nep.txt").write_text(selective_type_model()) + (directory / "model.xyz").write_text( + '2\nLattice="16 0 0 0 16 0 0 0 16" ' + 'Properties=species:S:1:pos:R:3:vel:R:3:spin:R:3:spin_vel:R:3 ' + 'pbc="T T T"\n' + 'Fe 0 0 0 0 0 0 1 0.2 -0.1 0.08 -0.03 0.04\n' + 'Ge 3 0 0 0 0 0 0.4 -0.3 0.7 0.15 -0.05 0.1\n') + (directory / "run.in").write_text( + "potential nep.txt\n" + "ensemble nvt_tspin 300 300 100 mass_factor Fe 0 Ge 1.5 seed 97531\n" + "time_step 0.1\n" + "dump_xyz 1 state.xyz mass spin mforce spin_velocity\n" + "run 1\n") + result = subprocess.run( + [str(GPUMD)], cwd=directory, + capture_output=True, text=True, check=False) + assert result.returncode == 0, result.stdout + result.stderr + + actual = _read_spin_frame(directory / "state.xyz") + np.testing.assert_allclose(actual["spin"][0], [1.0, 0.2, -0.1], atol=0.0) + np.testing.assert_allclose(actual["spin_velocity"][0], 0.0, atol=0.0) + assert np.max(np.abs(actual["spin"][1] - [0.4, -0.3, 0.7])) > 1.0e-12 + assert "spin mass factor for Fe is 0" in result.stdout + assert "spin mass factor for Ge is 1.5" in result.stdout + + +def test_npt_tspin_runs_with_spin3_force_path(tmp_path): + fixture = Path(__file__).parent / "fixtures" / "nep_spin3" + _, oracle = load_fixture("o3c2_uniform") + case = oracle["cases"]["chiral_soc"] + directory = tmp_path / "spin3" + directory.mkdir() + shutil.copy(fixture / "nep4_spin3_o3c2_uniform.nep", directory / "nep.txt") + lattice = " ".join(str(value) for value in case["cell"]) + lines = [ + str(len(case["types"])), + f'Lattice="{lattice}" Properties=species:S:1:pos:R:3:vel:R:3:spin:R:3 ' + 'pbc="T T T"', + ] + for symbol, position, spin in zip( + case["types"], case["positions"], case["spins"]): + values = position + [0.0, 0.0, 0.0] + spin + lines.append(symbol + " " + " ".join(str(value) for value in values)) + (directory / "model.xyz").write_text("\n".join(lines) + "\n") + (directory / "run.in").write_text( + "potential nep.txt\n" + "ensemble npt_tspin temp 300 300 iso 0 0 " + "tperiod 100 pperiod 1000 seed 13579\n" + "time_step 0.01\n" + "dump_xyz 1 state.xyz mass spin mforce spin_velocity\n" + "run 1\n") + result = subprocess.run( + [str(GPUMD)], cwd=directory, + capture_output=True, text=True, check=False) + assert result.returncode == 0, result.stdout + result.stderr + actual = _read_spin_frame(directory / "state.xyz") + assert np.all(np.isfinite(actual["spin"])) + assert np.all(np.isfinite(actual["mforce"])) + + +def test_tspin_requires_spin_potential(tmp_path): + case = tmp_path / "case" + case.mkdir() + shutil.copy( + Path(__file__).parent / "fixtures" / "models" / "nep_C.txt", + case / "nep.txt") + shutil.copy( + Path(__file__).parent / "fixtures" / "structures" / "C-nat16-rattled.xyz", + case / "model.xyz") + (case / "run.in").write_text( + "potential nep.txt\n" + "ensemble nvt_tspin 300 300 100\n" + "run 1\n") + result = subprocess.run( + [str(GPUMD)], cwd=case, + capture_output=True, text=True, check=False) + assert result.returncode != 0 + + +def test_tspin_reuses_velocity_across_runs_and_restart(tmp_path): + first = _prepare_case( + tmp_path / "first", + "potential nep.txt\n" + "ensemble nvt_tspin 300 300 100 seed 17\n" + "time_step 0.1\n" + "dump_restart 1\n" + "run 1\n" + "ensemble nvt_tspin 300 300 100 seed 999\n" + "run 1\n") + assert first.returncode == 0, first.stdout + first.stderr + assert first.stdout.count("Initialized TSPIN velocities with seed") == 1 + assert "Reuse initialized spin velocities; TSPIN seed is not used." in first.stdout + + restart_model = (tmp_path / "first" / "restart.xyz").read_text() + restarted = _prepare_case( + tmp_path / "restarted", + "potential nep.txt\n" + "ensemble nvt_tspin 300 300 100 seed 123\n" + "time_step 0.1\n" + "run 1\n", + restart_model) + assert restarted.returncode == 0, restarted.stdout + restarted.stderr + assert "Reuse initialized spin velocities; TSPIN seed is not used." in restarted.stdout + assert "Initialized TSPIN velocities with seed" not in restarted.stdout + + +@pytest.mark.slow +def test_tspin_short_temperature_statistics(tmp_path): + result = _prepare_case(tmp_path / "thermal", "replicate 5 5 5\npotential nep.txt\n" + "ensemble nvt_tspin 300 300 100 mass_factor 1.5 seed 314159\n" + "time_step .1\ndump_xyz 10 trajectory.xyz mass spin spin_velocity\nrun 500\n") + assert result.returncode == 0, result.stdout + result.stderr + lines = (tmp_path / "thermal/trajectory.xyz").read_text().splitlines() + n = int(lines[0]) + temperatures = [] + for start in range(0, len(lines), n + 2): + rows = np.array([[float(x) for x in line.split()[1:]] for line in lines[start+2:start+n+2]]) + kinetic = np.sum(rows[:, 3] * 1.5 * np.sum((rows[:, 7:10] * TIME_UNIT_CONVERSION)**2, axis=1)) + temperatures.append(kinetic / (3 * n * K_B)) + assert temperatures and np.isfinite(temperatures).all() + assert 240 <= np.mean(temperatures) <= 360 + + +def test_ordinary_nhc_keeps_spins_fixed(tmp_path): + model = _model_with_zero_lattice_velocity() + initial = np.array([[float(x) for x in row.split()[7:10]] for row in model.splitlines()[2:]]) + result = _prepare_case(tmp_path / "fixed", "potential nep.txt\n" + "ensemble nvt_nhc 300 300 100\ntime_step .1\n" + "dump_xyz 10 state.xyz mass spin mforce\nrun 10\n", model) + assert result.returncode == 0, result.stdout + result.stderr + np.testing.assert_array_equal(_read_spin_frame(tmp_path / "fixed/state.xyz")["spin"], initial) diff --git a/tests_pytest/validate_main_nep_spin3_training.py b/tests_pytest/validate_main_nep_spin3_training.py new file mode 100644 index 000000000..a33a81971 --- /dev/null +++ b/tests_pytest/validate_main_nep_spin3_training.py @@ -0,0 +1,638 @@ +#!/usr/bin/env python3 +"""Validate spin3 training, checkpoint prediction, and GPUMD runtime parity.""" + +import argparse +import json +import math +import os +import re +import shutil +import subprocess +import tempfile +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +NEP = Path(os.environ.get("NEP_COMMAND", ROOT / "src" / "nep")) +GPUMD = Path(os.environ.get("GPUMD_COMMAND", ROOT / "src" / "gpumd")) + +NEP_IN = """\ +type 2 Fe Ge +version 4 +spin_version 1 +spin_dof_type Fe +spin_env_type Fe Ge +cutoff 6.0 5.0 +n_max 0 0 +basis_size 0 0 +l_max 2 0 0 +neuron 4 +spin_compress 2 +spin_basis_size 8 0 +spin_l_max 2 0 0 +spin_cutoff 6.0 +spin_order 3 +spin_soc 1 +lambda_m 1.0 +lambda_tau 0.5 +population 10 +batch 3 +generation 1 +output_interval 1 +save_potential 1 0 0 +""" + +TRAIN_XYZ = """\ +4 +Lattice="24 0 0 0 24 0 0 0 24" Properties=species:S:1:pos:R:3:force:R:3:spin:R:3:mforce:R:3 energy=-4.0 virial="0 0 0 0 0 0 0 0 0" +Fe 1.0 1.0 1.0 0 0 0 1.0 0.1 0.0 0.2 -0.1 0.05 +Fe 2.2 1.1 1.0 0 0 0 0.8 -0.2 0.1 -0.1 0.2 -0.05 +Ge 1.4 2.3 1.1 0 0 0 0.0 0.0 0.0 9.0 9.0 9.0 +Ge 2.8 2.1 1.4 0 0 0 0.1 0.0 0.0 9.0 9.0 9.0 +4 +Lattice="24 0 0 0 24 0 0 0 24" Properties=species:S:1:pos:R:3:force:R:3:spin:R:3:mforce:R:3 energy=-2.0 virial="0 0 0 0 0 0 0 0 0" +Fe 1.2 1.0 1.0 0 0 0 0.9 0.0 0.2 0.1 0.0 -0.2 +Ge 2.1 1.4 1.0 0 0 0 0.0 0.0 0.0 8.0 8.0 8.0 +Ge 1.5 2.4 1.2 0 0 0 0.0 0.1 0.0 8.0 8.0 8.0 +Ge 2.8 2.5 1.5 0 0 0 0.0 0.0 0.1 8.0 8.0 8.0 +4 +Lattice="24 0 0 0 24 0 0 0 24" Properties=species:S:1:pos:R:3:force:R:3:spin:R:3:mforce:R:3 energy=-6.0 virial="0 0 0 0 0 0 0 0 0" +Fe 1.0 1.0 1.0 0 0 0 1.0 0.0 0.0 0.0 0.1 0.0 +Fe 2.0 1.0 1.0 0 0 0 0.8 0.1 0.0 0.1 0.0 0.0 +Fe 1.5 2.0 1.0 0 0 0 0.9 0.0 0.1 0.0 0.0 0.1 +Ge 2.5 2.0 1.2 0 0 0 0.0 0.0 0.0 7.0 7.0 7.0 +""" + + +def run(binary, cwd): + env = os.environ.copy() + env.setdefault("CUDA_VISIBLE_DEVICES", "0") + return subprocess.run( + [str(binary)], cwd=cwd, env=env, capture_output=True, text=True, + check=False) + + +def write_case(directory, nep_in=NEP_IN, train_xyz=TRAIN_XYZ): + directory.mkdir() + (directory / "nep.in").write_text(nep_in) + (directory / "train.xyz").write_text(train_xyz) + + +def response_xyz(): + lines = TRAIN_XYZ.splitlines() + output = [] + atom_count = int(lines[0]) + for coordinate in (-1.0, 0.0, 1.0): + output.append(lines[0]) + output.append( + f"{lines[1]} response_probe=rotation response_group=scan-a " + f"response_coordinate={coordinate}") + for atom in range(atom_count): + fields = lines[2 + atom].split() + if atom == 0: + fields[7:10] = [ + f"{math.cos(coordinate):.16e}", + f"{math.sin(coordinate):.16e}", + "0.0", + ] + output.append(" ".join(fields)) + return "\n".join(output) + "\n" + + +def columns(path, count, limit=None): + rows = [ + [float(item) for item in line.split()[:count]] + for line in path.read_text().splitlines()] + return rows if limit is None else rows[:limit] + + +def flatten(values): + if not isinstance(values, list): + return [values] + result = [] + for value in values: + result.extend(flatten(value)) + return result + + +def maximum_error(left, right): + left = flatten(left) + right = flatten(right) + if len(left) != len(right): + raise AssertionError(f"shape mismatch: {len(left)} != {len(right)}") + return max(abs(a - b) for a, b in zip(left, right)) + + +def parity_tolerance(left, right): + scale = max(abs(value) for value in flatten(left) + flatten(right)) + return 5.0e-5 + 5.0e-6 * scale + + +def validate_parser(root): + root.mkdir() + cases = { + "invalid_basis": NEP_IN.replace("spin_basis_size 8 0", "spin_basis_size 7 0"), + "invalid_second_basis": NEP_IN.replace("spin_basis_size 8 0", "spin_basis_size 8 1"), + "invalid_order": NEP_IN.replace("spin_order 3", "spin_order 4"), + "invalid_soc": NEP_IN.replace("spin_soc 1", "spin_soc 2"), + "oversized_spin_shape": NEP_IN.replace("spin_compress 2", "spin_compress 4"), + "removed_spin_mode_1": NEP_IN.replace("spin_version 1", "spin_mode 1"), + "removed_spin_mode_2": NEP_IN.replace("spin_version 1", "spin_mode 2"), + "invalid_spin_cutoff_arity": NEP_IN.replace( + "spin_cutoff 6.0", "spin_cutoff 4.0 5.0 6.0"), + "removed_spin_chiral": NEP_IN.replace("spin_soc 1", "spin_soc 1\nspin_chiral 1"), + "removed_curriculum": NEP_IN.replace("spin_order 3", "spin_order 2").replace( + "lambda_tau 0.5", "lambda_tau 0.5\nspin_curriculum 1"), + "response_requires_metadata": NEP_IN.replace( + "lambda_tau 0.5", "lambda_tau 0.5\nlambda_spin_response 0.3"), + } + for value in ("0", "2", "1.0", "nan", "1 2", ""): + cases[f"invalid_spin_version_{value}"] = NEP_IN.replace("spin_version 1", f"spin_version {value}") + cases["duplicate_spin_version"] = NEP_IN + "spin_version 1\n" + cases["mixed_spin_selectors"] = NEP_IN + "spin_mode 3\n" + cases["mixed_spin_selectors_reverse"] = "spin_mode 3\n" + NEP_IN + cases["mixed_disabled_spin_selector"] = NEP_IN + "spin_mode 0\n" + cases["duplicate_legacy_spin_selector"] = NEP_IN.replace("spin_version 1", "spin_mode 3\nspin_mode 3") + for keyword in ("model_type 1", "charge_mode 1", "vdw 1", "charge_vdw 1"): + cases["conflicting_" + keyword] = NEP_IN + keyword + "\n" + cases["removed_mforce_mode"] = NEP_IN + "spin_mforce_mode full\n" + results = {} + for name, text in cases.items(): + case = root / name + write_case(case, text.replace("generation 1", "generation 0")) + result = run(NEP, case) + results[name] = result.returncode + if result.returncode == 0: + raise AssertionError(f"{name} did not fail closed") + tangent_case = root / "spin_tangent_is_not_a_label" + tangent_input = NEP_IN.replace( + "lambda_tau 0.5", "lambda_tau 0.5\nlambda_spin_response 0.3", + ).replace("generation 1", "generation 0") + tangent_xyz = response_xyz().replace( + "mforce:R:3", "mforce:R:3:spin_tangent:R:3") + tangent_xyz = "\n".join(line + " 0 0 0" if i % 6 >= 2 else line + for i, line in enumerate(tangent_xyz.splitlines())) + "\n" + write_case(tangent_case, tangent_input, tangent_xyz) + result = run(NEP, tangent_case) + results["spin_tangent_is_not_a_label"] = result.returncode + if result.returncode == 0 or "not an input label" not in result.stdout + result.stderr: + raise AssertionError("spin_tangent input was not rejected explicitly") + return results + + +def validate_response_training(root): + nep_in = NEP_IN.replace( + "lambda_tau 0.5", + "lambda_tau 0.5\nlambda_spin_response 0.3", + ).replace("generation 1", "generation 3") + write_case(root, nep_in.replace("batch 3", "batch 1")) + (root / "response.xyz").write_text(response_xyz()) + result = run(NEP, root) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + loss = (root / "loss.out").read_text().splitlines()[-1] + if re.search(r"\b(?:nan|inf)\b", loss, re.IGNORECASE): + raise AssertionError("response training produced a non-finite loss") + return {"training_loss": loss} + + +def validate_flexible_zbl_rejected(root): + from spin_fixtures import load_fixture + from spin_model_format import block_model + + root.mkdir() + training = root / "training" + write_case(training, NEP_IN + "zbl 2.5\n") + # Malformed contents must never reach the flexible parameter scanner. + (training / "zbl.in").write_text("not ZBL parameters\n") + result = run(NEP, training) + message = "NEP-spin does not support flexible ZBL" + assert result.returncode != 0 and message in result.stdout + result.stderr + legacy, _ = load_fixture("o3c2_uniform") + legacy = legacy.replace("nep4_spin3 ", "nep4_spin3_zbl ", 1) + lines = legacy.splitlines() + lines.insert(2 + int(lines[1].split()[2]), "zbl 0 0") + legacy = "\n".join(lines) + "\n" + for name, model in (("legacy", legacy), ("block", block_model(legacy))): + case = root / name + write_case(case, NEP_IN + "zbl 2.5\nprediction 1\n") + (case / "nep.txt").write_text(model) + (case / "model.xyz").write_text(TRAIN_XYZ) + (case / "run.in").write_text("potential nep.txt\n") + for binary in (NEP, GPUMD): + result = run(binary, case) + assert result.returncode != 0 and message in result.stdout + result.stderr, ( + name, binary, result.stdout, result.stderr) + return "training and legacy/block prediction/runtime reject flexible ZBL" + + +def validate_training_and_runtime( + root, enable_zbl=False, spin_compress=2, typewise_spin_cutoff=False, + all_spin_types=False, check_restart=False, torque_only=False, wide_spin_cutoff=False): + root.mkdir() + training = root / "training" + nep_in = NEP_IN.replace("version 4", "version 4\nzbl 2.5") \ + if enable_zbl else NEP_IN + nep_in = nep_in.replace( + "spin_compress 2", f"spin_compress {spin_compress}") + if torque_only: + nep_in = nep_in.replace("lambda_m 1.0", "lambda_m 0") + if all_spin_types: + nep_in = nep_in.replace("spin_dof_type Fe\n", "spin_dof_type Fe Ge\n") + if typewise_spin_cutoff: + nep_in = nep_in.replace("spin_cutoff 6.0", "spin_cutoff 5.0 7.0") + if check_restart: + # Nontrivial channel/basis axes expose incorrect parameter transposes. + nep_in = nep_in.replace("n_max 0 0", "n_max 4 4").replace( + "basis_size 0 0", "basis_size 2 2") + xyz = TRAIN_XYZ + if wide_spin_cutoff: + nep_in = nep_in.replace("spin_cutoff 6.0", "spin_cutoff 7.0").replace("batch 3", "batch 1") + xyz = xyz.replace("24 0 0 0 24 0 0 0 24", "13 0 0 0 13 0 0 0 13").replace("Ge 2.8", "Ge 8.0") + write_case(training, nep_in, xyz) + result = run(NEP, training) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + + checkpoint = (training / "nep.txt").read_text() + if not checkpoint.startswith("nep 2 Fe Ge\nformat_version 1\nmodel nep_spin\n"): + raise AssertionError("invalid block-format spin3 checkpoint") + if "\nspin_version 1\n" not in checkpoint or "\nspin_mode " in checkpoint: + raise AssertionError("Spin models must declare spin_version instead of spin_mode") + if "\nenergy_reference " not in checkpoint or "spin_baseline" in checkpoint: + raise AssertionError("Spin3 must use the shared energy reference") + if enable_zbl and "\nzbl 1.25 2.5\n" not in checkpoint: + raise AssertionError("spin3 ZBL checkpoint is missing its zbl line") + required = { + "spin_basis_size": "8", "spin_l_max": "2", "spin_order": "3", + "spin_soc": "1", "spin_scaler": "1", "spin_compress": str(spin_compress), + "spin_projection_size": str(4 * spin_compress * spin_compress), + "spin_cutoff": "5 7" if typewise_spin_cutoff else "7" if wide_spin_cutoff else "6", + } + if not all_spin_types: + required.update(spin_dof_type="Fe", spin_env_type="Fe Ge") + else: + assert "spin_dof_type" not in checkpoint and "spin_env_type" not in checkpoint, ( + "all-active masks should use the canonical implicit representation") + for key, value in required.items(): + assert f"\n{key} {value}\n" in checkpoint, f"missing checkpoint field: {key} {value}" + + loss = (training / "loss.out").read_text().splitlines()[-1] + if re.search(r"\b(?:nan|inf)\b", loss, re.IGNORECASE): + raise AssertionError("spin3 training produced a non-finite loss") + loss_values = [float(value) for value in loss.split()] + regularization_only = loss_values[2] + loss_values[3] + if abs(loss_values[1] - regularization_only) > 2.0e-5: + raise AssertionError( + "generation zero must use upstream regularization-only fitness") + + spin_descriptor_dims = {1: 21, 2: 55, 3: 91} + structural_dim = 15 if check_restart else 3 + descriptor_dim = structural_dim + spin_descriptor_dims[spin_compress] + q_scaler = [ + float(value) for value in checkpoint.splitlines()[-descriptor_dim:]] + # The production magnetic scaler downscales but never amplifies channels. + spin_scaler = q_scaler[structural_dim:] + if any(not math.isfinite(value) or value <= 0 for value in q_scaler): + raise AssertionError("spin3 q_scaler must be positive and finite") + if max(spin_scaler) > 1.0: + raise AssertionError( + f"spin3 magnetic q_scaler must not amplify channels: max={max(spin_scaler)}") + + prediction = root / "prediction" + prediction.mkdir() + shutil.copy(training / "nep.txt", prediction / "nep.txt") + shutil.copy(training / "train.xyz", prediction / "train.xyz") + prediction_in = re.sub( + r"^(population|generation|output_interval|save_potential).*$", + "", nep_in, flags=re.MULTILINE) + prediction_in = prediction_in.replace( + "version 4", "version 4\nprediction 1") + (prediction / "nep.in").write_text(prediction_in) + result = run(NEP, prediction) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + + runtime = root / "runtime" + runtime.mkdir() + shutil.copy(training / "nep.txt", runtime / "nep.txt") + model_lines = xyz.splitlines()[:6] + model_lines[1] = model_lines[1].replace("mforce:R:3", "mforce:R:3:group:I:1") + for i in range(2, 6): + model_lines[i] += " 0" if i < 4 else " 1" + (runtime / "model.xyz").write_text("\n".join(model_lines) + "\n") + (runtime / "run.in").write_text( + "potential nep.txt\n" + "velocity 1\n" + "ensemble nve\n" + "time_step 0\n" + "dump_xyz 1 result.xyz force potential spin mforce virial precision double\n" + "dump_xyz 1 ge.xyz force potential spin mforce virial group_labels group 0 1 precision double\n" + "run 1\n") + result = run(GPUMD, runtime) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + + lines = (runtime / "result.xyz").read_text().splitlines() + grouped = (runtime / "ge.xyz").read_text().splitlines() + if int(grouped[0]) != 2 or ":group:I:1" not in grouped[1]: + raise AssertionError("dump_xyz group selection or group_labels header is incorrect") + for selected, full in zip(grouped[2:], lines[4:6]): + fields = selected.split() + if fields[:-1] != full.split() or fields[-1] != "1": + raise AssertionError("grouped spin/mforce dump differs from the all-atom dump") + atom_count = int(lines[-6]) + header = lines[-5] + rows = [ + [float(item) for item in line.split()[1:]] + for line in lines[-atom_count:]] + runtime_energy = ( + float(re.search(r"\benergy=([-+0-9.eE]+)", header).group(1)) / + atom_count) + runtime_force = [row[3:6] for row in rows] + runtime_mforce = [row[9:12] for row in rows] + atom_virial = [row[13:22] for row in rows] + runtime_virial = [ + sum(row[index] for row in atom_virial) / atom_count + for index in (0, 4, 8, 1, 5, 6)] + + main_energy = float( + (prediction / "energy_train.out").read_text().split()[0]) + main_force = columns(prediction / "force_train.out", 3, atom_count) + main_mforce = columns(prediction / "mforce_train.out", 3, atom_count) + main_virial = columns(prediction / "virial_train.out", 6, 1)[0] + report = { + "energy_per_atom": abs(main_energy - runtime_energy), + "force": maximum_error(main_force, runtime_force), + "mforce": maximum_error(main_mforce, runtime_mforce), + "virial_per_atom": maximum_error(main_virial, runtime_virial), + "ge_mforce_max": max( + abs(value) for row in runtime_mforce[2:] for value in row), + "all_spin_types": all_spin_types, + "training_loss": loss, + "q_scaler_max": max(q_scaler), + "zbl": enable_zbl, + "spin_compress": spin_compress, + "typewise_spin_cutoff": typewise_spin_cutoff, + "torque_only": torque_only, + "descriptor_dim": descriptor_dim, + "grouped_dump": "passed", + } + for name in ("energy_per_atom", "force", "mforce", "virial_per_atom"): + reference = { + "energy_per_atom": [main_energy, runtime_energy], + "force": [main_force, runtime_force], + "mforce": [main_mforce, runtime_mforce], + "virial_per_atom": [main_virial, runtime_virial], + }[name] + tolerance = parity_tolerance(*reference) + report[f"{name}_tolerance"] = tolerance + if report[name] > tolerance: + raise AssertionError( + f"{name} parity failed: {report[name]} > {tolerance}") + if not all_spin_types and report["ge_mforce_max"] > 1.0e-12: + raise AssertionError("inactive spin DOF received a public mforce") + if all_spin_types and report["ge_mforce_max"] <= 1.0e-12: + raise AssertionError("active Ge spin DOF was incorrectly masked") + if check_restart: + # Zero search variance freezes the saved parameter vector. A restart must + # round-trip structural and magnetic coefficients without reordering them + # or refitting the checkpoint's elemental energy baseline. + checkpoint_lines = checkpoint.splitlines() + first_parameter = next( + i + 1 for i, line in enumerate(checkpoint_lines) if line.startswith("@ parameters ")) + parameters = checkpoint_lines[first_parameter:-descriptor_dim - 1] + resumed = root / "resumed" + write_case(resumed, nep_in, TRAIN_XYZ.replace("energy=-4.0", "energy=40.0")) + (resumed / "nep.txt").write_text(checkpoint) + (resumed / "nep.restart").write_text( + "nep_restart\nenergy_reference 2 " + next(line.split(" ", 1)[1] for line in checkpoint_lines if line.startswith("energy_reference ")) + "\nparameters " + str(len(parameters)) + "\n" + "".join(f"{value} 0.0\n" for value in parameters)) + result = run(NEP, resumed) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + resumed_lines = (resumed / "nep.txt").read_text().splitlines() + if resumed_lines[:first_parameter] != checkpoint_lines[:first_parameter]: + raise AssertionError("restart changed the Spin3 header or energy baseline") + error = maximum_error( + [float(value) for value in parameters], + [float(line.split()[0]) for line in (resumed / "nep.restart").read_text().splitlines()[3:]]) + if error > 1.0e-7: + raise AssertionError(f"zero-variance restart changed parameters: {error}") + if resumed_lines[-descriptor_dim:] != checkpoint_lines[-descriptor_dim:]: + raise AssertionError("restart changed saved descriptor scaling") + report["restart_parameter_error"] = error + report["restart_scaler"] = "preserved" + # The legacy two-column restart uses basis-major structural coefficients. + legacy_values = list(parameters) + fields = {line.split()[0]: line.split()[1:] for line in checkpoint_lines[:first_parameter - 1]} + nr, na = map(int, fields["n_max"]) + br, ba = map(int, fields["basis_size"]) + neurons = int(fields["ann"][0]) + offset = (descriptor_dim + 2) * neurons * 2 + 1 + for basis_count in ((nr + 1) * (br + 1), (na + 1) * (ba + 1)): + values = legacy_values[offset:offset + 4 * basis_count] + legacy_values[offset:offset + len(values)] = [values[pair * basis_count + b] + for b in range(basis_count) for pair in range(4)] + offset += len(values) + legacy_resume = root / "legacy-resumed" + write_case(legacy_resume, nep_in, TRAIN_XYZ) + (legacy_resume / "nep.txt").write_text(checkpoint) + (legacy_resume / "nep.restart").write_text("".join(f"{v} 0\n" for v in legacy_values)) + result = run(NEP, legacy_resume) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + restored = [float(line.split()[0]) for line in + (legacy_resume / "nep.restart").read_text().splitlines()[3:]] + error = maximum_error([float(v) for v in parameters], restored) + if error > 1e-7: + raise AssertionError(f"legacy restart layout changed parameters: {error}") + report["legacy_restart_parameter_error"] = error + + return report + + +def validate_native_compiled_checkpoint(root): + """Compare full outputs at fixed parameters, including cross-block scatter.""" + root.mkdir() + # 36 centers span multiple fused-force tiles; Fe and Ge both carry spin. + atoms = TRAIN_XYZ.splitlines()[2:6] + expanded = ["36", TRAIN_XYZ.splitlines()[1]] + for tile in range(9): + for atom in atoms: + fields = atom.split() + fields[1] = str(float(fields[1]) + 4.0 * (tile % 3)) + fields[2] = str(float(fields[2]) + 4.0 * (tile // 3)) + expanded.append(" ".join(fields)) + xyz = "\n".join(expanded) + "\n" + report = {} + for channels, order in ((1, 3), (2, 3), (3, 3), (9, 1)): + config = NEP_IN.replace("spin_compress 2", f"spin_compress {channels}") + config = config.replace("spin_order 3", f"spin_order {order}") + config = config.replace("spin_dof_type Fe\n", "spin_dof_type Fe Ge\n") + config = config.replace("n_max 0 0", "n_max 4 4").replace( + "basis_size 0 0", "basis_size 2 2") + if channels == 3: + config = config.replace("spin_cutoff 6.0", "spin_cutoff 5.0 7.0") + initial = root / f"c{channels}-initial" + write_case(initial, config + "nep_compile 0\n", xyz) + result = run(NEP, initial) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + checkpoint = (initial / "nep.txt").read_text() + restart_lines = (initial / "nep.restart").read_text().splitlines() + frozen = "\n".join(restart_lines[:3]) + "\n" + "".join( + f"{line.split()[0]} 0\n" for line in restart_lines[3:]) + cases = [] + for compiled in (0, 1): + case = root / f"c{channels}-compiled-{compiled}" + # Report test outputs at fixed parameters after the first physical evaluation. + output_config = config.replace("generation 1\n", "generation 2\n") + write_case(case, output_config + f"nep_compile {compiled}\n", xyz) + (case / "test.xyz").write_text(xyz) + (case / "nep.txt").write_text(checkpoint) + (case / "nep.restart").write_text(frozen) + result = run(NEP, case) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + if compiled and ( + "Compile specialized Spin3 training kernels" not in result.stdout or + "specialization disabled" in (result.stdout + result.stderr).lower()): + raise AssertionError("Spin3 JIT did not compile successfully") + cases.append(case) + errors = {} + for name, width in (("energy", 1), ("force", 3), ("virial", 6), ("mforce", 3)): + values = [columns(case / f"{name}_test.out", width) for case in cases] + error = maximum_error(*values) + tolerance = parity_tolerance(*values) + if not math.isfinite(error) or error > tolerance: + raise AssertionError(f"C{channels} JIT {name}: {error} > {tolerance}") + errors[name] = {"max_abs": error, "tolerance": tolerance} + report[f"o{order}c{channels}"] = errors + return report + + +def validate_default_shape(root): + """Exercise model defaults and compare omitted vs explicit C2 end to end.""" + root.mkdir() + # Only select the elements/model and bound the training budget and output. + # Leave all structural, Spin descriptor, network and loss settings implicit. + config = ( + "type 2 Fe Ge\nspin_version 1\nseed 20261025\n" + "population 12\nbatch 3\ngeneration 3\noutput_interval 1\n" + "save_potential 100000 1 0\n") + cases = [root / "implicit", root / "explicit"] + configs = [config, config + "spin_compress 2\n"] + for case, text in zip(cases, configs): + write_case(case, text) + # Without ZBL enabled, a stray zbl.in must not affect any lifecycle stage. + (cases[0] / "zbl.in").write_text("not ZBL parameters\n") + report = {} + for stage in ("training", "prediction", "restart"): + for case, text in zip(cases, configs): + if stage == "prediction": + text += "prediction 1\n" + elif stage == "restart": + text = text.replace("generation 3\n", "generation 4\n") + (case / "nep.in").write_text(text) + result = run(NEP, case) + (case / f"{stage}.log").write_text(result.stdout + result.stderr) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + checkpoint = (case / "nep.txt").read_text() + for line in ("spin_compress 2", "spin_order 3", "spin_soc 1", + "spin_l_max 2", "spin_basis_size 8", + "spin_cutoff 8", "spin_projection_size 16"): + if f"\n{line}\n" not in checkpoint: + raise AssertionError(f"default checkpoint missing {line}") + if "@ q_scaler 97\n" not in checkpoint: + raise AssertionError("default descriptor must have 42 + 55 coordinates") + loss = [float(value) for value in + (case / "loss.out").read_text().splitlines()[-1].split()] + if not all(math.isfinite(value) for value in loss): + raise AssertionError(f"{stage}: non-finite default-shape loss") + files = ["nep.txt", "nep.restart"] + if stage == "prediction": + for name, width, rows in (("energy", 2, 3), ("force", 6, 12), + ("mforce", 6, 12), ("virial", 12, 3)): + filename = f"{name}_train.out" + files.append(filename) + values = columns(cases[0] / filename, width) + if len(values) != rows or any(len(row) != width for row in values): + raise AssertionError(f"unexpected default prediction shape: {filename}") + if not all(math.isfinite(value) for value in flatten(values)): + raise AssertionError(f"non-finite default prediction: {filename}") + energies = columns(cases[0] / "energy_train.out", 2) + report["energy_rmse_per_atom"] = math.sqrt( + sum((predicted - reference) ** 2 for predicted, reference in energies) + / len(energies)) + for filename in files: + if (cases[0] / filename).read_bytes() != (cases[1] / filename).read_bytes(): + raise AssertionError(f"{stage}: implicit/explicit C2 differ in {filename}") + report[stage] = "implicit/explicit C2 byte-identical" + report["descriptor_dim"] = 97 + return report + + +def validate_shared_nep_io(root): + """Guard the ordinary NEP callers of the shared writer and restart reader.""" + config = "\n".join(line for line in NEP_IN.splitlines() + if not line.startswith(("spin_", "lambda_m", "lambda_tau"))) + "\n" + write_case(root, config) + result = run(NEP, root) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + first = (root / "nep.restart").read_text().splitlines()[1] + result = run(NEP, root) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + if (root / "nep.restart").read_text().splitlines()[1] != first: + raise AssertionError("ordinary NEP restart changed energy references") + (root / "nep.in").write_text(config + "prediction 1\n") + result = run(NEP, root) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + predictions = [(root / (name + "_train.out")).read_text() for name in ("energy", "force", "virial")] + (root / "nep.in").write_text(config + "spin_mode 0\nprediction 1\n") + result = run(NEP, root) + if result.returncode: + raise RuntimeError(result.stdout + result.stderr) + assert predictions == [(root / (name + "_train.out")).read_text() for name in ("energy", "force", "virial")] + return "training/restart/prediction and legacy disabled selector passed" + + +def main(): + global NEP, GPUMD + parser = argparse.ArgumentParser() + parser.add_argument("--nep", type=Path, default=NEP) + parser.add_argument("--gpumd", type=Path, default=GPUMD) + parser.add_argument("--check-jit", action="store_true", + help="Require the CUDA compiler and validate specialized Spin3 training") + args = parser.parse_args() + NEP = args.nep.resolve() + GPUMD = args.gpumd.resolve() + with tempfile.TemporaryDirectory(prefix="gpumd-main-nep-spin3-") as tmp: + root = Path(tmp) + report = { + "default_shape": validate_default_shape(root / "defaults"), + "flexible_zbl_rejected": validate_flexible_zbl_rejected(root / "flexible-zbl"), + "ordinary_nep_io": validate_shared_nep_io(root / "ordinary-nep"), + "parser_negative_exit_codes": validate_parser(root / "parser"), + "response_training": validate_response_training(root / "response"), + "training_runtime": validate_training_and_runtime(root / "correctness"), + "rank_one_training_runtime": validate_training_and_runtime( + root / "rank-one", spin_compress=1, + typewise_spin_cutoff=True, torque_only=True), + "zbl_training_runtime": validate_training_and_runtime( + root / "zbl", enable_zbl=True), + "magnetic_cutoff_small_cell": validate_training_and_runtime( + root / "wide-spin-cutoff", all_spin_types=True, wide_spin_cutoff=True), + "channel_layout_restart": validate_training_and_runtime( + root / "restart", spin_compress=3, + all_spin_types=True, check_restart=True), + } + if args.check_jit: + report["native_compiled_checkpoint"] = validate_native_compiled_checkpoint(root / "jit") + print(json.dumps(report, indent=2, sort_keys=True)) + + +if __name__ == "__main__": + main() diff --git a/tests_pytest/validate_mfield_runtime.py b/tests_pytest/validate_mfield_runtime.py new file mode 100644 index 000000000..6ad4bc3a7 --- /dev/null +++ b/tests_pytest/validate_mfield_runtime.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +"""GPU runtime checks for group-selected Zeeman coupling; standard library only.""" +import json +import tempfile +from pathlib import Path +import spin_runtime_helpers as runtime + +CB = 5.7883818060e-5 +FIELD = [12.0, -7.0, 31.0] + +def grouped(model): + lines = model.splitlines() + lines[1] = lines[1].replace('spin:R:3', 'spin:R:3:group:I:2') + for i in range(2, len(lines)): + lines[i] += f' 0 {(i-2)%2}' + return '\n'.join(lines)+'\n' + +def frame(path): + lines = path.read_text().splitlines() + n = int(lines[0]) + return [[float(x) for x in line.split()[1:]] for line in lines[-n:]] + +def main(): + original_run = runtime.run_case + with tempfile.TemporaryDirectory(prefix='gpumd-mfield-') as tmp: + root = Path(tmp) + model = grouped(runtime.base_model()) + def static(name, command, model_text=None): + case, result = original_run(root, name, + 'potential nep.txt\n'+command+'\nensemble nve\ntime_step 0\n' + 'dump_xyz 1 state.xyz precision double mass spin mforce potential\nrun 1\n', model_text or model) + assert result.returncode == 0, result.stdout+result.stderr + return frame(case/'state.xyz') + baseline = static('baseline', '') + applied = static('field', 'add_mfield 1 1 12 -7 31') + for i, (before, after) in enumerate(zip(baseline, applied)): + h = [CB*b if i%2 else 0.0 for b in FIELD] + for k in range(3): + assert abs((after[7+k]-before[7+k])-h[k]) < 2e-12 + expected = -sum(before[4+k]*h[k] for k in range(3)) + assert abs(after[10]-before[10]-expected) < 2e-12 + cleared = static('cleared', 'add_mfield 1 1 12 -7 31\nadd_mfield 0 0 0 0 0') + assert cleared == baseline + negative = ['add_mfield 0 0 1 2', 'add_mfield -1 0 1 2 3', + 'add_mfield 0 99 1 2 3', 'add_mfield 0 0 nan 0 0', + 'add_mfield 0 0 1 2 3 block 0 1 0 1 0 1'] + for i, command in enumerate(negative): + _, result = original_run(root, f'negative{i}', 'potential nep.txt\n'+command+'\n', model) + assert result.returncode != 0, command + region_command = 'add_mfield region 0.25 0.75 0 1 0 1 12 -7 31' + for scale, skew, wrap in [(20, 0, False), (20, 4, False), (40, 8, False), (20, 0, True)]: + lines = runtime.base_model().splitlines() # region mode needs no groups + import re + lines[1] = re.sub(r'Lattice="[^"]+"', + f'Lattice="{scale} 0 0 {skew} {scale} 0 0 0 {scale}"', lines[1]) + for i, fraction in enumerate([0.25, 0.5, 0.75, 0.875]): + fields = lines[i+2].split() + fields[1:4] = [str(scale*(fraction + (1 if wrap else 0)) + skew*0.25), + str(scale*0.25), str(scale*0.25)] + lines[i+2] = ' '.join(fields) + text = '\n'.join(lines)+'\n' + tag = f'region-{scale}-{skew}-{wrap}' + before = static(tag+'-off', '', text) + after = static(tag+'-on', region_command, text) + for i, (left, right) in enumerate(zip(before, after)): + h = [CB*b if i < 2 else 0.0 for b in FIELD] + for k in range(3): + assert abs(right[7+k]-left[7+k]-h[k]) < 2e-12, tag + assert abs(right[10]-left[10]+sum(left[4+k]*h[k] for k in range(3))) < 2e-12, tag + # A moving atom enters and then leaves the region; the field must be + # recomputed from current positions, not cached as a fixed group. + lines = runtime.base_model().splitlines() + fields = lines[2].split() + fields[4] = '2' # vx = 2 Angstrom/fs + lines[2] = ' '.join(fields) + moving = '\n'.join(lines)+'\n' + states = [] + for tag, command in [('off', ''), ('on', 'add_mfield region 0.015 0.025 0 1 0 1 12 -7 31\n')]: + case, result = original_run(root, 'moving-'+tag, + 'potential nep.txt\n'+command+'ensemble nve\ntime_step 0.1\n' + 'dump_xyz 1 state.xyz precision double mass spin mforce potential\nrun 2\n', moving) + assert result.returncode == 0, result.stdout+result.stderr + rows = (case/'state.xyz').read_text().splitlines() + states.append([[float(x) for x in rows[offset+2].split()[1:]] for offset in (0, 6)]) + assert 0.3 <= states[1][0][0] < 0.5 and states[1][1][0] >= 0.5 + for step in range(2): + for k in range(3): + expected = CB*FIELD[k] if step == 0 else 0.0 + assert abs(states[1][step][7+k]-states[0][step][7+k]-expected) < 2e-12 + for i, bounds in enumerate(['-0.1 1 0 1 0 1', '0 1.1 0 1 0 1', + '0.5 0.5 0 1 0 1', '0 1 nan 1 0 1']): + _, result = original_run(root, f'region-negative{i}', + 'potential nep.txt\nadd_mfield region '+bounds+' 0 0 10\n', runtime.base_model()) + assert result.returncode != 0 + print(json.dumps({'group_energy_force': 'passed', 'zero_field': 'passed', + 'parser_negatives': len(negative)+4, 'region_boundary_skew_wrap': 'passed', + 'region_enter_exit': 'passed'})) + +if __name__ == '__main__': + main() diff --git a/tests_pytest/validate_nep_spin3_runtime.py b/tests_pytest/validate_nep_spin3_runtime.py new file mode 100644 index 000000000..a93c26dc0 --- /dev/null +++ b/tests_pytest/validate_nep_spin3_runtime.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python3 +"""Validate the GPUMD nep4_spin3 force path against the frozen FP64 oracle.""" + +import argparse +import hashlib +import os +import re +import subprocess +import tempfile +from pathlib import Path +from spin_model_format import block_model +from spin_fixtures import selective_type_model, write_xyz, reshape, read_text_oracle, load_fixture + + +ROOT = Path(__file__).resolve().parents[1] +FIXTURE = Path(__file__).parent / "fixtures" / "nep_spin3" +GPUMD = Path(os.environ.get("GPUMD_COMMAND", ROOT / "src" / "gpumd")) + + + + + + + + + + + + +def read_frame(path): + lines = path.read_text().splitlines() + atom_count = int(lines[0]) + rows = [line.split() for line in lines[-atom_count:]] + values = [[float(value) for value in row[1:]] for row in rows] + energy = float( + re.search(r"\benergy=([-+0-9.eE]+)", lines[-atom_count - 1]).group(1)) + virial = [] + for row in values: + # dump_xyz already serializes the internal 9-plane tensor in row-major + # order (xx, xy, xz, yx, yy, yz, zx, zy, zz). + virial.append(row[13:22]) + return { + "energy": energy, + "force": [row[3:6] for row in values], + "mforce": [row[9:12] for row in values], + "potential": [row[12] for row in values], + "atom_virial": virial, + "virial": [sum(row[index] for row in virial) for index in range(9)], + } + + +def flatten(values): + if not isinstance(values, list): + return [values] + result = [] + for value in values: + result.extend(flatten(value)) + return result + + +def max_error(candidate, reference): + left = flatten(candidate) + right = flatten(reference) + if len(left) != len(right): + raise AssertionError(f"shape mismatch: {len(left)} != {len(right)}") + return max(abs(a - b) for a, b in zip(left, right)) + + +def worst_difference(candidate, reference): + left = flatten(candidate) + right = flatten(reference) + index = max(range(len(left)), key=lambda item: abs(left[item] - right[item])) + return index, left[index], right[index] + + +def run_case(root, name, case, model): + directory = root / name + directory.mkdir() + write_xyz(directory / "model.xyz", case) + (directory / "nep.txt").write_text(model) + (directory / "run.in").write_text( + "potential nep.txt\n" + "velocity 1\n" + "ensemble nve\n" + "time_step 0\n" + "dump_xyz 1 result.xyz force potential spin mforce virial precision double\n" + "run 1\n") + result = subprocess.run( + [str(GPUMD)], cwd=directory, capture_output=True, text=True, check=False) + if result.returncode: + raise RuntimeError( + f"{name}: GPUMD failed with {result.returncode}\n" + f"{result.stdout}{result.stderr}") + return read_frame(directory / "result.xyz") + + +def validate_removed_spin2(root): + model, oracle = load_fixture("o3c2_uniform") + case = next(iter(oracle["cases"].values())) + directory = root / "removed_spin2" + directory.mkdir() + write_xyz(directory / "model.xyz", case) + (directory / "nep.txt").write_text( + model.replace("nep4_spin3", "nep4_spin2", 1)) + (directory / "run.in").write_text( + "potential nep.txt\nensemble nve\ntime_step 0\nrun 1\n") + result = subprocess.run( + [str(GPUMD)], cwd=directory, capture_output=True, text=True, check=False) + if result.returncode == 0: + raise AssertionError("removed nep4_spin2 model was accepted") + + +def validate_energy_reference(root): + legacy, oracle = load_fixture("o3c2_uniform") + model = block_model(legacy) + case = oracle["cases"]["noncollinear"] + base = run_case(root, "reference-base", case, model) + old = next(line for line in model.splitlines() if line.startswith("energy_reference ")) + references = list(map(float, old.split()[1:])) + shifts = [100000.123456789, -200000.987654321] + changed = "energy_reference " + " ".join(format(a + b, '.17g') for a, b in zip(references, shifts)) + shifted = run_case(root, "reference-shift", case, model.replace(old, changed)) + expected = base["energy"] + sum(shifts[0 if t == "Fe" else 1] for t in case["types"]) + if abs(shifted["energy"] - expected) > 2e-6: + raise AssertionError(f"energy reference mismatch: actual={shifted['energy']:.17g}, expected={expected:.17g}") + for field in ("force", "mforce", "virial"): + if max_error(base[field], shifted[field]) > 1e-10: + raise AssertionError(f"constant energy reference changed {field}") + print("Spin3 double energy-reference shift and derivative invariance passed") + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--cases", nargs="*", default=None, + help="oracle cases to run; default runs every case") + parser.add_argument( + "--fixtures", nargs="*", + choices=("o3c2_uniform", "o3c2_typewise", "o3c3_uniform"), + default=("o3c2_uniform", "o3c2_typewise", "o3c3_uniform"), + help="frozen Spin3 fixtures to run") + parser.add_argument("--tolerance", type=float, default=2.0e-4) + parser.add_argument("--block-format", action="store_true", help="Validate converted block-format fixtures against the same frozen oracle") + args = parser.parse_args() + + errors = {} + with tempfile.TemporaryDirectory(prefix="gpumd-spin3-") as temp: + root = Path(temp) + validate_removed_spin2(root) + if args.block_format: + validate_energy_reference(root) + for fixture in args.fixtures: + model, oracle = load_fixture(fixture) + if args.block_format: + model = block_model(model) + selected = args.cases or list(oracle["cases"]) + fixture_root = root / fixture + fixture_root.mkdir() + for name in selected: + if name not in oracle["cases"]: + continue + reference = oracle["cases"][name] + candidate = run_case(fixture_root, name, reference, model) + case_errors = { + "energy": abs(candidate["energy"] - sum(reference["potential"])), + "potential": max_error(candidate["potential"], reference["potential"]), + "force": max_error(candidate["force"], reference["force"]), + "mforce": max_error(candidate["mforce"], reference["mforce"]), + "virial": max_error( + candidate["virial"], + [sum(row[index] for row in reference["atom_virial"]) + for index in range(9)]), + } + key = f"{fixture}/{name}" + errors[key] = case_errors + print(key + ": " + " ".join( + f"{field}={error:.3e}" for field, error in case_errors.items())) + failed = { + field: error for field, error in case_errors.items() + if error > args.tolerance + } + if failed: + for field in failed: + if field == "energy": + target = sum(reference["potential"]) + elif field == "virial": + target = [sum(row[index] for row in reference["atom_virial"]) + for index in range(9)] + else: + target = reference[field] + index, actual, expected = worst_difference(candidate[field], target) + print( + f"{key} {field} worst[{index}]: " + f"actual={actual:.10e} expected={expected:.10e}", + flush=True) + raise AssertionError( + f"{key}: tolerance {args.tolerance:.3e} exceeded: {failed}") + + worst = max(error for case in errors.values() for error in case.values()) + print( + f"spin3 oracle validation passed: cases={len(errors)} " + f"max_error={worst:.3e}; nep4_spin2 rejected") + + +if __name__ == "__main__": + main() diff --git a/tests_pytest/validate_response_file_runtime.py b/tests_pytest/validate_response_file_runtime.py new file mode 100644 index 000000000..f3f7d1c58 --- /dev/null +++ b/tests_pytest/validate_response_file_runtime.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""Independent response file parser, isolation, batching and numerical checks.""" +import json +import math +import os +from pathlib import Path +import re +import tempfile +import validate_main_nep_spin3_training as base + +PROBE = Path(os.environ['RESPONSE_FITNESS_PROBE']) +CONFIG = base.NEP_IN.replace('batch 3', 'batch 1') + 'lambda_spin_response 0.3\nnep_compile 0\n' + +def parsed(stdout): + result = {'fit': [], 'points': []} + for line in stdout.splitlines(): + words = line.split() + if not words: continue + if words[0] in ('SCALER', 'BASELINE'): + result[words[0]] = list(map(float,words[1:])) + if words[0] == 'FIT': result['fit'].append(list(map(float,words[1:]))) + if words[0] == 'POINT': result['points'].append((words[1],float(words[2]),float(words[3]))) + return result + +def main(): + with tempfile.TemporaryDirectory(prefix='gpumd-response-file-') as temp: + root = Path(temp) + def case(name, config=CONFIG, response=base.response_xyz(), train=base.TRAIN_XYZ, test=None, error=None): + path=root/name + base.write_case(path,config,train) + if response is not None: (path/'response.xyz').write_text(response) + if test is not None: (path/'test.xyz').write_text(test) + run=base.run(PROBE,path) + if error is not None: + assert run.returncode and error in run.stdout+run.stderr, (name,run.stdout+run.stderr) + return + assert run.returncode==0, (name,run.stdout+run.stderr) + return parsed(run.stdout) + for value in ('-1', 'nan', 'inf', '1e100'): + case('invalid-weight-'+value,config=CONFIG.replace('lambda_spin_response 0.3','lambda_spin_response '+value),error='finite and non-negative') + case('missing',response=None,error='requires response.xyz') + case('empty',response='',error='rotation response frames in response.xyz') + case('ordinary-file',response=base.TRAIN_XYZ,error='rotation response metadata') + rows=base.response_xyz().splitlines() + case('partial',response='\n'.join(rows[:12])+'\n',error='at least three') + case('duplicate-coordinate',response=base.response_xyz().replace('response_coordinate=1.0','response_coordinate=0.0'),error='distinct response_coordinate') + changed=rows.copy();changed[8]=changed[8].replace('Fe 1.0','Fe 1.5') + case('moving',response='\n'.join(changed)+'\n',error='atomic positions') + case('group-leak',test=base.response_xyz(),error='response_group leakage') + case('frame-leak',test=re.sub(r' response_probe=rotation response_group=scan-a response_coordinate=\S+','',base.response_xyz()),error='Response frame leakage') + disabled=CONFIG.replace('lambda_spin_response 0.3','lambda_spin_response 0') + off=case('off',disabled,response=None) + ignored=case('ignored',disabled,response='not xyz at all') + assert off==ignored + on=case('on') + assert on['SCALER']==off['SCALER'] and on['BASELINE']==off['BASELINE'] + for left,right in zip(on['fit'],off['fit']): + assert left[:-1]==right[:-1], (left,right) + assert right[-1]==0 + values=[row[-1] for row in on['fit']] + assert min(values)>0 and max(values)-min(values)<1e-7 # same complete groups/candidates across minibatches + groups={} + for group,prediction,target in on['points']: groups.setdefault(group,[]).append((prediction,target)) + huber=lambda x: .5*x*x if abs(x)<=1 else abs(x)-.5 + loss=0 + for points in groups.values(): + scale=max(math.sqrt(sum(t*t for _,t in points)/len(points)),1e-6) + mp=sum(p for p,t in points)/len(points);mt=sum(t for p,t in points)/len(points) + loss+=sum(huber(((p-mp)-(t-mt))/scale) for p,t in points)/len(points)+.25*huber((mp-mt)/scale) + expected=.3*loss/len(groups) + assert abs(values[0]-expected)<2e-6,(values[0],expected) + full=case('full',CONFIG.replace('batch 1','batch 3')) + assert len(full['SCALER'])==len(on['SCALER']) + assert all(math.isclose(a,b,rel_tol=2e-6,abs_tol=1e-7) for a,b in zip(full['SCALER'],on['SCALER'])) + assert abs(full['fit'][0][-1]-values[0])<2e-6 + duplicated=case('groups-equal',response=base.response_xyz()+base.response_xyz().replace('scan-a','scan-b')) + assert abs(duplicated['fit'][0][-1]-values[0])<2e-6 + changed=case('unused-labels',response=base.response_xyz().replace('energy=-4.0','energy=40.0').replace(' 0 0 0 1.0',' 30 40 50 1.0')) + assert changed['BASELINE']==on['BASELINE'] and changed['SCALER']==on['SCALER'] and changed['fit']==on['fit'] + case('response-needs-energy',response=re.sub(r'energy=\S+\s*','',base.response_xyz()),error="'energy' is missing") + for label,start,end,error in [('force',4,7,"'force' or 'forces' is missing"),('mforce',10,13,'requires mforce:R:3')]: + stripped=[] + for i,line in enumerate(base.response_xyz().splitlines()): + if i%6==1: + line=line.replace(':'+label+':R:3','') + elif i%6>=2: + fields=line.split();line=' '.join(fields[:start]+fields[end:]) + stripped.append(line) + case('response-needs-'+label,response='\n'.join(stripped)+'\n',error=error) + no_virial=case('no-virial',response=re.sub(r'virial="[^"]*"\s*','',base.response_xyz())) + assert no_virial==on + case('train-still-needs-energy',train=re.sub(r'energy=\S+\s*','',base.TRAIN_XYZ),error="'energy' is missing") + print(json.dumps({'parser_and_leakage':'passed','lambda_zero':'passed','ordinary_fitness_isolation':'passed', + 'minibatch_fullbatch_response':'passed','group_equal_weight':'passed','response':values[0],'oracle':expected})) + +if __name__=='__main__':main() diff --git a/tests_pytest/validate_restart_scaler.py b/tests_pytest/validate_restart_scaler.py new file mode 100644 index 000000000..ee04d14d2 --- /dev/null +++ b/tests_pytest/validate_restart_scaler.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +"""Check native SNES restore/scalers using generated fixtures and RESTART_PROBE. + +The probe is built from restart_parity.cu against the current NEP objects. +No private dataset or pre-refactor executable is required. +""" +import json +import os +from pathlib import Path +import shutil +import subprocess +import tempfile + +import validate_main_nep_spin3_training as base +from validate_spin_training_multigpu import read_restart + + +def execute(binary, case): + result = base.run(binary, case) + (case / 'run.log').write_text(result.stdout + result.stderr) + assert result.returncode == 0, result.stdout + result.stderr + + +def values(path): + return list(map(float, path.read_text().split())) + + +def validate(root): + probe = Path(os.environ['RESTART_PROBE']).resolve() + report = {} + for kind in ('spin', 'structural'): + config = base.NEP_IN + if kind == 'structural': + config = '\n'.join(line for line in config.splitlines() + if not line.startswith(('spin_', 'lambda_m', 'lambda_tau'))) + '\n' + config += 'nep_compile 0\nseed 20261021\n' + config = config.replace('generation 1', 'generation 3') + initial = root / (kind + '-initial') + base.write_case(initial, config) + execute(base.NEP, initial) + restored = [] + for name, extra in (('restore', ''), ('restore-import', 'import_q_scaler 1\n')): + case = root / (kind + '-' + name) + base.write_case(case, config.replace('generation 3', 'generation 0') + extra) + for file in ('nep.txt', 'nep.restart'): + shutil.copyfile(initial / file, case / file) + execute(probe, case) + assert read_restart(case/'restored.restart') == read_restart(initial/'nep.restart') + restored.append(case) + for file in ('scaler.txt', 'baseline.txt', 'mu.pred', 'elite.pred'): + assert (restored[0]/file).read_text() == (restored[1]/file).read_text(), (kind, file) + assert (restored[0]/'mu.pred').read_text() != (restored[0]/'elite.pred').read_text() + if kind == 'spin': + scales = values(restored[0]/'scaler.txt') + imported = root/'fresh-import' + base.write_case(imported, config.replace('generation 3', 'generation 0')+'import_q_scaler 1\n') + shutil.copyfile(initial/'nep.txt', imported/'nep.txt') + execute(probe, imported) + assert values(imported/'scaler.txt') == scales + assert read_restart(imported/'restored.restart')[0] != read_restart(initial/'nep.restart')[0] + fresh = [] + for seed in (1, 2): + case = root/f'fresh-{seed}' + base.write_case(case, config.replace('generation 3', 'generation 0').replace('seed 20261021', f'seed {seed}')) + execute(probe, case) + fresh.append(case) + assert values(fresh[0]/'scaler.txt') == values(fresh[1]/'scaler.txt') + assert read_restart(fresh[0]/'restored.restart')[0] != read_restart(fresh[1]/'restored.restart')[0] + report[kind] = {'restore': 'passed', 'import': 'passed', 'search_mean_distinct_from_elite': True} + return report + + +if __name__ == '__main__': + with tempfile.TemporaryDirectory(prefix='restart-scalers-') as temp: + print(json.dumps(validate(Path(temp)), indent=2)) diff --git a/tests_pytest/validate_spin_mforce_split.py b/tests_pytest/validate_spin_mforce_split.py new file mode 100644 index 000000000..e4789f8df --- /dev/null +++ b/tests_pytest/validate_spin_mforce_split.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python3 +"""Validate independent Spin3 magnetic RMSE terms, restart, and GPU parity. + +Run on four allocated CUDA devices after building src/nep. Optionally supply +--oracle pointing to the linked spin_mforce_split.cu numerical test executable. +""" +import argparse +import json +import math +import os +from pathlib import Path +import shutil +import subprocess +import tempfile + +import validate_main_nep_spin3_training as base +from validate_spin_training_multigpu import read_restart, run_nep + + +def loss_rows(case): + lines = (case / 'loss.out').read_text().splitlines() + header = next(line.split()[2:] for line in reversed(lines) if line.startswith('# columns ')) + rows = [[float(v) for v in line.split()] for line in lines if line and not line.startswith('#')] + assert all(len(row) == len(header) and all(math.isfinite(v) for v in row) for row in rows) + return [dict(zip(header, row)) for row in rows] + + +def independent_metrics(case): + """Recompute unweighted active-Fe residuals from exported Cartesian forces.""" + atoms = [line.split() for line in base.TRAIN_XYZ.splitlines() if line.startswith(('Fe ', 'Ge '))] + values = base.columns(case / 'mforce_test.out', 6) + assert len(values) == len(atoms) + raw = parallel = perp = 0.0 + count = 0 + for atom, row in zip(atoms, values): + if atom[0] != 'Fe': + continue + spin = list(map(float, atom[7:10])) + error = [row[i] - row[3+i] for i in range(3)] + norm2 = sum(v*v for v in error) + length = math.sqrt(sum(v*v for v in spin)) + projection = sum(e*s for e, s in zip(error, spin)) / length if length else 0 + p = projection**2 if length else norm2/3 + raw += norm2; parallel += p; perp += norm2-p; count += 1 + return {'rmse_mforce_test': math.sqrt(raw/(3*count)), + 'rmse_m_parallel_test': math.sqrt(parallel/count), + 'rmse_m_perp_test': math.sqrt(perp/(2*count))} + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--output', type=Path) + parser.add_argument('--oracle', type=Path) + args = parser.parse_args() + visible = os.environ.get('CUDA_VISIBLE_DEVICES', '0,1,2,3').split(',') + assert len(visible) >= 4, 'Four allocated GPUs are required' + env = os.environ.copy(); env['CUDA_VISIBLE_DEVICES'] = visible[0] + common = base.NEP_IN.replace('population 10', 'population 12').replace('generation 1', 'generation 3') + common += 'seed 20261021\nnep_compile 0\nlambda_1 0\nlambda_2 0\n' + split = common.replace('lambda_m 1.0', 'lambda_m_parallel 2\nlambda_m_perp 0.5') + with tempfile.TemporaryDirectory(prefix='spin-mforce-split-') as temp: + root = args.output.resolve() if args.output else Path(temp) + if args.output: root.mkdir(parents=True, exist_ok=False) + report = {'passed': False} + initial = root / 'initial' + base.write_case(initial, common) + run_nep(initial, env) + if args.oracle: + run = subprocess.run([str(args.oracle.resolve())], cwd=initial, env=env, capture_output=True, text=True) + (root / 'oracle.log').write_text(run.stdout + run.stderr) + assert run.returncode == 0, run.stdout + run.stderr + report['numerical_oracle'] = 'passed' + # Require clear parser errors, not an arbitrary runtime failure. + invalid = [ + ('lambda_m_parallel 1', 'Specify both'), + ('lambda_m_perp 1', 'Specify both'), + ('lambda_m 1\nlambda_m_parallel 1\nlambda_m_perp 1', 'Do not combine'), + ('lambda_m_parallel 1\nlambda_m_perp 1\nlambda_mforce 1', 'Do not combine'), + ('lambda_m_parallel 1\nlambda_m_perp 1\nlambda_m_parallel 2', 'Duplicate'), + ('lambda_m_parallel 1 2\nlambda_m_perp 1', '1 parameter'), + ] + for key in ('lambda_m_parallel', 'lambda_m_perp'): + for bad in ('-1', 'nan', 'inf', '1e40'): + other = 'lambda_m_perp' if key.endswith('parallel') else 'lambda_m_parallel' + invalid.append((f'{key} {bad}\n{other} 1', 'finite and non-negative')) + for key, message in [('lambda_tau', 'finite and non-negative'), + ('spin_cutoff', 'finite positive')]: + for bad in ('nan', 'inf', '1e40'): + case = root / f'invalid-{key}-{bad}' + config = common.replace(f'{key} ' + ('0.5' if key == 'lambda_tau' else '6.0'), f'{key} {bad}') + base.write_case(case, config) + run = subprocess.run([str(base.NEP)], cwd=case, env=env, capture_output=True, text=True) + assert run.returncode != 0 and message in run.stdout + run.stderr, (key, bad, run.stdout, run.stderr) + report['nonfinite_torque_cutoff_rejections'] = 6 + for i, (keywords, message) in enumerate(invalid): + case = root / f'invalid-{i}' + base.write_case(case, common.replace('lambda_m 1.0', keywords)) + run = subprocess.run([str(base.NEP)], cwd=case, env=env, capture_output=True, text=True) + assert run.returncode != 0 and message in run.stdout + run.stderr, (keywords, run.stdout, run.stderr) + report['parser_rejections'] = len(invalid) + # Freeze a common parameter vector, including its q scaler and references. + restart = (initial / 'nep.restart').read_text().splitlines() + frozen = '\n'.join(restart[:3]) + '\n' + ''.join(f'{row.split()[0]} 0\n' for row in restart[3:]) + objective = common.replace('lambda_tau 0.5', 'lambda_tau 0') + 'lambda_e 0\nlambda_f 0\nlambda_v 0\n' + terms = [('parallel', 2, 0), ('perp', 0, .5), ('mixed', 2, .5), ('disabled', 0, 0)] + fixed = {}; predictions = [] + for name, lp, lt in terms: + config = objective.replace('lambda_m 1.0', f'lambda_m_parallel {lp}\nlambda_m_perp {lt}') + case = root / name + base.write_case(case, config) + (case / 'test.xyz').write_text(base.TRAIN_XYZ) + shutil.copyfile(initial / 'nep.txt', case / 'nep.txt') + (case / 'nep.restart').write_text(frozen) + run_nep(case, env) + rows = loss_rows(case); row = rows[-1] + oracle = independent_metrics(case) + for key, value in oracle.items(): assert abs(row[key]-value) < 8e-6, (key, row[key], value) + expected = lp * row['rmse_m_parallel_train'] + lt * row['rmse_m_perp_train'] + for result in rows[1:]: + assert abs(result['total'] - expected) < 1.5e-5, (name, result['total'], expected) + predictions.append(base.columns(case / 'mforce_test.out', 3)) + fixed[name] = {'total': row['total'], 'independent_rmse': oracle} + assert all(base.maximum_error(predictions[0], values) == 0 for values in predictions[1:]) + report['frozen_objective_checks'] = fixed + # Ordinary stochastic training, multi-structure batch, and actual saved-model energy. + results = [] + for count in (1, 2, 4): + case = root / f'gpu-{count}' + base.write_case(case, split) + (case / 'test.xyz').write_text(base.TRAIN_XYZ) + run_env = env.copy(); run_env['CUDA_VISIBLE_DEVICES'] = ','.join(visible[:count]) + run_nep(case, run_env) + rows = loss_rows(case); row = rows[-1] + oracle = independent_metrics(case) + for key, value in oracle.items(): assert abs(row[key]-value) < 8e-6, (key, row[key], value) + for suffix in ('train', 'test'): + m = row['rmse_mforce_'+suffix]; p = row['rmse_m_parallel_'+suffix]; t = row['rmse_m_perp_'+suffix] + assert abs(3*m*m-p*p-2*t*t) < 1e-5 + energy = base.columns(case / 'energy_test.out', 2) + assert base.maximum_error([r[1] for r in energy], [-1, -.5, -1.5]) < 1e-12 + raw_e = math.sqrt(sum((r[0]-r[1])**2 for r in energy)/3) + assert raw_e > 1e-5 and abs(raw_e-row['rmse_energy_test']) < 6e-6 + parameters, reference = read_restart(case / 'nep.restart') + results.append({'restart': parameters, 'references': reference, + 'loss': [list(r.values()) for r in rows], + 'energy': energy, 'mforce': base.columns(case / 'mforce_test.out', 6)}) + errors = [] + for result in results[1:]: + error = {key: base.maximum_error(results[0][key], result[key]) for key in result} + assert error['restart'] <= 2e-6 and error['references'] <= 1e-12, error + assert error['loss'] <= 2e-5 and error['energy'] <= 2e-6 and error['mforce'] <= 2e-6, error + errors.append(error) + report['multigpu_max_abs'] = dict(zip(('2', '4'), errors)) + report['passed'] = True + (root / 'report.json').write_text(json.dumps(report, indent=2)) + print(json.dumps(report)) + + +if __name__ == '__main__': + main() diff --git a/tests_pytest/validate_spin_multigpu.py b/tests_pytest/validate_spin_multigpu.py new file mode 100644 index 000000000..87c0bfab6 --- /dev/null +++ b/tests_pytest/validate_spin_multigpu.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +"""Same-system 1/2/4 GPU NEP-Spin checks; run inside one four-GPU allocation. + +Requires numpy. Keeps inputs, per-case logs, and a JSON error ledger under --output. +The single-GPU executable is an independent pre-decomposition build when --reference is supplied. +""" +import argparse, hashlib, json, os, re, shutil, subprocess, time +from pathlib import Path +import numpy as np +from spin_model_format import block_model + +# Componentwise gates: |candidate-reference| <= atol + rtol*|reference|. +# Energy tolerance is per atom and does not scale with the elemental baseline. +GATES = {'potential': (5e-6, 0), 'force': (5e-5, 1e-5), + 'mforce': (5e-6, 1e-5), 'virial': (5e-5, 1e-5), + 'pos': (2e-5, 0), 'vel': (2e-5, 0), 'spin': (3e-5, 0), + 'spin_vel': (3e-5, 0)} + +def sha(path): + return hashlib.sha256(Path(path).read_bytes()).hexdigest() + +def frame(path): + with path.open() as f: + while True: + line = f.readline() + if not line: break + n = int(line); header = f.readline() + props = re.search(r'Properties=([^\s]+)', header).group(1).split(':') + raw = [f.readline().split() for _ in range(n)] + offset = 0; result = {} + for i in range(0, len(props), 3): + key, kind, width = props[i], props[i+1], int(props[i+2]) + key = {'forces': 'force', 'energy_atom': 'potential'}.get(key, key) + if kind != 'S': + result[key] = np.array([r[offset:offset+width] for r in raw], dtype=float) + offset += width + return result + +def compare(left, right, keys): + results = {} + for key in keys: + x, y = left[key], right[key] + assert x.shape == y.shape + assert np.isfinite(x).all() and np.isfinite(y).all(), key + err = np.abs(x-y); atol, rtol = GATES[key] + flat = int(np.argmax(err)); idx = np.unravel_index(flat, err.shape) + result = {'max_abs': float(err.max()), 'rms': float(np.sqrt(np.mean(err**2))), + 'max_rel_floor_1e-3': float(np.max(err / np.maximum(np.abs(y), 1e-3))), + 'worst_index': list(map(int, idx)), 'reference': float(y[idx]), + 'candidate': float(x[idx]), 'atol': atol, 'rtol': rtol, + 'exceedances': int(np.sum(err > atol+rtol*np.abs(y)))} + if key in ('potential','virial','force','mforce'): + result['sum_delta'] = (x.sum(axis=0)-y.sum(axis=0)).tolist() + results[key] = result + return results + +def write_xyz(path, positions, spins, cell, velocity=None, species=None): + if velocity is None: velocity = np.zeros_like(positions) + n = len(positions) + with path.open('w') as f: + f.write(str(n)+'\nLattice="'+' '.join(map(str,cell.ravel()))+'" ' + 'Properties=species:S:1:pos:R:3:vel:R:3:spin:R:3:spin_vel:R:3:group:I:1 pbc="T T T"\n') + for i,(r,v,s) in enumerate(zip(positions,velocity,spins)): + symbol = species[i] if species is not None else 'Fe' + f.write(symbol+' '+' '.join(f'{x:.15g}' for x in np.r_[r,v,s,[0,0,0]])+f' {i%2}\n') + +def structure(dims=(48,12,12), variant='bcc'): + rng = np.random.default_rng(813) + a = 2.8402441439 + ijk = np.indices(dims).reshape(3,-1).T + pos = np.vstack((ijk,ijk+0.5))*a + cell = np.diag(np.array(dims)*a) + pos += rng.uniform(-0.012,0.012,pos.shape) + pos %= np.diag(cell) + if variant == 'nonuniform': + keep = (pos[:,0] < cell[0,0]*.42) | (rng.random(len(pos)) < .32) + pos = pos[keep] + if variant == 'triclinic': + frac = pos / np.diag(cell) + cell[1,0] = 5.4; cell[2,1] = 2.8 + pos = frac @ cell + spin = np.tile([0.,0.,2.4],(len(pos),1)) + rng.uniform(-.25,.25,pos.shape) + velocity = rng.normal(0,.0012,pos.shape) + velocity -= velocity.mean(axis=0) + return pos,spin,cell,velocity + +def execute(args, name, xyz, gpus, ensemble='nve', steps=1, dt=0, field='', direction='', reference=False): + path = args.output/name; path.mkdir() + shutil.copyfile(args.model,path/'nep.txt'); shutil.copyfile(xyz,path/'model.xyz') + run = (f'potential nep.txt{(" "+direction) if direction else ""}\n' + f'ensemble {ensemble}\ntime_step {dt}\n'+field+ + f'dump_xyz {steps} state.xyz precision double velocity force potential spin mforce spin_velocity virial\nrun {steps}\n') + (path/'run.in').write_text(run) + env = dict(os.environ); env['CUDA_VISIBLE_DEVICES'] = ','.join(args.devices[:gpus]) + exe = args.reference if reference and args.reference else args.binary + start=time.perf_counter() + with (path/'run.log').open('w') as log: + proc=subprocess.run([str(exe)],cwd=path,env=env,stdout=log,stderr=subprocess.STDOUT) + if proc.returncode: raise RuntimeError(f'{name}: exit {proc.returncode}: {path}/run.log') + return frame(path/'state.xyz'),time.perf_counter()-start + +def main(): + p=argparse.ArgumentParser();p.add_argument('--binary',type=Path,required=True) + p.add_argument('--reference',type=Path);p.add_argument('--model',type=Path,required=True) + p.add_argument('--output',type=Path,required=True) + p.add_argument('--block-format',action='store_true', + help='Convert the legacy fixture and check format/reference invariance.') + a=p.parse_args() + for key in ['binary','reference','model','output']: + if getattr(a,key):setattr(a,key,getattr(a,key).resolve()) + a.output.mkdir(parents=True,exist_ok=False) + a.devices=os.environ.get('CUDA_VISIBLE_DEVICES','0,1,2,3').split(',') + if len(a.devices)<4:raise RuntimeError('Requires four allocated GPUs') + report={'gates':GATES,'binary_sha256':sha(a.binary),'model_sha256':sha(a.model), + 'reference_sha256':sha(a.reference) if a.reference else None, + 'block_format':a.block_format,'cases':{}} + def save(): + (a.output/'report.json').write_text(json.dumps(report,indent=2)) + def record(name,candidate,ref,keys): + result=compare(candidate,ref,keys);report['cases'][name]=result;save() + bad={k:v for k,v in result.items() if v['exceedances']} + if bad:raise AssertionError((name,bad)) + print(name,'PASS',flush=True) + xyz=a.output/'input.xyz' + outputs=['potential','force','mforce','virial'] + if a.block_format: + legacy_model = a.model + model = block_model(legacy_model.read_text()) + converted = a.output/'block.nep'; converted.write_text(model) + report['block_model_sha256'] = sha(converted) + # Both elements appear on every slab; use a large cell to exercise the + # actual decomposition rather than its small-box fallback. + pos,spin,cell,vel=structure((48,8,8)) + symbols=legacy_model.read_text().splitlines()[0].split()[2:] + species=np.array([symbols[i % len(symbols)] for i in range(len(pos))]) + write_xyz(xyz,pos,spin,cell,vel,species) + ref,_=execute(a,'format-legacy-reference',xyz,1) + reference_line=next(line for line in model.splitlines() if line.startswith('energy_reference ')) + original=np.array(list(map(float,reference_line.split()[1:]))) + shifts=np.array([(-1)**i*(100000.123456789+i*100000.864197532) + for i in range(len(symbols))]) + shifted=a.output/'shifted.nep' + shifted.write_text(model.replace(reference_line,'energy_reference '+ + ' '.join(f'{v:.17g}' for v in original+shifts),1)) + atom_shift=np.array([shifts[i % len(symbols)] for i in range(len(pos))])[:,None] + for g in [1,2,4]: + a.model=converted + out,_=execute(a,f'format-block-g{g}',xyz,g) + record(f'format-block-g{g}',out,ref,outputs) + if g > 1: + repeated,_=execute(a,f'format-repeat-g{g}',xyz,g) + record(f'format-repeat-g{g}',repeated,out,outputs) + a.model=shifted + shifted_out,_=execute(a,f'energy-reference-g{g}',xyz,g) + shifted_out['potential']-=atom_shift + record(f'energy-reference-g{g}',shifted_out,out,outputs) + # Multi-GPU cell-list ordering varies between launches. Keep the + # established componentwise gates above and record a repeat control; + # the single-GPU path also supports a strict derivative check. + if g == 1: + for key in ['force','mforce','virial']: + if np.max(np.abs(shifted_out[key]-out[key]))>1e-10: + raise AssertionError(f'Energy reference changed {key} on {g} GPUs') + a.model=converted + for variant in ['bcc','nonuniform','triclinic','small','cutoff']: + if variant=='cutoff': + # Isolated pairs just inside/outside the 6 A cutoff, including slab/PBC faces. + cell=np.diag([144.,24.,24.]);pos=[] + for k,x in enumerate([0.,33.,69.,105.]): + for j,eps in enumerate([-1e-5,0,1e-5]): + pos.extend([[x,4+8*j,4],[((x+6+eps)%144),4+8*j,4]]) + pos=np.array(pos);spin=np.tile([.3,.4,2.35],(len(pos),1));vel=np.zeros_like(pos) + else: + pos,spin,cell,vel=structure((2,2,2) if variant=='small' else (48,12,12),variant) + write_xyz(xyz,pos,spin,cell,vel) + ref,_=execute(a,variant+'-reference',xyz,1,reference=True) + for g in [1,2,4]: + out,_=execute(a,f'{variant}-g{g}',xyz,g) + record(f'{variant}-g{g}',out,ref,outputs) + if variant=='bcc': + for d in ['x','y','z']: + out,_=execute(a,f'{variant}-{d}',xyz,4,direction=d) + record(f'{variant}-{d}',out,ref,outputs) + pos,spin,cell,vel=structure((36,8,8));write_xyz(xyz,pos,spin,cell,vel) + ensembles={'tspin': 'nvt_tspin 100 100 100 mass_factor Fe 0.01 seed 731', 'npt_tspin': 'npt_tspin temp 100 100 iso 0 0 tperiod 100 pperiod 1000 mass_factor Fe 0.01 seed 731'} + for label,ens in ensembles.items(): + field=('add_mfield region 0.3 0.7 0 1 0 1 7 -3 4\n' + if label.startswith('npt') else 'add_mfield 0 1 7 -3 4\n') + ref,_=execute(a,label+'-reference',xyz,1,ens,20,.1,field,reference=True) + for g in [1,2,4]: + out,_=execute(a,f'{label}-g{g}',xyz,g,ens,20,.1,field) + record(f'{label}-g{g}',out,ref,outputs+['pos','vel','spin','spin_vel']) + if 'sib' in label: + norm_error=float(np.max(np.abs(np.linalg.norm(out['spin'],axis=1)-np.linalg.norm(spin,axis=1)))) + report['cases'][f'{label}-g{g}']['spin_norm_max_abs']=norm_error + if norm_error>1e-7:raise AssertionError(norm_error) + # Uniform translation across slab/PBC faces exceeds the cached-partition + # displacement limit twice. Spin and force outputs must follow atom identity. + pos,spin,cell,vel=structure((48,8,8));vel[:]=[.75,0,0] + write_xyz(xyz,pos,spin,cell,vel) + ref,_=execute(a,'migration-reference',xyz,1,'nve',40,.1,reference=True) + for g in [1,2,4]: + out,_=execute(a,f'migration-g{g}',xyz,g,'nve',40,.1) + record(f'migration-g{g}',out,ref,outputs+['pos','vel','spin','spin_vel']) + delta=out['pos']-pos;delta-=np.rint(delta/np.diag(cell))*np.diag(cell) + assert delta[:,0].min()>2.5, 'Migration probe must exceed the partition rebuild limit' + report['passed']=True;save() + +if __name__=='__main__':main() diff --git a/tests_pytest/validate_spin_training_lifecycle.py b/tests_pytest/validate_spin_training_lifecycle.py new file mode 100644 index 000000000..0e2f48ba3 --- /dev/null +++ b/tests_pytest/validate_spin_training_lifecycle.py @@ -0,0 +1,278 @@ +#!/usr/bin/env python3 +"""Exercise Spin checkpoint/export contracts through the real NEP and GPUMD CLIs.""" +import json +import math +import re +import tempfile +from pathlib import Path + +import validate_main_nep_spin3_training as base + +CONFIG = base.NEP_IN + "nep_compile 0\nseed 20261021\n" +NO_MASKS = re.sub(r"^spin_(dof|env)_type.*\n", "", CONFIG, flags=re.M) + + +def execute(directory, config, xyz=base.TRAIN_XYZ, model=None, restart=None, error=None, test_xyz=None): + base.write_case(directory, config, xyz) + if test_xyz is not None: + (directory / "test.xyz").write_text(test_xyz) + if model is not None: + (directory / "nep.txt").write_text(model) + if restart is not None: + (directory / "nep.restart").write_text(restart) + result = base.run(base.NEP, directory) + output = result.stdout + result.stderr + (directory / "run.log").write_text(output) + if error: + assert result.returncode and error in output, output + elif result.returncode: + raise AssertionError(output) + return output + + +def predict(directory, model, xyz=base.TRAIN_XYZ, config=NO_MASKS): + execute(directory, config + "prediction 1\n", xyz, model) + return {name: base.columns(directory / f"{name}_train.out", width) + for name, width in (("energy", 1), ("force", 3), ("virial", 6), ("mforce", 3))} + + +def compare(left, right): + errors = {} + for name in left: + error = base.maximum_error(left[name], right[name]) + assert math.isfinite(error) and error <= base.parity_tolerance(left[name], right[name]), (name, error) + errors[name] = error + return errors + + +def metadata(model): + lines = model.splitlines() + stop = next(i for i, line in enumerate(lines) if line.startswith('@ ')) + return dict((line.split()[0], line.split()[1:]) for line in lines[:stop] + if line.startswith(('spin_', 'energy_reference '))) + + +def runtime_mforce(directory, model, reference): + directory.mkdir() + (directory / "nep.txt").write_text(model) + (directory / "model.xyz").write_text("\n".join(base.TRAIN_XYZ.splitlines()[:6]) + "\n") + (directory / "run.in").write_text( + "potential nep.txt\nvelocity 1\nensemble nve\ntime_step 0\n" + "dump_xyz 1 result.xyz force potential spin mforce virial precision double\nrun 1\n") + result = base.run(base.GPUMD, directory) + assert result.returncode == 0, result.stdout + result.stderr + rows = [[float(x) for x in line.split()[1:]] + for line in (directory / "result.xyz").read_text().splitlines()[-4:]] + return compare({"mforce": reference["mforce"][:4]}, {"mforce": [r[9:12] for r in rows]}) + + +def strip_labels(xyz, frames): + lines = xyz.splitlines() + for frame in frames: + start = frame * 6 + lines[start+1] = lines[start+1].replace(":mforce:R:3", "") + for a in range(start+2, start+6): + lines[a] = " ".join(lines[a].split()[:-3]) + return "\n".join(lines) + "\n" + + +def scalers(model): + lines = model.splitlines() + start = next(i for i, line in enumerate(lines) if line.startswith("@ q_scaler ")) + count = int(lines[start].split()[2]) + return [float(line) for line in lines[start+1:start+1+count]] + + +def validate_initial_para(root): + root.mkdir() + # Twelve candidates also support 2/4-GPU partitions. Larger spins exercise + # magnetic normalization below its gain cap, not just capped unit scalers. + config = CONFIG.replace("population 10", "population 12") + lines = base.TRAIN_XYZ.splitlines() + for i, line in enumerate(lines): + if i % 6 >= 2: + fields = line.split() + fields[7:10] = [str(4 * float(x)) for x in fields[7:10]] + lines[i] = " ".join(fields) + xyz = "\n".join(lines) + "\n" + execute(root / "default", config, xyz) + model = (root / "default" / "nep.txt").read_text() + default = scalers(model) + execute(root / "explicit_one", config + "initial_para 1\n", xyz) + for filename in ("nep.txt", "nep.restart"): + assert (root / "default" / filename).read_bytes() == (root / "explicit_one" / filename).read_bytes() + report = {"default_vs_one": "identical model and search state"} + for value in (0.5, 0.1): + case = root / str(value) + execute(case, config + f"initial_para {value}\n", xyz) + scaled = scalers((case / "nep.txt").read_text()) + assert len(default) == len(scaled) + assert all(math.isfinite(x) and x > 0 for x in scaled) + # n_max=0, l_max=2: one linear radial and two quadratic angular + # structural components give independent, known normalization ratios. + ratios = [scaled[i] / default[i] for i in range(3)] + for ratio, degree in zip(ratios, (1, 2, 2)): + assert math.isclose(ratio, value ** -degree, rel_tol=2e-5), ratios + assert all(x <= 1 for x in scaled[3:]) + assert any(abs(a-b) > 1e-5 for a, b in zip(default[3:], scaled[3:])) + report[str(value)] = {"structural_scaler_ratios": ratios, + "magnetic_scaler_max": max(scaled[3:])} + + changed = config + "initial_para 0.5\n" + before = predict(root / "before", model, xyz, config) + report["prediction"] = compare(before, predict(root / "after", model, xyz, changed)) + restart = (root / "default" / "nep.restart").read_text() + for mode, extra, state in (("restart", "", restart), ("import", "import_q_scaler 1\n", None)): + case = root / mode + execute(case, changed + extra, xyz, model=model, restart=state) + assert scalers((case / "nep.txt").read_text()) == default + report[mode] = "saved scalers preserved" + for value in ("nan", "inf", "0", "1.1"): + execute(root / ("invalid_" + value), config + f"initial_para {value}\n", xyz, + error="initial_para should be within [0.1, 1]") + report["invalid_values"] = "rejected" + return report + + +def validate(root): + report = {"initial_para": validate_initial_para(root / "initial_para")} + for name, config in (("fe_env_all", CONFIG), + ("fe_env_fe", CONFIG.replace("spin_env_type Fe Ge", "spin_env_type Fe"))): + fresh = root / name + execute(fresh, config) + model = (fresh / "nep.txt").read_text() + assert "\nmodel nep_spin\n" in model and "\nspin_version 1\n" in model + assert "\nspin_mode " not in model + old = predict(root / (name + "_before"), model) + # Freeze the exported elite in the shared reference-aware restart format. + lines = model.splitlines() + start = next(i for i, line in enumerate(lines) if line.startswith("@ parameters ")) + count = int(lines[start].split()[2]) + reference = metadata(model)["energy_reference"] + frozen = ("nep_restart\nenergy_reference " + str(len(reference)) + " " + " ".join(reference) + + f"\nparameters {count}\n" + + "".join(f"{x} 0\n" for x in lines[start+1:start+1+count])) + resumed = root / (name + "_resume") + execute(resumed, NO_MASKS.replace("generation 1", "generation 2"), model=model, restart=frozen) + snapshots = list(resumed.glob("nep_gen*.txt")) + assert len(snapshots) == 2, list(resumed.iterdir()) + saved = (resumed / "nep.txt").read_text() + assert metadata(saved) == metadata(model), (metadata(saved), metadata(model)) + after = predict(root / (name + "_after"), saved) + report[name] = compare(old, after) + imported = root / (name + "_import") + execute(imported, NO_MASKS + "import_q_scaler 1\n", model=model) + assert metadata((imported / "nep.txt").read_text()) == metadata(model) + # An exported import model must also be accepted with omitted input masks. + predict(root / (name + "_import_reload"), (imported / "nep.txt").read_text()) + if name == "fe_env_fe": + # The subset environment is distinct from the all-environment cases + # exercised by the main training/runtime parity suite. + report[name + "_md"] = runtime_mforce(root / (name + "_md"), saved, after) + execute(root / "partial_env", NO_MASKS + "spin_env_type Fe\n", model=model, restart=frozen) + execute(root / "invalid_fresh_subset", NO_MASKS + "spin_env_type Fe\n", + error="spin_dof_type must be a subset") + if name == "fe_env_all": + alias_config = config.replace("spin_version 1", "spin_mode 3") + alias_fresh = root / "legacy_input_fresh" + execute(alias_fresh, alias_config) + assert (alias_fresh / "nep.txt").read_text() == model + assert (alias_fresh / "nep.restart").read_text() == (fresh / "nep.restart").read_text() + report["legacy_input_training"] = "identical model and search state" + # The previous block header has identical numerical payload and restart indexing. + legacy_model = model.replace("model nep_spin\n", "model nep_spin3\n").replace( + "spin_version 1\n", "spin_mode 3\n") + legacy_prediction = predict(root / "old_block_prediction", legacy_model) + report["old_block_prediction"] = compare(old, legacy_prediction) + legacy_resume = root / "old_block_resume" + execute(legacy_resume, NO_MASKS.replace("generation 1", "generation 2"), + model=legacy_model, restart=frozen) + migrated = (legacy_resume / "nep.txt").read_text() + assert "\nmodel nep_spin\n" in migrated and "\nspin_mode " not in migrated + assert metadata(migrated) == metadata(model) + report["old_block_resume"] = compare(old, predict(root / "migrated_prediction", migrated)) + # Detailed format rejection belongs to the CPU codec suite; keep + # one real CLI check that the model reader propagates the failure. + execute(root / "unsupported_version", NO_MASKS + "prediction 1\n", + model=model.replace("spin_version 1\n", "spin_version 2\n"), + error="Unsupported spin_version") + for keyword, value in (("spin_dof_type", "Ge"), ("spin_env_type", "Fe")): + execute(root / (name + keyword), NO_MASKS + ("spin_dof_type Fe\n" if keyword == "spin_env_type" else "") + f"{keyword} {value}\n", + model=model, restart=frozen, error=f"{keyword} in nep.in conflicts") + + model = (root / "fe_env_all" / "nep.txt").read_text() + reference = predict(root / "labeled", model) + for name, frames in (("unlabeled", (0, 1, 2)), ("mixed", (0, 2))): + xyz = strip_labels(base.TRAIN_XYZ, frames) + directory = root / name + report[name] = compare(reference, predict(directory, model, xyz)) + rows = base.columns(directory / "mforce_train.out", 6) + assert len(rows) == 12 + for frame in frames: + assert all(row[3:] == [0, 0, 0] for row in rows[frame*4:frame*4+4]) + # Training diagnostics continue to contain only supervised configurations. + trained = root / (name + "_training") + execute(trained, CONFIG, xyz, test_xyz=xyz) + assert len((trained / "mforce_test.out").read_text().splitlines()) == 4 * (3-len(frames)) + + # Small periodic cells force image neighbors. pbc strings are deliberately ignored. + small = base.TRAIN_XYZ.replace('24 0 0 0 24 0 0 0 24', '4 0 0 0 4 0 0 0 4') + periodic = predict(root / "pbc_default", model, small) + for flag in ("F F F", "T T F"): + xyz = small.replace("Properties=", f'pbc="{flag}" Properties=') + report[flag] = compare(periodic, predict(root / flag.replace(" ", ""), model, xyz)) + report["ediff"] = validate_ediff(root / "ediff") + return report + + +def validate_ediff(directory): + # Interleaved groups force grouped batching to reorder frames, while spins + # distinguish equal geometries. Distinct targets detect label-map mistakes. + frames = [] + for index, name in enumerate(("a", "c", "b", "d")): + frame = base.TRAIN_XYZ.splitlines()[:6] + frame[1] = frame[1].replace("energy=-4.0", f"energy={-4+index}.0") + f" name={name}" + fields = frame[2].split() + fields[7:10] = [str(math.cos(index)), str(math.sin(index)), "0"] + fields[10:13] = [str(index+1), str(index+2), str(index+3)] + frame[2] = " ".join(fields) + frames.append(frame) + xyz = "\n".join(line for frame in frames for line in frame) + "\n" + base.write_case(directory, CONFIG.replace("batch 3", "batch 2").replace("generation 1", "generation 2") + "lambda_d 0.1\n", xyz) + (directory / "ediff.in").write_text("a - b\nc - d\n") + (directory / "test.xyz").write_text(xyz) + result = base.run(base.NEP, directory) + assert result.returncode == 0, result.stdout + result.stderr + loss = [[float(x) for x in line.split()] for line in + (directory / "loss.out").read_text().splitlines() + if line.strip() and not line.startswith("#")][-1] + energy = base.columns(directory / "energy_test.out", 2) + residuals = [4 * ((energy[a][0]-energy[b][0]) - (energy[a][1]-energy[b][1])) + for a, b in ((0, 2), (1, 3))] + expected = math.sqrt(sum(x*x for x in residuals)/2) + assert abs(loss[-1] - expected) < 2e-4, (loss, expected) + targets = base.columns(directory / "mforce_test.out", 6) + # Reconstruct the final training batch loss independently from predictions + # in file order. Both ediff and magnetic errors must identify the same pair. + pair_errors = [] + for a, b in ((0, 2), (1, 3)): + error2 = sum((row[c] - row[c+3])**2 + for i in (a, b) for row in targets[4*i:4*i+2] for c in range(3)) + pair_errors.append(math.sqrt(error2/12)) + assert any(abs(loss[7]-m) < 2e-4 and abs(loss[14]-abs(e)) < 2e-4 + for m, e in zip(pair_errors, residuals)), (loss, pair_errors, residuals) + assert [targets[4*i][3:] for i in range(4)] == [[i+1, i+2, i+3] for i in range(4)] + saved = (directory / "nep.txt").read_text() + prediction = predict(directory / "prediction", saved, xyz) + compare({"mforce": [row[:3] for row in targets]}, {"mforce": prediction["mforce"]}) + # No special acceptance of genuinely identical geometry+spin pairs. + frames[2][2] = frames[0][2] + (directory / "train.xyz").write_text("\n".join(line for frame in frames for line in frame) + "\n") + result = base.run(base.NEP, directory) + assert result.returncode and "same geometry and spins" in result.stdout + result.stderr + return {"test_rmse": loss[-1], "independent_rmse": expected, "original_label_order": "passed"} + + +if __name__ == "__main__": + with tempfile.TemporaryDirectory(prefix="spin-lifecycle-") as temporary: + print(json.dumps(validate(Path(temporary)), indent=2, sort_keys=True)) diff --git a/tests_pytest/validate_spin_training_multigpu.py b/tests_pytest/validate_spin_training_multigpu.py new file mode 100644 index 000000000..567bbc5e0 --- /dev/null +++ b/tests_pytest/validate_spin_training_multigpu.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +"""Check 1/2/4-GPU training parity and exported-model energy on three structures. + +Keep batch=1 as a centered-loss negative control; batch=3 exercises energy fitting. +The short synthetic run is a regression check, not a production accuracy target. +""" +import argparse +import json +import math +import os +from pathlib import Path +import re +import shutil +import subprocess +import tempfile +import validate_main_nep_spin3_training as base + + +def run_nep(case, env): + run = subprocess.run([str(base.NEP)], cwd=case, env=env, text=True, capture_output=True) + (case / 'run.log').write_text(run.stdout + run.stderr) + if run.returncode: + raise RuntimeError(f'{case}:\n{run.stdout}{run.stderr}') + + +def check_exported_energy(case, config, env, loss, batch): + prediction = case / 'prediction' + prediction_config = re.sub( + r'^(population|generation|output_interval|save_potential|lambda_spin_response).*$', + '', config, flags=re.MULTILINE) + prediction_config = prediction_config.replace('version 4', 'version 4\nprediction 1') + base.write_case(prediction, prediction_config) + shutil.copyfile(case / 'nep.txt', prediction / 'nep.txt') + run_nep(prediction, env) + values = base.columns(prediction / 'energy_train.out', 2) + # Independent labels for the three structures in base.TRAIN_XYZ, in eV/atom. + # This also catches reference energies accidentally left out of output labels. + assert len(values) == 3 and all(len(row) == 2 for row in values), values + assert all(math.isfinite(v) for v in base.flatten(values)), values + assert base.maximum_error([row[1] for row in values], [-1.0, -0.5, -1.5]) < 1e-12 + errors = [predicted - label for predicted, label in values] + # Do not subtract a fitted mean: check the saved model's actual predictions. + raw_rmse = math.sqrt(sum(error * error for error in errors) / len(errors)) + mean_error = sum(errors) / len(errors) + logged = [row[4] for row in loss] + if batch == 3: + assert all(value > 1e-5 for value in logged), ('energy loss is inactive', logged) + # loss.out has five decimal places; allow its rounding and model serialization. + assert abs(raw_rmse - logged[-1]) <= 6e-6, (raw_rmse, logged[-1]) + assert abs(mean_error) <= 2e-6, mean_error + # Bounded regression guard for this fixed-seed three-generation fixture. + assert raw_rmse <= 0.1, raw_rmse + else: + assert all(value == 0 for value in logged), logged + assert raw_rmse > 1e-5, 'The batch=1 negative control must expose hidden energy error' + return values, {'logged_energy_rmse': logged, 'raw_energy_rmse': raw_rmse, + 'mean_energy_error': mean_error, 'prediction_and_label': values} + + +def read_restart(path): + lines = path.read_text().splitlines() + assert lines[0] == 'nep_restart', lines[0] + reference = lines[1].split() + assert reference[0] == 'energy_reference' + assert int(reference[1]) == len(reference) - 2 + count = lines[2].split() + assert count[0] == 'parameters' + parameters = [[float(v) for v in row.split()] for row in lines[3:]] + assert len(parameters) == int(count[1]) + assert all(len(row) == 2 for row in parameters) + return parameters, list(map(float, reference[2:])) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--output', type=Path) + args = parser.parse_args() + visible = os.environ.get('CUDA_VISIBLE_DEVICES', '0,1,2,3').split(',') + if len(visible) < 4: + raise RuntimeError('This test requires four allocated CUDA devices.') + common_config = base.NEP_IN.replace('generation 1', 'generation 3') + common_config = common_config.replace('population 10', 'population 12') + common_config += 'lambda_spin_response 0.3\nnep_compile 0\nseed 20261021\n' + with tempfile.TemporaryDirectory(prefix='spin-training-multigpu-') as temporary: + root = args.output.resolve() if args.output else Path(temporary) + if args.output: + root.mkdir(parents=True, exist_ok=False) + report = {'passed': False, 'devices': [1, 2, 4], 'population': 12, + 'generations': 3, 'energy_units': 'eV/atom', 'batches': {}} + for batch in (1, 3): + config = common_config.replace('batch 3', f'batch {batch}') + batch_root = root / f'batch-{batch}' + batch_root.mkdir() + results = [] + energies = {} + for devices in (visible[:1], visible[:2], visible[:4]): + case = batch_root / str(len(devices)) + base.write_case(case, config) + (case / 'response.xyz').write_text(base.response_xyz()) + env = os.environ.copy() + env['CUDA_VISIBLE_DEVICES'] = ','.join(devices) + run_nep(case, env) + parameters, references = read_restart(case / 'nep.restart') + loss = [[float(v) for v in row.split()] + for row in (case / 'loss.out').read_text().splitlines() + if row and not row.startswith('#')] + assert len(loss) == 3 and all(len(row) == 14 for row in loss), loss + predictions, energies[str(len(devices))] = check_exported_energy( + case, config, env, loss, batch) + results.append({'restart': parameters, 'energy_reference': references, + 'loss': loss, 'energy_predictions': predictions}) + assert all(math.isfinite(v) for result in results for value in result.values() + for v in base.flatten(value)) + errors = {} + for devices, result in zip([2, 4], results[1:]): + error = {key: base.maximum_error(results[0][key], result[key]) for key in result} + assert error['restart'] <= 2e-6, error + assert error['loss'] <= 2e-5, error + assert error['energy_reference'] <= 1e-12, error + assert error['energy_predictions'] <= 2e-6, error + errors[str(devices)] = error + report['batches'][str(batch)] = { + 'energy_reference': results[0]['energy_reference'], + 'max_abs': errors, 'energy': energies} + (root / 'report.json').write_text(json.dumps(report, indent=2)) + report['passed'] = True + (root / 'report.json').write_text(json.dumps(report, indent=2)) + print(json.dumps(report)) + + +if __name__ == '__main__': + main()