-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introducing state #11
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a need for this kind of feature.
- Do not create new types to add features
- Update algorithm can be problematic - how is it intended to be used? This need more explaining on how to do this
- It would be good to add some tests. Like add it to some of the already existing test functions. (These need a general update, so we could do this on another PR too).
src/interface.jl
Outdated
@@ -1,4 +1,10 @@ | |||
|
|||
abstract type AbstractCalculator end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not add AbstractCalculator
type. It is not needed and it's presence will cause a lot of problems.
src/interface.jl
Outdated
@@ -1,4 +1,10 @@ | |||
|
|||
abstract type AbstractCalculator end | |||
|
|||
struct DummyState end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DummyState
is not needed. We just use Missing
to do the same
src/interface.jl
Outdated
calculator_state(::AbstractCalculator) = DummyState() | ||
update_state(::Any, ::DummyState, ::Any, ::Any) = DummyState() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use
calculator_internal_state(::Any) = missing
update_calculator_state(
update_algorithm::Any,
initial_internal_state::Missing,
initial_state::Any,
new_state::Any
) = missing # return new internal state
I would also add documentation on why to do this.
Also, update_algorithm
is potentially very problematic. This stems from where are you going to define it. If it is defined for individual packages (like DFTK) then it should not be in the interface, or it will cause problems.
You will potentially call the command with different calculator types (e.g. when comparing different methods) and this causes errors, if algorithm in not defined for both of them. You could ignore algorithm all together to solve this. But this then goes on to the question, why it is there in the first place?
Thanks a lot for your comment @tjjarvinen . This was helpful and made us come with a new point of view. Let me briefly sketch why this whole
This is where the idea of having a calculator state that can be extracted and provided as a starting point for computations originated in the first place. |
Now on to our new point of view and proposition, which tries to include your comments. What we need:
Implementation Suggestion
What a typical pipeline (geometry optimisation) would then look like
And
|
eager to know what you think. |
Thank you for the clarification! My own idea was something like this int_states = [ ]
for sys in some_systems
# do some work with my_calculator
if something_interesting
push!(int_states, (get_internal_state(my_calculator), sys) )
end
end
for (int_state, sys) in int_states
set_internal_state!(my_calculator, sys, int_state)
# do something else like
AtomsCalculators.potential_energy(sys, my_calculator)
end But, I also like your idea of using a keyword. Meaning that we would have keywords as part of the interface definition. However, I can see a potential issue coming from this. Let's say our calculator is a combination of several calculators, e.g. a QM/MM (or QM/ML) calculator using DFTK for QM part. If we use keyword in the interface this causes some issues. Because both QM and MM calculators get the same keywords and, if both have With function set_internal_state!(calc, sys, int_states::AbstractArray)
foreach( int_states ) do state
set_internal_state!(cals, sys, state)
end
end We can then use an array like Then there is the naming issue as well. We are using now We need to add also
|
I didn't have time to read through the details, but can I just ask : why do we not simply adopt the |
I had a look at Lux. I agree that it would be a good model for us. There is one caveat tough: adopting the Lux model would require calculators to return results and state upon each call. This would require changing the interface so that calls to (say) One possible way around it would be to add a keyword ActionIt seems to me that in order to use the
Personally, I think that at this point of development (using AtomsCalculators for geometry optimization), this question of state cannot be avoided anymore, so we should make a decision. Happy to hear what you guys think. |
For reference: (from Lux documentation) Design Principles
|
This is all being discussed right now on Zulip. Please follow the discussion there and try to make the calls with CEMIX |
Trying to catch up on things I've fallen behind on here and haven't read this in tremendous detail, but is it correct that this is superseded by #12? If so, unless we think there's a chance we'll revert back to this approach, should we close this to keep things clear/tidy? |
you are probably right, @CedricTravelletti can confirm? |
This introduces state updating in the calculator.
See this PR in GeometryOptimization.jl for a detailed discussion of why this is needed.