ttadano / ALM

MIT License
16 stars 9 forks source link

List of symmetrically dependent IFC #41

Closed ejmeitz closed 2 months ago

ejmeitz commented 3 months ago

I've been trying to understand the irreducible representation of force constants better and was wondering if there is some way to list which IFC indices should be identical?

Say we took the setup from the fcsxml example where we calculate the force constants in what ALAMODE calls the origin format which as noted by the docstrings is reducible. What I'm after is basically:

EDIT: Maybe this is an ill-posed question since the symmetry operations just tell you how a pair of IFC are related (e.g. $\phi{12} = a\phi{13} + b \phi_{23}$) not which values in the supercell representation are identical.

The linear combinations that form the irreps would also be useful information.

Thanks!

ttadano commented 3 months ago

Thank you for your question/suggestion.

The information of the mapping table reducible <--> irreducible cannot be accessed from the Python interface, but they are already constructed in the C++ class.

I think that information will be useful for others, so I will implement a Python method to obtain it.

ejmeitz commented 3 months ago

Amazing, thank you very much! This will be very helpful for my research.

ttadano commented 3 months ago

Hi,

I've implemented the get_fc_dependency method in the develop branch. f1d668fdee66e7e7218a04c88daf19d0e14fce0c

To show the dependency information between force constants, please use the method, for example, as follows:

with ALM(lavec, xcoord, kd) as alm:
    alm.define(2, [-1, 7.3])
    alm.displacements = disp
    alm.forces = force
    alm.set_constraint(translation=False)
    info = alm.optimize()

    dependency_fc2 = alm.get_fc_dependency(1)
    dependency_fc3 = alm.get_fc_dependency(2)

    print("# dependency for FC2")
    for key, val in dependency_fc2.items():
        print('{} = '.format(key), end='')
        for key2, val2 in val.items():
            if val2 > 0.0:
                print(' +{:4.2f} {}'.format(val2, key2), end='')
            else:
                print(' {:5.2f} {}'.format(val2, key2), end='')

        print('')

    print("# dependency for FC3")
    for key, val in dependency_fc3.items():
        print('{} = '.format(key), end='')
        for key2, val2 in val.items():
            if val2 > 0.0:
                print(' +{:4.2f} {}'.format(val2, key2), end='')
            else:
                print(' {:5.2f} {}'.format(val2, key2), end='')

        print('')

Please try it and tell us if this method is what you expected.

ejmeitz commented 3 months ago

Yes this is wonderful! Thank you very much.

Out of curiosity, I see a lot of the doc-strings support the calculation of fourth order IFC which are used in the SCPH portion of the code (I think, haven't actually used the SCPH). Are there plans to add this to the scattering rate calculations as well?

ttadano commented 3 months ago

Yes, the four-phonon scattering rate calculations are already implemented in 2.0dev branch of https://github.com/ttadano/alamode/tree/2.0dev, and will be officially supported when ver 2.0 is released.

ejmeitz commented 3 months ago

A technical question, then I think I'll have all I need.

I think its just this example (and also the same for all the crystals I tried), but val2 doesn't necessarily have to be +1 or -1 it could be any number right? Edit: I turned on the ASR and now see that is indeed the case. For posterity I'll leave this here.

Also is it safe to just pass dummy force/disp values into the optimizer since I don't actually have force data to fit? I would imagine so, just want to be safe as I do not understand all the innerworkings of the code. I imagine a random input could crash the solver, but all zeros seems safe. Just enough to trigger the symmetry calculation without crashing the code.

ttadano commented 2 months ago

Hi,

passing zeros to disp/force may cause an error in the fitting part (and the actual behavior of the code can depend on the actual fitting solver to be used), so I recommend passing random numbers to disp/force.

ejmeitz commented 2 months ago

I think there is maybe a small bug in the enumeration of 3rd order IFC dependencies. In terms of the example, the IFC term "1x3y3x" is non-zero if you use the force/disp data from fcsxml.py example (see index 5187 of fc3_vals). Despite that this IFC is not in the output dependency map nor are any of its permutations. Maybe I'm interpreting the output wrong, but everything worked brilliantly at second order so I don't think so.

My best guess is some edge case related to acoustic sum rule terms.

ttadano commented 2 months ago

Hi,

Did you use the same show_fc_dependency.py example?

When I issued

python show_fc_dependency.py | grep "1x3x3y"

I got 1x3x3y = -1.00 1x1y3x.

ejmeitz commented 2 months ago

Oh the permutation is there oops. Can't rely on the permutation from get_fc for this lol. I'll hack something together I suppose to just try both. Sorry to waste your time.

ejmeitz commented 2 months ago

Does ALAMODE care which permutation of an index I write into the fcsxml file as long as I have one? Right now I always have the indexes sorted (e.g. 1x3y5x instead of 5x3y1x). That said, I assume its safe to write redundant terms to this file.

Edit. I just wrote them all and what I was trying to do worked, so all good now.