treverhines / RBF

Python package containing the tools necessary for radial basis function (RBF) applications
MIT License
215 stars 50 forks source link

Removal of lambdify #35

Closed physics-enthusiast closed 5 months ago

physics-enthusiast commented 7 months ago

Hello, cool package you have here! The PDE weight matrix functionality in particular has been rather useful. Just wondering, was there any reason why the set_symbolic_to_numeric_method toggle to use lambdify needed to be removed entirely? Admittedly, usecases involving calculations >15 dimensions that don't cause most computers to burst into flames through their sheer memory requirements alone seem quite scarce, but at least having the option to do so was nice even if it came at a performance cost. This is with reference to commit 3cad702.

treverhines commented 7 months ago

Thanks! I removed the lambdify option because those functions do not allow you to specify an output array, which I needed for that commit.

I suppose we could wrap the lambdified functions to accept an out argument, but it would still create a bunch of intermediate arrays. So I do not know if that solution would be practical when dealing with high dimensions. Can you tell me more about the high dimensional use case you have in mind?

physics-enthusiast commented 7 months ago

In certain strongly coupled systems the number of dimensions scale with the number of interacting entities. For instance, in quantum mechanics, the waveform of a composite system has a dimension of ND, where D is the dimension of the space and N is the number of particles. From what I can tell some problems in finance and AI that can be formulated as a PDE also have high dimensionality, since in their case the "space" is more abstract and hence less constrained to physical limitations. For my specific usecase, I'm actually trying to build a package that leverages this one as part of an attempt to abstract away as many implementation details as possible in the numerical solvation of PDEs. The ideal end goal being that one would be able to just throw an arbitrary function at it and solve(). Of course, the performance would be abysmal without some form of vectorization in the function itself (which would be an optional argument passed to whichever wrapper is in charge of function conversion to indicate said function is a ufunc/sympy expr/accepts array inputs/whatnot) since iterating over all nodes would require the use of pure python for loops, but the point is that it would run*. Meshfree methods like RBF-FD help to abstract away the discretization of the domain since they have significantly laxer requirements for node positioning and connectivity to still remain a good approximation, hence the appeal. Optimization is a secondary concern since weight matrix generation only happens once per domain. Would you be opposed to throwing an error if both out and lambdify are specified unless an optional override flag like out_compat is set to true to signal that the caller is aware that intermediate arrays will be created anyways and just needs the semantics for some reason? It could also detect the dimension and automatically switch between lambdify and ufuncify to opportunistically compute arrays inplace while still retaining compatibility with out_compat. I'd be happy to open a PR with these changes if you have no issue with them.

treverhines commented 6 months ago

Thanks for the explanation. I like the idea of switching between lambdify and ufuncify depending on the number of dimensions. If we do that, I don't think there would be a situation where the symbolic-to-numeric method would need to be exposed to the user. I will try to work on this when I have time next month.

physics-enthusiast commented 6 months ago

For your convenience I've gone ahead and attempted an implementation, feel free to look it over when you have the spare time.