Possible to store multiple StructureData

Hello everyone,

I’m working on a new workflow within the aiida-environ module. We want to pass in multiple structures and we aren’t sure how many there will be. My initial thought is to make a list of StructureData objects and then store them as a List. This appears to not be allowed. I see that there is a TrajectoryData object but that species that the number of atoms and species must stay constant. What is the best way to store multiple StructureData objects? I wasn’t quite sure how to look that up in the documentation. Thanks.

Nathan

When you say “you want to pass in”, I take it you mean you want to pass multiple StructureData nodes as input to some kind of a process, e.g. a calcfunction or WorkChain? These have each a separate solutions.

For process functions (such as a calcfunction) you can use variadic arguments just as in normal Python functions:

from aiida.engine import calcfunction

@calcfunction
def take_multiple_structures(**kwargs):
    for link_label, structure in kwargs.items():
        # Here `structure` will be a `StructureData`


# Now you can call it with an arbitrary number of structures. Note that the 
# keys need to be valid identifiers, so just alphanumeric with underscores.
take_multiple_structures(struc_a=StructureData(), struc_b=StructureData(), etc....)

For WorkChains you would use dynamic input namespaces. These namespace simply declare a type, but don’t have to specify exactly which labels they expect but can take any number. Example:

from aiida.engine import WorkChain
from aiida.orm import StructureData

class SomeWorkChain(WorkChain)

    @classmethod
    def define(cls, spec):
        super().define(spec)
        spec.input_namespace('structures', valid_type=StructureData)
        spec.outline(cls.do_something)

    def do_something(self):
        for label, structure in self.inputs.structures.items():
            # Here label is again link label and `structure` the `StructureData` passed as inputs

# This would be launched as 
inputs = {
    'structures': {
        'struc_a': StructureData(),
        'struc_b': StructureData(),
    }
    ....
}
submit(SomeWorkChain, **inputs

Thanks Sebastiaan. Hope things are going well over there for you. I’ll look at getting this working today.

1 Like