... | ... | @@ -17,42 +17,6 @@ The input contains two files: |
|
|
- `pair_style lj/charmm/coul/long 8.0 10.0` This is the line that specifies that we are using the *lj/charmm/coul/charmm* *pair_style*. If a different *pair_style* was selected, then `PairLJCharmmCoulLong::compute` would not be executed, and the optimizations would not have any impact. Moreover, the `8.0`and `10.0` represent the *cutoff distances*, which can have an impact to the execution of the function. For more information, check the LAMMPS [documentation](https://docs.lammps.org/pair_charmm.html#pair-style-lj-charmm-coul-long-command).
|
|
|
- `data.protein`: contains the initial data for the atoms in the simulation and their properties
|
|
|
|
|
|
### Handling union_int_float_t
|
|
|
|
|
|
`PairLJCharmmCoulLong::compute` defines an union type `union_int_float_t` in order to be able with operate with the bits of a 32bit floating point number `rsq` as if it was a 32-bit integer.
|
|
|
Since the `union` construct cannot be used with RISC-V intrinsic data types, an inline assembler block with a `vmv.v.v` instruction was used instead.
|
|
|
the code snippet shows how the data can be successfully moved from a floating point data type to an integer data type.
|
|
|
|
|
|
```c++
|
|
|
__epi_1xf64 vecrsq;
|
|
|
__epi_1xi64 vecitable;
|
|
|
// vecitable <- vecrsq
|
|
|
__asm__ (
|
|
|
"nop\n\t"
|
|
|
"vmv.v.v %0, %1\n\t"
|
|
|
: "=vr" (vecitable)
|
|
|
: "vr" (vecrsq)
|
|
|
);
|
|
|
```
|
|
|
|
|
|
The downside of this `vmv.v.v`method is that it adds a redundant instruction, since is not actually needed to move data from a register to another, it should be enough just to interpret it as another type.
|
|
|
There is an intrinsic that allows converting between mask and integer vector without performing any operation, but not between integer and floating point, although it follows the same underlying principle (conversion between data types with same SEW).
|
|
|
|
|
|
After the conversion, then, some bit manipulation is performed on the result.
|
|
|
This becomes an issue, since in the code it was performed with 32-bit data types, and we use 64-bit data types.
|
|
|
To overcome this, we need to convert the bitmask and the shift value from 32 to 64 bits.
|
|
|
It cannot be done statically, since these values are generated in generated in `pair.cpp:init_bitmap` based to the settings specified in the input, so a small extra piece of code is needed.
|
|
|
|
|
|
Since the extracted bit fields are centered at the start of the mantissa, in order to convert the mask and shift value to 64-bit, it is enough to shift and add `(DBL_MANT_DIG - FLT_MANT_DIG)`, which corresponds to the increase of size of the mantissa when switching from single to double precision.
|
|
|
Here, we show the code snippet with the transformation to the mask and shift value and a representation of the bit manipulation performed.
|
|
|
|
|
|
```
|
|
|
ncoulmask64 = ((long) ncoulmask) << (DBL_MANT_DIG - FLT_MANT_DIG);
|
|
|
ncoulshiftbits64 = ncoulshiftbits + (DBL_MANT_DIG - FLT_MANT_DIG);
|
|
|
```
|
|
|
|
|
|
![lammps_union_mask](uploads/483b72359d0e41d0b754be1518ff2383/lammps_union_mask.png)
|
|
|
|
|
|
|
|
|
atom_vec.h -> contains `**x` and `**f` (3D)
|
|
|
neigh_list.h -> contains `**firstneigh` (for each i, store array of neighbors j)
|
... | ... | |