Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@Dayou-Zhang
Copy link
Contributor

In this pull request, I added a callback interface in libxc_itrf.c to allow using custom parameters in XC functionals. The user can adjust the parameters in the xc_func_type struct right before Libxc evaluates the functional through the callback interface. A fully commented example is supplied.

@susilehtola
Copy link
Contributor

This is not the way to set libxc parameters. You are not supposed to touch the Libxc internal arrays. Also, your example is hardcoded to a single functional, which sets a bad example. We have generic functionality to do this. Use the function xc_func_set_ext_params to set the external parameters. Moreover, you need to set the external parameters not just where the functions is evaluated, but also where PySCF queries various properties of the functional, such as exact exchange coefficients. At present these modifications will yield incorrect behavior.

Several people have expressed interest in being able to set libxc functional parameters in PySCF. For instance, I have been in touch with @ychen428 since early 2023 who has a proper interface to the external parameter setters. Per my request, @ychen428 promised to open up a pull request "shortly" several months ago, but I don't see one up yet. @ychen428 please open up a pull request; like we discussed by email the interface may need some discussion with the PySCF main developers since it's not obvious what is the best way to store the parameters in PySCF.

@Dayou-Zhang
Copy link
Contributor Author

Thanks for pointing me towards the right direction. I didn't know Libxc has such a convenient method to set external parameters.

I made a new implementation of the interface to set external parameters. This should be much cleaner than what is previously done. In the new implementation, no manual adjustment of HF exchange percentage is needed.

@Dayou-Zhang Dayou-Zhang changed the title Implement callback interface in libxc_itrf.c to allow using custom parameters in XC functionals Implement interface to set custom parameters of XC functionals in Libxc May 28, 2023
@susilehtola
Copy link
Contributor

Moreover, you need to set the external parameters not just where the functions is evaluated, but also where PySCF queries various properties of the functional, such as exact exchange coefficients. At present these modifications will yield incorrect behavior.

This is still missing.

@Dayou-Zhang
Copy link
Contributor Author

In the current implementation, the external parameters are set when PySCF queries properties of the functional.

Here is a summary of how this is achieved. In LIBXC_hybrid_coeff, LIBXC_nlc_coeff, LIBXC_rsh_coeff, and LIBXC_eval_xc, the xc_func_init function call is replaced by _xc_func_init, which sets the custom parameters after the xc_func_type struct is initialized. Therefore, when PySCF queries the parameters such as the HF exchange percentage, the library will return the updated values. I also added an option to clear the lru cache so that PySCF will call the library again to read the updated values after the external parameters have changed.

Can you please let me know which part I am missing?

@susilehtola
Copy link
Contributor

Can you please let me know which part I am missing?

I do see now that the minute change of adding _ in the function calls changes the behavior. This is not sufficiently clear. I left other comments on code clarity. Please also fix your C indentation to a tab width of 4 characters instead of 8.

@Dayou-Zhang
Copy link
Contributor Author

Thanks for the suggestions. I have fixed the issues mentioned above.

Please also fix your C indentation to a tab width of 4 characters instead of 8.

I used 8-space indentation because libxc_itrf.c used 8-space indentation before I made any changes. To make the whole file consistent, I reformatted the entire file with 4-space indentation in my last commit.

@sunqm
Copy link
Collaborator

sunqm commented Jun 13, 2023

Modifying the internal parameters of libxc through PySCF's libxc interface IMO is not a good way to use libxc. The pyscf libxc interface is supposed to combine different libxc functionals at Python level. In this scenario, it is better to use pylibxc library and call its APIs to modify functionals. An adapter may need to be implemented for calling pylibxc in the dft module.

@sunqm
Copy link
Collaborator

sunqm commented Jun 13, 2023

In the current implementation, the external parameters are set when PySCF queries properties of the functional.

Here is a summary of how this is achieved. In LIBXC_hybrid_coeff, LIBXC_nlc_coeff, LIBXC_rsh_coeff, and LIBXC_eval_xc, the xc_func_init function call is replaced by _xc_func_init, which sets the custom parameters after the xc_func_type struct is initialized. Therefore, when PySCF queries the parameters such as the HF exchange percentage, the library will return the updated values. I also added an option to clear the lru cache so that PySCF will call the library again to read the updated values after the external parameters have changed.

Can you please let me know which part I am missing?

Please consider to cache parameters in Python. Modification to libxc library can only applied when needed and parameters should be restored immediately after calling the libxc functions. It looks an error-prone code to persistently change the libxc internal parameters. E.g., imaging that the libxc library is called by another thread after set_ext_params in one thread.

@susilehtola
Copy link
Contributor

@sunqm an issue is that pylibxc is overengineered in terms of an interface and we are thinking about disbanding it in favor of a more minimal interface similar to the C interfacing used in PySCF...

However, it is true that many codes will want a more abstract, object-oriented interface to Libxc; this could be done by another project in a higher-level language like C++ with Python interfaces.

@Dayou-Zhang Dayou-Zhang force-pushed the master branch 2 times, most recently from d7310e6 to 88266d5 Compare July 24, 2023 22:19
@Dayou-Zhang Dayou-Zhang reopened this Jul 24, 2023
@Dayou-Zhang
Copy link
Contributor Author

Here is a new implementation where the external parameters are cached in Python. The parameters are cached in the NumInt object. Parameter editing can be done via a dict-like interface accessible from mf.ext_params_dict. When user sets a new external parameter, an array of struct ext_params_cache_t is created via ctypes. The struct array is passed to the C library as a pointer while calling LIBXC_hybrid_coeff, LIBXC_nlc_coeff, LIBXC_rsh_coeff, and LIBXC_eval_xc. This implementation will not set parameters persistently and allows multiple mf objects with different external parameters set.

I made modifications in the base classes KohnShamDFT and _NumIntMixin. Hopefully this would work for all variations of DFT, but I have not done a thorough test yet.

@sunqm
Copy link
Collaborator

sunqm commented Aug 27, 2023

This feature looks make the interface to libxc unnecessarily complicated. I think it needs more consideration whether and how to handle this feature. I will close the PR for the moment.

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.

3 participants