Although the rotated XH bond vector and atomic position code was very fast, the amount of memory
needed to store these in the spin containers and interatomic data containers was huge when N > 1e6.
The subsequent rdc.back_calc and pcs.back_calc user function calls would also take far too long.
Therefore the base script has been redesigned. The _create_distribution() method has been split
into four: _calculate_pcs(), _calculate_rdc(), _create_distribution(), and _pipe_setup().
The _pipe_setup() method is called first to set up the data pipe with all required data. Then the
_calculate_rdc() and _calculate_pcs() methods, and finally _create_distribution() if the DIST_PDB
flag is set.
The calls to the rdc.back_calc and pcs.back_calc user functions have been eliminated. Instead the
_calculate_rdc() and _calculate_pcs() methods calculate the averaged RDC and PCS themselves as numpy
array structures. Rather than storing the huge rotated vectors and atomic positions data
structures, the RDCs and PCSs are summed. These are then divided by self.N at the end to average
the values.
Compared to the old code, when N is set to 20 million the RAM usage drops from ~20 GB to ~65 MB.
The total run time is also decreased on one system from a few days to a few hours (an order or two
of magnitude).