SCM-NV / pyZacros

Python Library for Automating Zacros Simulations
Other
7 stars 2 forks source link

pyZacros able to read standard Zacros input files #59

Closed lopeztarifa closed 3 years ago

lopeztarifa commented 3 years ago

Hi @nfaguirrec,

@stefsmeets is working on the semantic wrappers for pyZacros and we were wondering:

nfaguirrec commented 3 years ago

Hi @lopeztarifa,

Regarding your first question. The name of the function to load input zacros files is load_external. You can see some examples in tests/test_ZacrosJob.py. This function will load all the input files in the given directory (energetics_input.dat lattice_input.dat mechanism_input.dat simulation_input.dat).

Regarding your second question, now the clusters and mechanisms are entirely different entities. They receive a list of clusters as a parameter in their constructors. See e.g., examples/CO_tutorial/CO_tutorial.py. I hope this version of the example results familiar for you with respect to the original CP_tutorial; I tried to modify it as little as possible.

PS: Please use the branch 'develop' if you would like to have access to the latest updates.

lopeztarifa commented 3 years ago

Hi @nfaguirrec,

Thanks for your reply. Good to know that everything is in place.

I am trying to run the CO_tutorial.py from master and I got the following error message:

Traceback (most recent call last):
  File "/Users/plopez/Programs/ReaxPro/pyZacros/examples/CO_tutorial/CO_tutorial.py", line 4, in <module>
    import pyzacros as pz
  File "/Users/plopez/Programs/miniconda3/envs/osp/lib/python3.9/site-packages/pyzacros-0.0.1-py3.9.egg/pyzacros/__init__.py", line 24, in <module>
    __all__ = __autoimport(__path__[0], ['core','utils'])
  File "/Users/plopez/Programs/miniconda3/envs/osp/lib/python3.9/site-packages/pyzacros-0.0.1-py3.9.egg/pyzacros/__init__.py", line 16, in __autoimport
    tmp = __import__(imp, globals=globals(), fromlist=['*'], level=1)
  File "/Users/plopez/Programs/miniconda3/envs/osp/lib/python3.9/site-packages/pyzacros-0.0.1-py3.9.egg/pyzacros/utils/RKFLoader.py", line 8, in <module>
    from pyzacros.utils.setting_utils import get_unique_reactions
ImportError: cannot import name 'get_unique_reactions' from 'pyzacros.utils.setting_utils' (/Users/plopez/Programs/miniconda3/envs/osp/lib/python3.9/site-packages/pyzacros-0.0.1-py3.9.egg/pyzacros/utils/setting_utils.py)

Can you take a look? Thanks!

stefsmeets commented 3 years ago

Regarding your first question. The name of the function to load input zacros files is load_external. You can see some examples in tests/test_ZacrosJob.py. This function will load all the input files in the given directory (energetics_input.dat lattice_input.dat mechanism_input.dat simulation_input.dat).

If I have all the input files ready, then I might as well run zacros directly on that path 😅

I think it would be useful to be able to load any ***_input.dat and turn it into some pyZacros object that can be modified from the script, and then passed to ZacrosJob.

At the moment I'm doing this:

CO2_adsorbed = Species("CO2*", 2)

with open('/home/ssmeets/reaxpro-wrappers/examples/Zacros_inputs/lattice_input.dat') as f:
    lattice = f.read()

with open('/home/ssmeets/reaxpro-wrappers/examples/Zacros_inputs/energetics_input.dat') as f:
    cluster_expansion = f.read()

myJob = ZacrosJob(settings=sett,
                  mechanism=myMechanism, 
                  # additional_species=[CO2_adsorbed], ??
                  lattice=lattice,
                  cluster_expansion=cluster_expansion,
                  )

I'm not sure if this is the correct way to use ZacrosJob class, but it seems to work for now. I'm missing a way here to specify extra surface species, which is available in the CO_tutorial branch. Is there any plan to get this feature or branch merged? Or is there some other way to achieve this?

nfaguirrec commented 3 years ago

Hi @nfaguirrec,

Thanks for your reply. Good to know that everything is in place.

I am trying to run the CO_tutorial.py from master and I got the following error message:

Traceback (most recent call last):
  File "/Users/plopez/Programs/ReaxPro/pyZacros/examples/CO_tutorial/CO_tutorial.py", line 4, in <module>
    import pyzacros as pz
  File "/Users/plopez/Programs/miniconda3/envs/osp/lib/python3.9/site-packages/pyzacros-0.0.1-py3.9.egg/pyzacros/__init__.py", line 24, in <module>
    __all__ = __autoimport(__path__[0], ['core','utils'])
  File "/Users/plopez/Programs/miniconda3/envs/osp/lib/python3.9/site-packages/pyzacros-0.0.1-py3.9.egg/pyzacros/__init__.py", line 16, in __autoimport
    tmp = __import__(imp, globals=globals(), fromlist=['*'], level=1)
  File "/Users/plopez/Programs/miniconda3/envs/osp/lib/python3.9/site-packages/pyzacros-0.0.1-py3.9.egg/pyzacros/utils/RKFLoader.py", line 8, in <module>
    from pyzacros.utils.setting_utils import get_unique_reactions
ImportError: cannot import name 'get_unique_reactions' from 'pyzacros.utils.setting_utils' (/Users/plopez/Programs/miniconda3/envs/osp/lib/python3.9/site-packages/pyzacros-0.0.1-py3.9.egg/pyzacros/utils/setting_utils.py)

Can you take a look? Thanks!

Hi @lopeztarifa ,

Could you please make a double-check that you are using the latest version? The function get_unique_reactions should no longer exist.

nfaguirrec commented 3 years ago

Regarding your first question. The name of the function to load input zacros files is load_external. You can see some examples in tests/test_ZacrosJob.py. This function will load all the input files in the given directory (energetics_input.dat lattice_input.dat mechanism_input.dat simulation_input.dat).

If I have all the input files ready, then I might as well run zacros directly on that path sweat_smile

I think it would be useful to be able to load any ***_input.dat and turn it into some pyZacros object that can be modified from the script, and then passed to ZacrosJob.

At the moment I'm doing this:

CO2_adsorbed = Species("CO2*", 2)

with open('/home/ssmeets/reaxpro-wrappers/examples/Zacros_inputs/lattice_input.dat') as f:
    lattice = f.read()

with open('/home/ssmeets/reaxpro-wrappers/examples/Zacros_inputs/energetics_input.dat') as f:
    cluster_expansion = f.read()

myJob = ZacrosJob(settings=sett,
                  mechanism=myMechanism, 
                  # additional_species=[CO2_adsorbed], ??
                  lattice=lattice,
                  cluster_expansion=cluster_expansion,
                  )

I'm not sure if this is the correct way to use ZacrosJob class, but it seems to work for now. I'm missing a way here to specify extra surface species, which is available in the CO_tutorial branch. Is there any plan to get this feature or branch merged? Or is there some other way to achieve this?

Hi @stefsmeets,

I'm really surprised that your code works. It should not. If you have all the input files (energetics_input.dat, lattice_input.dat, mechanism_input.dat, and simulation_input.dat) in the directory '/home/ssmeets/reaxpro-wrappers/examples/Zacros_inputs', you can reconstruct your job with the following line:

job = ZacrosJob.load_external( path='/home/ssmeets/reaxpro-wrappers/examples/Zacros_inputs' )

After that, you can run it as follows:

job.run()

and then to access the results with lines as for example:

data = job.results.provided_quantities()
print(data)
job.results.plot_lattice_states()
stefsmeets commented 3 years ago

I'm really surprised that your code works. It should not.

Well, it works up till that point. When I do job.run() it crashes because it can't find the CO2 gas surface species, so I need to specify it somewhere, but I don't know how.

Error code 8004: reference to an unknown species in energetics_input.dat.

More information: 
Encountered unknown surface species "CO2*" in line 61.

If you have all the input files (energetics_input.dat, lattice_input.dat, mechanism_input.dat, and simulation_input.dat) in the directory '/home/ssmeets/reaxpro-wrappers/examples/Zacros_inputs', you can reconstruct your job with the following line:

I don't want to load the entire Zacros input (if I did, I would run zacros directly). The goal afaik is to be able to specify the entire reaction from python, but I don't know how to do that yet.

nfaguirrec commented 3 years ago

ohhh, I see. Now I understand what you want to do. For that, I have the functions e.g., ZacrosJob.__recreate_mechanism_input(path). But as you can see, they are private methods. I didn't design them to be used as you are trying to do. The idea is to work everything on the pyZacros side and eventually, brig all your Zacros input files into pyZacros if needed, but not mix both cases. I need to think more about the possible consequences of exposing these methods to the users. I think it is not a good idea, but maybe I can make something more robust. I will be back to this matter later, but if you can make your script in a different way, for now, it would be better.

stefsmeets commented 3 years ago

Do you have any recommendations on how to approach or work-around this issue?

The solution using additional_species in the CO_tutorial branch seems to work nicely: https://github.com/SCM-NV/pyZacros/blob/b808e2b4ed12919d390a8db0fae7ff1d0bd135ff/pyzacros/classes/KMCJob.py#L21-L26

Unfotunately, the branch has not much activity recently. What are your plans to merge that feature into the master branch?

nfaguirrec commented 3 years ago

No. That option additional_species is not a good idea because the species must always be consistent with the clusters_expansion and the mechanism. To do that, you first have to create the species and then use them to create the cluster_expansion and mechanism. So, we are not planning to merge that feature into the master branch.

One possible workaround that just came to my mind is as follows:

  1. Load the whole set of zacros files
    job = ZacrosJob.load_external( path='/home/ssmeets/reaxpro-wrappers/examples/Zacros_inputs' )
  2. Modify or replace the settings/mechanisms/lattice/cluster_expansion, e.g.
    mechanism2 = job.mechanism
    mechanism2.pop() # For example remove the last reaction
  3. Create a new job using the modified settings/mechanisms/lattice/cluster_expansion:
    job2 = pz.ZacrosJob( settings=settings2,
                         lattice=lattice2,
                         mechanism=mechanism2,
                         cluster_expansion=cluster_expansion2 )
  4. Run the new job:
    job2.run()

    I think this is a very clean way to do this. Please, let me know if it works for you.

stefsmeets commented 3 years ago

Thanks for the suggestion! Unfortunately, that does not solve the problem. I need to specify some additional species that are part of my energetics_input.dat but that are not part of a mechanism, as @lopeztarifa also wrote in the OP.

If I specify them in simulation_input.dat, and then use load_external, and then save the job, these species get removed, because pyzacros only writes surface species that are part of a mechanism: https://github.com/SCM-NV/pyZacros/blob/d75d7c8604c8cc2f45dd7573418967858106b7d4/pyzacros/core/ZacrosJob.py#L193

Here is a minimal example to illustrate the bug, if I do:

from pyzacros.core.ZacrosJob import ZacrosJob
import scm

scm.plams.init()

job = ZacrosJob.load_external('.')

job2 = ZacrosJob(
    settings=job.settings,
    lattice=job.lattice,
    mechanism=job.mechanism,
    cluster_expansion=job.cluster_expansion
)
job2.run()

I get an error (https://github.com/SCM-NV/pyZacros/issues/59#issuecomment-948578777), but if I run zacros.x directly, it works fine. I think this is a bug in pyzacros, because it does not write the CO2 species in simulation_input.dat.

I have attached the offending input files below. Could you have a look at them and let me know what you think?


issue59.zip

nfaguirrec commented 3 years ago

Hi @stefsmeets,

Thanks for the example. It is indeed a bug in pyZacros. Nice catch! I already fixed it. Could you please give it a try again?

stefsmeets commented 3 years ago

Nice work, thanks for the quick fix. Seems to work on my side as well, and also my script is now running! This issue can be closed. 🥳

nfaguirrec commented 3 years ago

Great! Thanks!