Skip to content

Adding Chebyshev anisotropic pair potential#121

Open
mzf0069 wants to merge 5 commits intomphowardlab:mainfrom
mzf0069:feature/chebyshev-aniso-pair
Open

Adding Chebyshev anisotropic pair potential#121
mzf0069 wants to merge 5 commits intomphowardlab:mainfrom
mzf0069:feature/chebyshev-aniso-pair

Conversation

@mzf0069
Copy link
Contributor

@mzf0069 mzf0069 commented Jan 26, 2026

No description provided.

@mzf0069 mzf0069 requested a review from mphoward January 26, 2026 22:37
Copy link
Collaborator

@mphoward mphoward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good start! Here are some comments, let me know what questions you have.

@mzf0069 mzf0069 requested a review from mphoward February 5, 2026 23:04
Copy link
Collaborator

@mphoward mphoward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going in a good direction. Let's finalize the interface, especially the constructor, then start to implement that.

const std::vector<Scalar>& r0_data,
const std::vector<unsigned int>& terms,
const std::vector<Scalar>& coeffs);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r0_data should be a raw pointer to Scalar so that we can copy the data in-place from a NumPy array. You will need a second raw pointer or a std::vector that stores the dimensionality of r0_data along each of the 5 dimensions.

terms and coeffs also need to be raw pointers, and you'll need one more variable that is the number of terms.

Last, domain should probably also be a raw pointer to a regular Scalar so you can accept a NumPy array that is (6,2) in shape. Otherwise, it can be a std::vector<Scalar2>, and you can copy into it.

}

/// r0 data (theta, phi, alpha, beta, gamma) (N x 6)
const GPUArray<Scalar>& getR0Data() const
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to be expose the R0Data data directly after you construct the class? Same questions go for some of the members below that return GPUArray. You have to decide whether you are OK with the user modifying their contents or not.

Comment on lines +85 to +86
/// Allocate storage for term list and coefficients.
void resizeTerms(unsigned int Nterms);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this something we want the user to be able to do? It seems like you wouldn't want them to do that themselves, most likely. If it's a method the class needs to trigger, though, it can be protected.

protected:
void computeForces(uint64_t timestep) override;

private:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the members in this section will need to be protected not private if the GPU version of the class is going to access them.

@mzf0069 mzf0069 requested a review from mphoward February 16, 2026 15:20
Copy link
Collaborator

@mphoward mphoward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, let's start on the implementation!

Comment on lines +45 to +47
unsigned int Nterms,
const unsigned int* terms,
const Scalar* coeffs);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like to follow the convention that the number of items comes after the pointers

Suggested change
unsigned int Nterms,
const unsigned int* terms,
const Scalar* coeffs);
const unsigned int* terms,
const Scalar* coeffs,
unsigned int Nterms);

Comment on lines +43 to +44
const Scalar* r0_data,
const unsigned int* r0_shape,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logically, should these come before the things related to the potential approximation or after? It doesn't really matter, beyond which way it makes more sense for you to read them.

Comment on lines +67 to +68
// neighbor list object
std::shared_ptr<hoomd::md::NeighborList> m_nlist;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Member variables should be documented like this in doxygen style

Suggested change
// neighbor list object
std::shared_ptr<hoomd::md::NeighborList> m_nlist;
std::shared_ptr<hoomd::md::NeighborList> m_nlist; //!< Neighbor list

Comment on lines +73 to +79
// intenal r0 linear interpolator
std::unique_ptr<LinearInterpolator5D> m_r0_interp;

// r0_data
GPUArray<Scalar> m_r0_data;

std::array<unsigned int, 5> m_r0_shape;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should discuss how the linear interpolator will work. It may not be necessary to store a separate variable for it, and instead just construct it each time it is needed because it will be a lightweight wrapper around the data and the shape.

Noting: if the shape is stored in an array, it will need to be copied into the interpolator to pass it to the GPU.

GPUArray<Scalar> m_coeffs;

// number of terms
unsigned int m_Nterms = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need a default value assigned to it

Suggested change
unsigned int m_Nterms = 0;
unsigned int m_Nterms;

@mzf0069 mzf0069 requested a review from mphoward February 27, 2026 16:05
Copy link
Collaborator

@mphoward mphoward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is moving in a good direction! Please see my comments and let me know what questions you have.

Comment on lines +16 to +17
domain = numpy.zeros((5, 2), dtype=numpy.float64)
terms = numpy.zeros((2, 6), dtype=numpy.uint32)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest giving the domain and terms some real values, not just zeros, as it may cause problems later once we start implementing things.

Comment on lines +64 to +65
assert pot._cpp_obj.n_terms == 2
assert numpy.isclose(pot._cpp_obj.r_cut, r_cut)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_cpp_obj is an implementation detail, so we should not test it in detail. The check above that it exists and is not None is OK though.

Suggested change
assert pot._cpp_obj.n_terms == 2
assert numpy.isclose(pot._cpp_obj.r_cut, r_cut)

src/pair.py Outdated
Comment on lines +39 to +42
@property
def r_cut(self):
"""Cut-off distance in approximation domain"""
return self._r_cut
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need a property for the ones coming from C++, but you need to use the ParameterDict correctly for those.

Suggested change
@property
def r_cut(self):
"""Cut-off distance in approximation domain"""
return self._r_cut

src/pair.py Outdated
Comment on lines +44 to +47
@property
def n_terms(self):
"""Number of terms."""
return int(self._terms.shape[0])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, this should come from C++ automatically.

Suggested change
@property
def n_terms(self):
"""Number of terms."""
return int(self._terms.shape[0])

src/pair.py Outdated
Comment on lines +49 to +52
@property
def r0_shape(self):
"""r0 table shape."""
return tuple(int(x) for x in self._r0_data.shape)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will want to discuss how to expose the array quantities later on. However, I note for now that we don't want to have a special shape property for r0. It should be a NumPy inside this class, so it should work like r0.shape.

@mzf0069 mzf0069 requested a review from mphoward March 19, 2026 16:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants