Skip to content
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

Add Hessian calculation support #10

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Add Hessian calculation support #10

wants to merge 1 commit into from

Conversation

tjjarvinen
Copy link
Collaborator

Hessian calculation is defined the same way as other calculation types

AtomsCalculators.hessian(system, calculator)
# or
AtomsCalculators.calculate(AtomsCalculators.Hessian(), system, calculator)

@generate_interface macro can be used to help define the calculator interface. Also, test_hessian function has been added to help testing the interface.

So, basically this is a very simple addition of Hessian to the interface.

@cortner, @mfherbst, @rkurchin, @jgreener64


# add your own definition
l = length(system) * length(position(system, 1))
return zeros(l,l) * (u"eV" / u"Å"^2)
Copy link
Member

Choose a reason for hiding this comment

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

This definition of hessian is inconsistent with how we return forces I believe? Forces are AbstractVector{<: SVector} and hence hessians should be AbstractMatrix{<: SMatrix}. The conversion from this format to a AbstractMatrix{<: Number} requires the specification of how positions are converted into degrees of freedom.

What is a key difficulty here is that this refers exclusively to the hessian w.r.t. positions. Hessian w.r.t. combined cell and position will need to be discussed.

@cortner
Copy link
Member

cortner commented Jan 10, 2024

Thanks for starting this. I think a hessian should be an AbstractMatrix{<: SMatrix} - see my comment above.

@tjjarvinen
Copy link
Collaborator Author

Forces are AbstractVector{<:SVector}, you can use e.g. reinterpret(Float64, f) to get it into AbstractVector{<:Number}.

In my opinnion we should use this definition to define the AbstractMatrix{<:Number} definition for Hessian.

For cell vector Hessian, it can be build from position Hessian. Secondly we don't have AtomsBase system structure that uses fractional coordinates.

@cortner
Copy link
Member

cortner commented Jan 10, 2024

thanks for reminding me about this. I am strongly opposed to using inconsistent formats here. If forces are vector(vector) then hessians must be matrix(matrix). reinterpret doesn't really play a role here in my view.

For cell vector Hessian, it can be build from position Hessian

I have not seen this before. My first instinct is that this cannot be true: Take a unit cell containing a single atom. Force will always be zero, hence hessian will always be zero. But energy-volume curve will have non-zero variation so cell-hessian will be non-zero.

Please text me on Zulip and explain if you think I'm wrong.

Project.toml Show resolved Hide resolved
Comment on lines +239 to 257
function generate_calculator_hessian(calc_type)
q = quote
function AtomsCalculators.calculate(::AtomsCalculators.Hessian, system, calculator::$calc_type; kwargs...)
h = AtomsCalculators.hessian(system, calculator; kwargs...)
return ( hessian = h, )
end
end
return q
end

function generate_hessian(calc_type)
q = quote
function AtomsCalculators.hessian(system, calculator::$calc_type; kwargs...)
h = AtomsCalculators.calculate(AtomsCalculators.Hessian(), system, calculator; kwargs...)
return h[:hessian]
end
end
return q
end
Copy link
Member

Choose a reason for hiding this comment

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

There is a lot of code duplication in this file for the generates. Can this not be simplified somehow by an @eval inside a for loop or similar ?

Copy link
Member

Choose a reason for hiding this comment

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

(Just a suggestion, no need to do that now)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, I noticed that too. Although this was not an issue untill now, so it was just faster to add these two.

Comment on lines +114 to +116
# we can ignore kwargs... or use them to tune the calculation
# or give extra information like pairlist

Copy link
Member

Choose a reason for hiding this comment

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

Is this not boilerplate ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, it is. Originally the idea was to add that there, so that, if someone looks for implementation examples, there would be some "helpful comments".

Comment on lines +45 to +48
# we can ignore kwargs... or use them to tune the calculation
# or give extra information like pairlist

# add your own definition
Copy link
Member

Choose a reason for hiding this comment

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

feels like it's not needed here.

@tjjarvinen
Copy link
Collaborator Author

If we want to add Hessian to AD tools (Zygote, ForwardDiff, etc.), we need to use use AbstractMatrix{<:Number} formatting. So, we would need to add conversion layer, if we go for Matrix{Matrix} format. And it would need to include permutation in the conversion. So, from my point, the Matrix{Matrix} format is the inconsistent one.

The other issue is that Matrix{Matrix} times Vector{Vector} is not a BLAS operation, and you would need to perform permutation in order to get it to use BLAS calls. For me this big enough reason alone to not have Matrix{Matrix} format in the first place.

For cell vector Hessian you are correct. My version would only work, if atoms don't see their own images.

@cortner
Copy link
Member

cortner commented Jan 10, 2024

Re AD - I don't think this is true, I've been using AD tools regularly with arrays of arrays.

I think you are confusing two different hessians. For linear algebra you need the hessian w.r.t. degrees of freedom. Here we are implementing the hessian with respect to positions. They are not always the same.

If we are going Matrix{<: Number} then the entire design has to be overhauled from scratch.

@cortner
Copy link
Member

cortner commented May 21, 2024

I'd like to return to this and propose a compromise. In JuLIP I actually had two hessian implementations: (1) pos_hessian and (2) hessian. The first was the block-matrix format that I prefer for consistency reasons. The second was with respect to DOFs. We can provide simple conversion routines.

A final point: Hessians are expensive to compute. The conversion will almost never be the overhead. Maybe for some some very simple empirical potentials, but in those cases we should definitely not perform global AD. I actually do not believe that we will ever compute the global hessian using ForwardDiff. We will compute the local site-energy hessian using ForwardDiff and then write that into the global hessian. Therefore there is no conversion overhead as suggested above.

@cortner
Copy link
Member

cortner commented May 30, 2024

based on discussions in other repos, can we pleaes add prototypes for block_hessian and for hessian and possibly also a conversion utility?

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