A Request for Intermediate Scattering function
Description
The intermediate scattering function is defined as the Fourier transform of the Van Hove function:
Instead of Fourier transform, these functions can also be directly computed from the atomic trajectories:
Fs and Fd are self and distinct parts.
Is there any plan to support this function? Otherwise, I can write one following structure factor code and MSD part.
Proposed Solution
isf = freud.Scattering.Intermedidate(k_space, ...)
# points = (N_frames, N_particles, 3)
# points = (N_frames, M_particles, 3)
isf.compute((box, points)).query(query_points)
isf.self_part
isf.distinct_part
Additional Context
Reference: https://www.lehigh.edu/imi/teched/AtModel/Lecture_11_Micoulaut_Atomistics_Glass_Course.pdf
Developer
Would someone else please implement this?
This seems like a reasonable feature to add to freud. This function has a time-dependence to it. We have only one other analysis, MSD, in freud which computes a function with explicit time dependence, so the API should mirror that and take the box as a parameter to the constructor, and then give a 3-dimensional array of positions to the compute method.
In addition, it will be important to average over k-vectors properly. A good example to work from is in the StaticStructureFactorDirect class.
With all of those things in mind, here's how I would propose the new class to look, along with all the properties that make sense to expose:
isf = freud.diffraction.IntermediateScattering(box, k_max, k_min, num_sampled_k_points)
isf.compute(points, query_points, N_total, reset)
# access properties
isf.k_max
isf.k_min
isf.k_points
isf.nbins
isf.num_sampled_k_points
isf.min_valid_k
isf.bounds
isf.bin_edges
isf.bin_centers
isf.self_function
isf.distinct_function
The query_points and N_total in the compute method are only needed when computing partial scattering functions. It would be completely okay to ignore that and just compute full scattering functions in a PR that creates the class, then come back later and implement partials only if necessary.
@Roy-Kid How comfortable would you be trying to implement this yourself? It's not a simple calculation to write, but I would be able to assist to get past roadblocks in implementation.
Thanks for your concern.
I have started to read the source code of StaticStructureFactorDirect and msd and hope to combine those together. I think the difficulty is to understand the code about how to contracture reciprocal space.
I am try to do this work, but i'm not sure I can complete or give a robust code.
Okay. The sampling of reciprocal space is done in StaticStructureFactorDirect::reciprocal_isotropic, that code should actually be reused for this new feature, because the sampling method will be the same.
When I have the time, I can assist with getting some of the boilerplate code and class structure in place first and then we can work more on implementation from after that.
@tommy-waltmann Hi waltmann,
I start a PR as a start for intermediate scattering calculation. I write boilerplate code for both python and c++. Here is my plan:
- We derive/extend the
StaticStructureFactorDirectclass to usereciprocal_isotropiccompute_F_ketc. - Since the isf is time-dependent and reply on
r(t=0), so we record the position of first frame, and construct a neighborlist byAABQUERY((box, point)).query(r(t=0)). - The neighborlist computes the all distance between all particles and there should be a method to separate "self-distance" and "distinct-distance" (I think it can be done by the construct a index filter).
- When we get the
r_i_t - r_i_t0andr_i_t - r_j_t0, we can reuse thecompute_F_kto compute exponent factor. - To compute F(k, t), we need to pass all frames to compute method in python like what MSD does. The inner for loop accumulate the isf result one-by-one frame.
- Finally we get a
(n_frame, n_k)array for both self and distinct function.
What do you think? Please indicate any physical errors or code-style differences.