pyiron / pyiron_contrib

User developments to extend and modify core pyiron functionality
https://pyiron.org
BSD 3-Clause "New" or "Revised" License
8 stars 10 forks source link

protocol neb issue with different versions of VASP #694

Closed sinazadeh closed 1 year ago

sinazadeh commented 1 year ago

The following notebook for different versions of VASP raises different issues: protocol_neb_example.ipynb

In Version 6.3, there is an issue with starting the neb job. It only generates the neb_job_initialize_jobs_0 folder along with the following files: POSCAR, POTCAR, INCAR, and KPOINTS. The job never starts.

In Version 5.4.4, the notebook successfully creates the neb_job_initialize_jobs_0_hdf5 file and completes the calculations. However, it fails to compress the folder. Additionally, it generates neb_job_initialize_jobs_1_hdf5 and the same files as before (POSCAR, POTCAR, INCAR, and KPOINTS). Unfortunately, it encounters a problem and does not perform calculations for jobs_1, resulting in being stuck at this point.

sinazadeh commented 1 year ago

Similar behavior in GPAW: gpaw 22.1.0: the notebook successfully creates the neb_job_initialize_jobs_0_hdf5 file and completes the calculations. It generates 19 other empty folders and raises "AttributeError: 'NoneType' object has no attribute 'set_label'."

liamhuber commented 1 year ago

@sinazadeh,

So I see a few places things could be going wrong: 1) pyiron_contrib.protocol is no longer playing well with pyiron_base 2) pyiron_atomistics is no longer playing well with Vasp 3) The specific material system you're running in Vasp is crashing and causing problems

Re (1): I just re-ran the demo notebook using LAMMPS, and while there's some outdated syntax and some warnings, everything worked fine. I was concerned that maybe the stuff protocols do under the hood (mostly copying input template jobs) had gone off the rails, but it looks like everything is still compatible.

Re (2): This is the top suspect for me right now. The AttributeError: 'NoneType' object has no attribute 'set_label' sounds like maybe this is related to recent changes to our Atoms atomic structure class.... There's a slim chance that the trouble here actually has some same-or-related root cause as your issue over in pyiron_atomistics pyiron/pyiron_atomistics#1069.

The fact things fail for v6.3 is not crazy to me -- I have no idea if anyone has updated our parsers to that version. However, certainly it should be working for v5.4.4.

Unfortunately, it encounters a problem and does not perform calculations for jobs_1, resulting in being stuck at this point.

What is the "problem"? Can you please post the python stack trace or error log file contents (similarly for the GPAW issue, it would be very helpful to have the full trace).

Is this problem specific to the NEB protocol? I.e. are you able to run static calculations/minimizations with pyiron_atomistics on top of Vasp 6.3, 5.4.4, and GPAW, or do you encounter similar problems there?

Re (3): I doubt this is the issue, but what system are you working on and what's (roughly) your geometric setup? In pyiron_atomistics pyiron/pyiron_base#1048 I see we are apparently having trouble with parsing spins atm, so if you're altering the demo in any way to run magnetic systems that would give us a lead to follow.

Unfortunately, Vasp is licensed and I no longer have access to it, and GPaw won't install trivially on my machine, so I don't intend to experiment with this directly myself -- at least not today; if the issue persists I can find a workaround.

@raynol-dsouza @hari-ushankar, any insight?

sinazadeh commented 1 year ago

Thank you for your time.

Re (1): I just re-ran the demo notebook using LAMMPS, and while there's some outdated syntax and some warnings, everything worked fine. I was concerned that maybe the stuff protocols do under the hood (mostly copying input template jobs) had gone off the rails, but it looks like everything is still compatible.

Yes, LAMMPS works fine for me too.

Is this problem specific to the NEB protocol? I.e. are you able to run static calculations/minimizations with pyiron_atomistics on top of Vasp 6.3, 5.4.4, and GPAW, or do you encounter similar problems there?

I can run every example from this page without any errors. All lamps, gpaw, Sphinx, vasp examples. https://pyiron.readthedocs.io/en/latest/source/notebooks/test_pyiron_installation.html

What is the "problem"? Can you please post the python stack trace or error log file contents (similarly for the GPAW issue, it would be very helpful to have the full trace).

The error message for GPAW:

The job ref_neb was saved and received the ID: 2596
The job neb_job was saved and received the ID: 2597
envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/jobs/job/generic.py:534: UserWarning: input_only conflicts new_database_entry; setting new_database_entry=False
  warnings.warn(
The job neb_job_initialize_jobs_0 was saved and received the ID: 2598
The job neb_job_initialize_jobs_1 was saved and received the ID: 2599
The job neb_job_initialize_jobs_2 was saved and received the ID: 2600
The job neb_job_initialize_jobs_3 was saved and received the ID: 2601
The job neb_job_initialize_jobs_4 was saved and received the ID: 2602
The job neb_job_initialize_jobs_5 was saved and received the ID: 2603
The job neb_job_initialize_jobs_6 was saved and received the ID: 2604
The job neb_job_initialize_jobs_7 was saved and received the ID: 2605
The job neb_job_initialize_jobs_8 was saved and received the ID: 2606
The job neb_job_initialize_jobs_9 was saved and received the ID: 2607
The job neb_job_initialize_jobs_10 was saved and received the ID: 2608
The job neb_job_initialize_jobs_11 was saved and received the ID: 2609
The job neb_job_initialize_jobs_12 was saved and received the ID: 2610
The job neb_job_initialize_jobs_13 was saved and received the ID: 2611
The job neb_job_initialize_jobs_14 was saved and received the ID: 2612
The job neb_job_initialize_jobs_15 was saved and received the ID: 2613
The job neb_job_initialize_jobs_16 was saved and received the ID: 2614
The job neb_job_initialize_jobs_17 was saved and received the ID: 2615
The job neb_job_initialize_jobs_18 was saved and received the ID: 2616
The job neb_job_initialize_jobs_19 was saved and received the ID: 2617
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[8], line 25
     19 # neb_job.server.queue = neb_job.server.list_queues()[0]
     20 
     21 # set_output_whitelist sets how often an output of a particular vertex is stored in the archive.
     22 # for example, here, the output 'energy_pot' of vertex 'calc_static' is saved every 20 steps in the archive.
     23 neb_job.set_output_whitelist(**{'calc_static': {'energy_pot': 20}})
---> 25 neb_job.run()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/generic.py:648, in Protocol.run(self, delete_existing_job, repair, debug, run_mode, continue_run)
    646 if continue_run:
    647     self.status.created = True
--> 648 super(CompoundVertex, self).run(delete_existing_job=delete_existing_job, repair=repair, debug=debug,
    649                                 run_mode=run_mode)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/utils/deprecate.py:171, in Deprecator.__deprecate_argument.<locals>.decorated(*args, **kwargs)
    161     if kw in self.arguments:
    162         warnings.warn(
    163             message_format.format(
    164                 "{}.{}({}={})".format(
   (...)
    169             stacklevel=2,
    170         )
--> 171 return function(*args, **kwargs)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/jobs/job/generic.py:693, in GenericJob.run(self, delete_existing_job, repair, debug, run_mode, run_again)
    691     self._run_if_repair()
    692 elif status == "initialized":
--> 693     self._run_if_new(debug=debug)
    694 elif status == "created":
    695     self._run_if_created()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/jobs/job/generic.py:1215, in GenericJob._run_if_new(self, debug)
   1207 def _run_if_new(self, debug=False):
   1208     """
   1209     Internal helper function the run if new function is called when the job status is 'initialized'. It prepares
   1210     the hdf5 file and the corresponding directory structure.
   (...)
   1213         debug (bool): Debug Mode
   1214     """
-> 1215     run_job_with_status_initialized(job=self, debug=debug)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/jobs/job/runfunction.py:76, in run_job_with_status_initialized(job, debug)
     74 else:
     75     job.save()
---> 76     job.run()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/generic.py:648, in Protocol.run(self, delete_existing_job, repair, debug, run_mode, continue_run)
    646 if continue_run:
    647     self.status.created = True
--> 648 super(CompoundVertex, self).run(delete_existing_job=delete_existing_job, repair=repair, debug=debug,
    649                                 run_mode=run_mode)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/utils/deprecate.py:171, in Deprecator.__deprecate_argument.<locals>.decorated(*args, **kwargs)
    161     if kw in self.arguments:
    162         warnings.warn(
    163             message_format.format(
    164                 "{}.{}({}={})".format(
   (...)
    169             stacklevel=2,
    170         )
--> 171 return function(*args, **kwargs)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/jobs/job/generic.py:695, in GenericJob.run(self, delete_existing_job, repair, debug, run_mode, run_again)
    693     self._run_if_new(debug=debug)
    694 elif status == "created":
--> 695     self._run_if_created()
    696 elif status == "submitted":
    697     run_job_with_status_submitted(job=self)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/jobs/job/generic.py:1226, in GenericJob._run_if_created(self)
   1217 def _run_if_created(self):
   1218     """
   1219     Internal helper function the run if created function is called when the job status is 'created'. It executes
   1220     the simulation, either in modal mode, meaning waiting for the simulation to finish, manually, or submits the
   (...)
   1224         int: Queue ID - if the job was send to the queue
   1225     """
-> 1226     return run_job_with_status_created(job=self)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/jobs/job/runfunction.py:99, in run_job_with_status_created(job)
     97     job.run_if_manually(_manually_print=False)
     98 elif job.server.run_mode.modal:
---> 99     job.run_static()
    100 elif job.server.run_mode.srun:
    101     job.run_if_srun()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/generic.py:639, in Protocol.run_static(self)
    637 """If this CompoundVertex is the highest level, it can be run as a regular pyiron job."""
    638 self.status.running = True
--> 639 self.execute()
    640 self.status.collect = True  # Assume modal for now
    641 self.protocol_finished.fire()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/generic.py:634, in Protocol.execute(self)
    633 def execute(self):
--> 634     super(Protocol, self).execute()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/generic.py:432, in CompoundVertex.execute(self)
    430     self.graph.step()
    431 self.vertex_processing.fire(self.graph.active_vertex)
--> 432 self.graph.active_vertex.execute()
    433 self.vertex_processed.fire(self.graph.active_vertex)
    434 self.graph.step()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/generic.py:328, in PrimitiveVertex.execute(self)
    326 def execute(self):
    327     """Just parse the input and do your physics, then store the output."""
--> 328     output_data = self.command(**self.input.resolve())
    329     self.update_and_archive(output_data)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/list.py:257, in AutoList.command(self, n_children)
    255     return ParallelList.command(self, n_children)
    256 else:
--> 257     return SerialList.command(self, n_children)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/list.py:228, in SerialList.command(self, n_children)
    225     self._initialize(n_children)
    227 for child in self.children:
--> 228     child.execute()
    230 output_data = self._extract_output_data_from_children()
    231 return output_data

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/generic.py:328, in PrimitiveVertex.execute(self)
    326 def execute(self):
    327     """Just parse the input and do your physics, then store the output."""
--> 328     output_data = self.command(**self.input.resolve())
    329     self.update_and_archive(output_data)

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/primitive/one_state.py:215, in ExternalHamiltonian.command(self, ref_job_full_path, project_path, job_name, structure, positions, cell, interesting_keys)
    212         raise AttributeError('Please specify valid project path OR ref_job_full_path, but not both!')
    214 if self._job is None:
--> 215     self._reload()
    216 elif not self._job.interactive_is_activated():
    217     self._job.status.running = True

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/primitive/one_state.py:280, in ExternalHamiltonian._reload(self)
    278 self._job = pr.load(self._job_name)
    279 self._job.interactive_open()
--> 280 self._job.interactive_initialize_interface()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_atomistics/gpaw/pyiron_ase.py:71, in AseJob.interactive_initialize_interface(self)
     69 def interactive_initialize_interface(self):
     70     self.status.running = True
---> 71     self._structure.calc.set_label(self.working_directory + "/")
     72     self._interactive_library = True

AttributeError: 'NoneType' object has no attribute 'set_label'

Error log for VASP:

envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/jobs/job/generic.py:534: UserWarning: input_only conflicts new_database_entry; setting new_database_entry=False
  warnings.warn(
2023-05-29 10:09:06,230 - pyiron_log - INFO - run job: neb_job_initialize_jobs_0 id: None, status: initialized
The job neb_job_initialize_jobs_0 was saved and received the ID: 2593
2023-05-29 10:09:07,024 - pyiron_log - INFO - run job: neb_job_initialize_jobs_0 id: 2593, status: created
envs/prnenvnew/lib/python3.9/site-packages/pyiron_base/jobs/job/generic.py:534: UserWarning: input_only conflicts new_database_entry; setting new_database_entry=False
  warnings.warn(
2023-05-29 10:12:50,751 - pyiron_log - INFO - run job: neb_job_initialize_jobs_1 id: None, status: initialized
The job neb_job_initialize_jobs_1 was saved and received the ID: 2595
2023-05-29 10:12:51,157 - pyiron_log - INFO - run job: neb_job_initialize_jobs_1 id: 2595, status: created
I doubt this is the issue, but what system are you working on and what's (roughly) your geometric setup?

Al supercell, same as the example notebook. I didn't change the structure.

sinazadeh commented 1 year ago

Can it be related to what Jan mentioned here?

For 5.4.1 it works out of the box, for 5.4.4 you need the following patch: 
Fix flushing in interactive mode
author: Jan Janssen (MPIE)

===================================================================
--- src/main.F  (date 1574848431000)
+++ src/main.F  (date 1574848662858)
@@ -3662,6 +3662,10 @@
 ! interactive mode
 !-----------------------------------------------------------------------
         ELSE IF (DYN%IBRION==11) THEN
+io_begin
+           IF (IO%LOPEN) CALL WFORCE(IO%IU6)            ! write of OUTCAR
+           IF (IO%LOPEN) CALL WFORCE(17)                ! write of OSZICAR
+io_end
            CALL INPOS(LATT_CUR, T_INFO, DYN, IO%IU6, IO%IU0, INFO%LSTOP, WDES%COMM)
         ENDIF

Originally posted by @jan-janssen in https://github.com/pyiron/pyiron/issues/979#issuecomment-695356083

liamhuber commented 1 year ago

Perfect, this is exactly what was needed. We're in luck that actually everything relevant is just in the last two frames:

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_contrib/protocol/primitive/one_state.py:280, in ExternalHamiltonian._reload(self)
    278 self._job = pr.load(self._job_name)
    279 self._job.interactive_open()
--> 280 self._job.interactive_initialize_interface()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_atomistics/gpaw/pyiron_ase.py:71, in AseJob.interactive_initialize_interface(self)
     69 def interactive_initialize_interface(self):
     70     self.status.running = True
---> 71     self._structure.calc.set_label(self.working_directory + "/")
     72     self._interactive_library = True

AttributeError: 'NoneType' object has no attribute 'set_label'

So in 71 we learn that self._structure.calc is None. If we just create a structure, its calc field is None by default, so next I went into pyiron_atomistics.gpaw.pyiron_ase.AseJob to take a look at where this is getting populated. The problem we're running into is that this field only gets set inside AseJob.run_if_interactive, but it's expected to exist in AseJob.interactive_initialize_interface. The trouble is that here in protocol we are explicitly calling load, interactive_open, then interactive_initialize_interface before any run calls.

My first impression is that it's bad form for interactive_initialize_interface to rely on run being called first. I opened a PR to do this, but never having used GPaw and having no access to it on my machine I can't make any immediate guarantees that this is the right fix.

Can it be related to what Jan mentioned here?

Everything above is for Gpaw (which inherits from AseJob), and doesn't explain why Vasp fails. If you are running an unpatched version of Vasp, then it would absolutely fail for protocols! The protocols only work for jobs with an interactive mode, and that's what the patch gives us for Vasp.

sinazadeh commented 1 year ago

Everything above is for Gpaw (which inherits from AseJob), and doesn't explain why Vasp fails. If you are running an unpatched version of Vasp, then it would absolutely fail for protocols! The protocols only work for jobs with an interactive mode, and that's what the patch gives us for Vasp.

I gave VASP 6.3 another try, and it seems the issue has something to do with this:

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_atomistics/vasp/interactive.py:262, in VaspInteractive.run_if_interactive(self)
    260 def run_if_interactive(self):
    261     self.run_if_interactive_non_modal()
--> 262     self._interactive_check_output()
    263     self._interactive_vasprun = Outcar()
    264     self.interactive_collect()

File envs/prnenvnew/lib/python3.9/site-packages/pyiron_atomistics/vasp/interactive.py:290, in VaspInteractive._interactive_check_output(self)
    288 def _interactive_check_output(self):
    289     while self._interactive_library.poll() is None:
--> 290         text = self._interactive_library.stdout.readline()
    291         if "POSITIONS: reading from stdin" in text:
    292             return

The last lines of OUT file:

FORCES:
    -0.0000002     0.0032229     0.0032186
    -0.0032200     0.0032229    -0.0000002
    -0.0032206     0.0000015     0.0032200
    -0.0000003    -0.0032230     0.0032202
    -0.0000004    -0.0000020    -0.0000002
    -0.0032204    -0.0032225     0.0000005
    -0.0025813    -0.0000011     0.0025802
     0.0000002     0.0025837     0.0025810
     0.0000001     0.0000010    -0.0000003
     0.0032199     0.0032226    -0.0000010
     0.0032206     0.0000016     0.0032192
     0.0000002    -0.0025837     0.0025802
     0.0000003    -0.0000009    -0.0000003
     0.0032206    -0.0032225    -0.0000005
     0.0025813    -0.0000011     0.0025808
    -0.0000003     0.0032229    -0.0032198
    -0.0000002     0.0000013     0.0000002
    -0.0025819     0.0025840     0.0000006
    -0.0032206     0.0000013    -0.0032193
    -0.0000005    -0.0032228    -0.0032191
    -0.0000004    -0.0000009     0.0000001
    -0.0025817    -0.0025840    -0.0000002
    -0.0025815    -0.0000014    -0.0025808
     0.0000005     0.0025837    -0.0025804
     0.0000003     0.0000013     0.0000002
     0.0025817     0.0025838     0.0000008
     0.0032206     0.0000017    -0.0032199
     0.0000003    -0.0025837    -0.0025804
     0.0000003    -0.0000014     0.0000003
     0.0025815    -0.0025840    -0.0000001
     0.0025816    -0.0000011    -0.0025802
   1 F= -.11525594E+03 E0= -.11526209E+03  d E =-.115256E+03
POSITIONS: reading from stdin
liamhuber commented 1 year ago

Is this output after recompiling 6.3 with the interactive patch?

This anyhow looks like it's just directly an issue with vasp parsing/interactive vasp, so we'll probably need to pull in someone other than me to help fix it.

sinazadeh commented 1 year ago

Is this output after recompiling 6.3 with the interactive patch?

Correct.

liamhuber commented 1 year ago

Is this output after recompiling 6.3 with the interactive patch?

Correct.

Can you try running just a basic interactive job with this and see if it fails in the same way? I suspect it will, in which case you'll need to go over to pyiron_atomistics and put the issue there. Hopefully the fix for GPaw in pyiron_atomistics #1068 is good and mergeable in short order so at least you can use that. If the Vasp interactive parser is broken this should also be fixable, but might take a bit longer and involve others.

I think a Vaspified version of the following should work for a MWE:

from pyiron_atomistics import Project

pr = Project("tmp")
pr.remove_jobs(silently=True, recursive=True)
job = pr.create.job.Lammps("interactive")
job.structure = pr.create.structure.bulk("Al", cubic=True)
# For VASP you probably want to set low encut and one kpoint for speed
job.calc_md(n_ionic_steps=2, n_print=1, temperature=300)
with job.interactive_open() as ijob:
    ijob.run()
job.output.energy_pot
>>> array([-13.43971504, -13.43886176])
# Obviously works fine for Lammps,
# but I hope/expect the same error as you got before with Vasp

EDIT: add hyperlink

sinazadeh commented 1 year ago

Can you try running just a basic interactive job with this and see if it fails in the same way? I suspect it will, in which case you'll need to go over to pyiron_atomistics and put the issue there. Hopefully the fix for GPaw in pyiron_atomistics #1068 is good and mergeable in short order so at least you can use that. If the Vasp interactive parser is broken this should also be fixable, but might take a bit longer and involve others.

I think a Vaspified version of the following should work for a MWE:

from pyiron_atomistics import Project

pr = Project("tmp")
pr.remove_jobs(silently=True, recursive=True)
job = pr.create.job.Lammps("interactive")
job.structure = pr.create.structure.bulk("Al", cubic=True)
# For VASP you probably want to set low encut and one kpoint for speed
job.calc_md(n_ionic_steps=2, n_print=1, temperature=300)
with job.interactive_open() as ijob:
    ijob.run()
job.output.energy_pot
>>> array([-13.43971504, -13.43886176])
# Obviously works fine for Lammps,
# but I hope/expect the same error as you got before with Vasp

The Lammps version works, VASP version is stuck and results same error: POSITIONS: reading from stdin image

Hopefully the fix for GPaw in [pyiron_atomistics #1068](https://github.com/pyiron/pyiron_atomistics/pull/1068) is good and mergeable in short order so at least you can use that. Is there any timetable for that? I started working with ssneb package, but my preference is using pyiron.

liamhuber commented 1 year ago

VASP version is stuck and results same error

Ok, in a way that's good news; it means that other than the issue with gpaw (which, IMO, is the gpaw job's fault for initializing the structure.calc in a weird place), there doesn't seem to be anything wrong with the NEB protocol.

but my preference is using pyiron.

Glad to hear that! 😄

Is there any timetable for that?

That's hard for me to answer precisely, because it certainly won't be me doing the work (no Vasp license=no debugging changes on my local machine). Use the MWE above to open a new issue on pyiron_atomistics and I'll assign a couple people to it. To give some very rough bounds: I think it's possible someone will make a PR that fixes it this week, but I would be surprised if it got merged prior to the team meeting on Monday; and I would also be very surprised if it was still not working by the end of June.

Does the MWE also give an error with 5.4.4? If so, please also include this info on the new issue; if interactivity is working ok but it's somehow borking on the NEB protocol, lmk the details here and I'll try to fix it on the protocol's side.

sinazadeh commented 1 year ago

Glad to hear that! 😄

Since pyiron does not have any documentation on NEB, can you please provide some clarification on pyiron NEB protocol? Here the tangent styles are:

tangent_style ('plain'/'improved'/'upwinding'): How to calculate the image tangent in 3N-dimensional space.
            (Default is 'upwinding'.)

I assume that these are similar to method parameter of ase.neb.NEB (here)

method: string of method
Choice betweeen five methods:

aseneb: standard ase NEB implementation

improvedtangent: Paper I NEB implementation

eb: Paper III full spring force implementation

spline: Paper IV spline interpolation (supports precon)

string: Paper IV string method (supports precon)

One question is, which one is upwinding? My second question is, is there an easy way to implement Solid State Nudged Elastic Band in pyiron? An example code of SSNEB is this, so I assume pyiron can generate p1 and p2 to feed this code.

from tsase import neb
nim = 7  # number of images, including end points
band = neb.ssneb(p1, p2, numImages = nim, method = 'ci')
opt = neb.fire_ssneb(band, maxmove =0.2, dtmax = 0.1, dt=0.1)
opt.minimize(forceConverged=0.001, maxIterations = 1000)
liamhuber commented 1 year ago

Since pyiron does not have any documentation on NEB

Welcome to _contrib 😝

I assume that these are similar to method parameter of ase.neb.NEB (here)

I failed to document I'm not going to dig through the papers to compare, and I'm not going to go back and dig through the papers now. It's extremely likely that standard::aseneb, improved::improvedtangent. "Paper III" is locked behind a pay-wall, but from the abstract it sounds like they use a dynamic number of images, which is not what we're doing here. It's almost a certainty that nothing from "Paper IV" is implemented here, since the git blame for this code shows it was last updated the same year that paper got published.

The crux of NEB is to allow the system to evolve according to the interatomic forces in the hyperspace perpendicular to the reaction pathway, while constraining the forces parallel to that reaction pathway. standard, improved, and upwinding are all just different ways of defining what this reaction path using the geometry of the images; in the case of upwinding, we also use the energy so that the tangent is simply defined as the direction towards the up-hill image.

You can take a look at the protocol and see that the only fancy bit is calculating the NEB forces. Taking a look again at the vertex that does this, I'm retrospectively pretty happy with the readability (although I do regret not directly putting the paper citations in the docstring). You can see all the different tangent definitions here; The method for the upwinding tangent looks slightly scary, but it's just complicated by the fact that we need to account for the central image where there is not up-hill reference. You can compare the code to the papers to see what the connections are.

E.g. I can see that the smoothing flag directly implements smoothing discussed on Henkelman's page. I'm actually kind of surprised not to see smoothing mentioned in the ASE docs, but maybe they just always have it on?

My second question is, is there an easy way to implement Solid State Nudged Elastic Band in pyiron?

Without being super familiar with it, yes, there should be a way. The easiest is probably just to sub-class the python template job, and pass p1 and p2 in as arguments -- the docs you linked don't give a type hint for what these endpoints should be, but I'm assuming ase.Atoms will do. You could thus get these endpoints the same way we get the endpoints for the NEB protocol, although you may need to dig out where to import our pyiron_to_ase converter function, depending on how picky tsase is.

Here is an older example of subclassing PythonTemplateJob to invoke some python stuff. Remember that for running remotely on HPC, your remote instance of python interpreter needs to know how to instantiate your custom job class -- that means it needs to be available in the JOB_CLASS_DICT; this isn't a hard thing to do, but it's been forever since I had to deal with that and I simply don't remember the details -- we can deal with that in another issue if you need it and don't find docs/an example for it.

liamhuber commented 1 year ago

@sinazadeh did you ever manage to get interactive Vasp working?

I patched the issue with Gpaw here, so on the latest head of pyiron_atomistics the NEB protocol is now working with a GPaw job. I'm attaching the NEB example notebook lightly modified to use Gpaw that now runs fine on my machine.

protocol_neb_example.ipynb.zip

sinazadeh commented 1 year ago

@sinazadeh did you ever manage to get interactive Vasp working?

It didn't work for me so I ran my calculations the manual way, without Pyiron.

liamhuber commented 1 year ago

@sinazadeh did you ever manage to get interactive Vasp working?

It didn't work for me so I ran my calculations the manual way, without Pyiron.

I'm sorry to hear that.

The atomistics issue for interactive vasp is still open over on atomistics, but now that the NEB protocol is playing well with Gpaw I don't think there's any further issues with the NEB part. I'll close this now, but if you play with the uploaded notebook and run into any Gpaw+NEB problems feel free to re-open it.