spirit-code / spirit

Atomistic Spin Simulation Framework
http://spirit-code.github.io
MIT License
117 stars 52 forks source link

Loading configurations from ovf files into nebm chain #566

Closed davidcortesortuno closed 4 years ago

davidcortesortuno commented 4 years ago

Hi, I have a question regarding the nebm functionality in the Python API. I have two ovf files which I relaxed with the LLG method. Now I want to use them as initial and final states of an nebm chain, however, when I try to read the images with io.image_read, nothing happens.
I have tried

    # Copy the first image and set chain length
    chain.image_to_clipboard(p_state)
    chain.set_length(p_state, noi)

    # First image
    chain.jump_to_image(p_state, 0)
    io.image_read(p_state,
                  f'my_file_initial.ovf',
                  idx_image_inchain=0
                  )

    # Last image
    chain.jump_to_image(p_state, noi-1)
    io.image_read(p_state,
                  f'my_file_final.ovf',
                  # idx_image_inchain=noi-1  # not sure if necessary
                  )

Reading an image works fine for an LLG simulation but somehow does not work for the chain. I also tried io.chain_read with insert_idx which works for the 0-th image but does not load the image at noi-1.

Is there an extra step I'm missing to load the configurations correctly?

I saw in the code that there is this piece of code, but io.image_from_file no longer exists in the code.

### Read Image from file
# spinsfile = "input/spins.ovf"
# io.image_from_file(state.get(), spinsfile, idx_image=0);
### Read Chain from file
# io.chain_from_file(state.get(), chainfile);
GPMueller commented 4 years ago

Thanks for the detailed description! To me, your code looks like it should work. Which version of spirit are you using?

idx_image_inchain=noi-1 should not be needed since you called chain.jump_to_image(p_state, noi-1), but you can use it instead. The code which is commented out is apparently out of date, thanks for pointing it out.

Please also attach the corresponding log file (on debug level), which should state if something went wrong reading the file. You can set the log file level to debug using the input file or python api.

davidcortesortuno commented 4 years ago

Hi, thanks for the quick reply. I'm using the git version, I mean, I cloned the repo and linked the Python libs to PYTHONPATH.

The part where the code loads the file seems ok in the following log (I removed my computer file paths btw). Strangely, it loads ok in my LLG simulation

2020-05-11 17:21:07  [  ALL  ] [ALL ] [--] [--]  =====================================================
2020-05-11 17:21:07  [  ALL  ] [ALL ] [--] [--]  ============ Spirit State: Initialised ==============
2020-05-11 17:21:07  [  ALL  ] [ALL ] [--] [--]  ============     NOS=27000 NOI=1
2020-05-11 17:21:07  [  ALL  ] [ALL ] [--] [--]      Initialisation took 0:0:0.16
2020-05-11 17:21:07  [  ALL  ] [ALL ] [--] [--]      Number of  Errors:  0
2020-05-11 17:21:07  [  ALL  ] [ALL ] [--] [--]      Number of Warnings: 111
2020-05-11 17:21:07  [  ALL  ] [ALL ] [--] [--]  =====================================================
2020-05-11 17:21:07  [ INFO  ] [ALL ] [--] [--]  Appending Log to file ./Log.txt
2020-05-11 17:21:07  [ INFO  ] [API ] [01] [01]  Set GNEB output tag = "sim_H_960e-3"
2020-05-11 17:21:07  [ INFO  ] [API ] [01] [01]  Set GNEB force convergence = 1e-07
2020-05-11 17:21:07  [ INFO  ] [API ] [01] [01]  Set external field to 8.76562, direction (0, 0, 1)
2020-05-11 17:21:07  [ INFO  ] [API ] [01] [01]  Copied image to clipboard.
2020-05-11 17:21:08  [ INFO  ] [API ] [01] [--]  Increased length of chain to 16
2020-05-11 17:21:08  [ DEBUG ] [API ] [01] [01]  Jumped to image 1 of 16
2020-05-11 17:21:08  [ INFO  ] [API ] [01] [01]  Read image from file "***_Image-00_Spins-final.ovf"
2020-05-11 17:21:08  [ DEBUG ] [API ] [01] [16]  Jumped to image 16 of 16
2020-05-11 17:21:08  [ INFO  ] [API ] [01] [16]  Read image from file "***_Image-00_Spins-final.ovf"
2020-05-11 17:21:08  [ INFO  ] [API ] [01] [--]  Set homogeneous transition between images 1 and 16
2020-05-11 17:21:08  [  ALL  ] [GNEB] [01] [--]  ------------  Started  GNEB Calculation  ------------
2020-05-11 17:21:08  [  ALL  ] [GNEB] [01] [--]      Going to iterate 2 step(s)
2020-05-11 17:21:08  [  ALL  ] [GNEB] [01] [--]                  with 5000 iterations per step
2020-05-11 17:21:08  [  ALL  ] [GNEB] [01] [--]      Force convergence parameter: 0.000000100000
2020-05-11 17:21:08  [  ALL  ] [GNEB] [01] [--]      Maximum force component:     1.000000100000
2020-05-11 17:21:08  [  ALL  ] [GNEB] [01] [--]      Solver: Velocity Projection
2020-05-11 17:21:08  [  ALL  ] [GNEB] [01] [--]  -----------------------------------------------------

The total energy in the ...Chain_Energies_000000.txt file, is the same for all the images, which is not right. When I use

        io.chain_read(p_state,
                      f'***_Image-00_Spins-final.ovf',
                      insert_idx=0
                      )

the energy of the first image loads fine.

My Python file looks like

Hz_range = np.linspace(0.5, 0.96, 24)
SIM_DIR = 'gnebm'
if not os.path.exists(SIM_DIR):
    os.makedirs(SIM_DIR)

if not os.path.exists('logs'):
    os.makedirs('logs')

noi = 16

for H_z in Hz_range[-1::-1][:1]:

    with state.State("input/input.cfg") as p_state:

        Hz_tag = int(np.round(H_z * 1e3))
        SIM_NAME = f'sim_H_{Hz_tag:02}e-3'

        log.set_output_file_tag(p_state, SIM_NAME)
        log.set_output_folder(p_state, 'logs')
        log.set_output_to_file(p_state, True, 5)

        parameters.gneb.set_output_folder(p_state, SIM_DIR)
        parameters.gneb.set_output_energies(p_state)
        parameters.gneb.set_output_tag(p_state, SIM_NAME)
        parameters.gneb.set_output_general(p_state, final=True)
        parameters.gneb.set_convergence(p_state, 1e-7)
        parameters.gneb.set_iterations(p_state,
                                       n_iterations=10000,
                                       n_iterations_log=5000)

        # Set the field magnitude
        hamiltonian.set_field(p_state, magnitude=H_z, direction=[0, 0, 1])

        # Copy the first image and set chain length
        chain.image_to_clipboard(p_state)
        chain.set_length(p_state, noi)

        # First image
        chain.jump_to_image(0)
        io.chain_read(p_state,
                      f'initial_image_Image-00_Spins-final.ovf',
                      insert_idx=0
                      )

        # Last image
        chain.jump_to_image(noi-1)
        io.image_read(p_state,
                      f'last_image_Image-00_Spins-final.ovf'
                      )

        # Create initial guess for transition: homogeneous rotation
        transition.homogeneous(p_state, 0, noi-1)

...
GPMueller commented 4 years ago

Looks like you are running the master version.

Your log looks fine to me, unless the two "***_Image-00_Spins-final.ovf" are identical, which would explain why all the energies are identical. Please make sure you don't have some sort of copy-paste bug. Also, please make sure that the two files are not identical.

Note that io.chain_read is meant to read an ovf-file containing several "images", i.e. spin configurations. You can write a corresponding file using io.chain_write.

Regarding your script, instead of chain.jump_to_image etc., please try io.image_read(p_state, "initial_image_Image-00_Spins-final.ovf", idx_image_inchain=0) and io.image_read(p_state, "last_image_Image-00_Spins-final.ovf", idx_image_inchain=noi-1).

If that is not successful, I would recommend running the energy minimizations in the same script where you subsequently run the GNEB method.

davidcortesortuno commented 4 years ago

Ok, I see. I double checked and the files are definitely not identical. I now fixed the problem by adding the relaxation just after the io reading

        io.image_read(p_state,
                      f'last_image_Image-00_Spins-final.ovf')
        simulation.start(p_state, simulation.METHOD_LLG, simulation.SOLVER_VP,
                         idx_image=noi-1)

(and same for image 0). It now loads the states correctly. It might be the case that it's necessary to add something after the image_read if I don't want to relax the state, as it was already minimised?

MSallermann commented 4 years ago

How do you verify the images are not loaded correctly? Only by looking at the energies? If so, can you try adding a call to chain.update_data(p_state) after reading the images and instead of the energy minimization. See https://spirit-docs.readthedocs.io/en/stable/core/docs/python-api/spirit.chain.html.

davidcortesortuno commented 4 years ago

Aha, that works. Thanks so much ;)

So I finally get the right energies at the extrema, but the interpolated images after transition.homogeneous(p_state, 0, noi-1) have the same energy, is this supposed to work like this? My energy file for the initial state looks like this

----------------------++----------------------++----------------------++----------------------+----------------------+----------------------
        image         ||          Rx          ||        E_tot         ||        Zeeman        |       Exchange       |         DMI          
----------------------++----------------------++----------------------++----------------------+----------------------+----------------------
          0           ||     0.0000000000     ||    -3.4700663951     ||    -0.4925451658     |    -2.9514654108     |    -0.0260558184     
          1           ||    280.6793539429    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          2           ||    280.6793551916    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          3           ||    280.6793564403    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          4           ||    280.6793576890    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          5           ||    280.6793589376    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          6           ||    280.6793601863    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          7           ||    280.6793614350    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          8           ||    280.6793626837    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          9           ||    280.6793639324    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          10          ||    280.6793651810    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          11          ||    280.6793664297    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          12          ||    280.6793676784    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          13          ||    280.6793689271    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          14          ||    280.6793701757    ||    -0.0115928630     ||    -0.0021493290     |    -0.0098916369     |     0.0004481029     
          15          ||    561.3330554528    ||    -3.4740544998     ||    -0.5073877951     |    -2.9666666395     |    -0.0000000651     
MSallermann commented 4 years ago

In that case, you can move chain.update_data(p_state) behind transition.homogeneous(p_state, 0, noi-1). Then all fields holding the temporary image energies should be updated and the file should look fine.

davidcortesortuno commented 4 years ago

Awesome, thanks! I'd recommend adding some documentation on this, as it was difficult to find what was the problem.