This tutorial will show you how to build a simple lemmings workflow. The CFD part will be handled by Barbatruc, an open-source python package.

Step 1: install packages

pip install lemmings
pip install barbatruc

Step 2: Get barbatruc file

Copy to your current folder the tuto’s files using the command : lemmings get_tuto_files

The cylinder_lem.py file represent the CFD code that calculate the flow around a cylinder. You don’t have to open this file.

Step3: Create Workflow’s files

Create two files with the same name:

  • with “.yml” extension (Parameters required by the workflow)

  • with “.py” extension (Workflow script)

For example:

./tuto_lem.py

./tuto_lem.yml

Step4: Complete the common part of the .yml

In all lemmings workflows, there are mandatory parameters that you have to specify :

exec: |
      source "your/virtual_env/path"        #specific to your virtual env
      python3 cylinder_lem.py               #specific to this workflow
exec_pj: |
      source "your/virtual_env/path"
job_queue: debug
pjob_queue: debug_pj
cpu_limit: 10
  • exec / exec_pj : Custom part of your batch. Commonly, this is your virtual_env and the script to execute if it is needed.

  • job_queue / pjob_queue : Specify wich queue configuration you want to use for your Job and Post-job. To find the available machine’s queues, use the command : lemmings info. Choose the appropriate queues to your case.

  • cpu_limit : The CPU limit you want to set (to prevent infinite/very long calculation)

Step 5: Complete the custom part of the .yml

If you need specific input(s) for your workflow, you have to define it in the .yml. For example, for this workflow:

custom_run:
    nsave: 150            #nsave per loop
    simu_end_time: 7.9    #final end time desired
    diameter: 0.05        #cylinder diameter

Step 6: Create the workflow’s frame

There are 7 mandatory methods that compose all lemmings classes. They are defined as follow (in the .py file):

class LemmingJob(LemmingJobBase):
    """
    A lemming job follows always the same pattern.
    START > SPAWN JOB> POST JOB > SPAWN JOB > POST JOB > EXIT

    each step can be customized in the present class.
    e.g. you control the nb. of SPAWN JOB>POST JOB with the 'Check on end` function.


                 Prior to job  +---------+             Prepare run
                     +--------->SPAWN JOB+---------------------+
                     |         +------^--+                     |
                     |                |                      +-v------+
                   True               |                      |POST JOB|
    +-----+          |                |                      +--------+
    |START+--->Check on start         |                          v
    +-----+          |                +---------------False-Check on end
                   False            Prior to new iteration       +
                     |                                         True
                     |                                           |
                     |                                           |
                     |           +----+                          |
                     +---------->|EXIT|<-------------------------+
               Abort on start    +----+                After end job

    you can use the database if you need to store info from one job to the other.

    """

    def prior_to_job(self):
        """
        Function that prepare the run when the user launch the Lemmings command.
        """

    def abort_on_start(self):
        """
        What lemmings do if the criterion is reached in the first loop.
        """
        pass

    def prepare_run(self):
        """
        Prepare the run before submission
        """
        pass

    def prior_to_new_iteration(self):
        """
        Prepare the new loop specifics actions if criterion is not reached
        """
        pass

    def after_end_job(self):
        """
        Actions just before lemmings end
        """

    def check_on_start(self):
        """
        Verify if the condition is already satisfied before launching a lemmings chain.
        """
        start_chain = True
        return start_chain


    def check_on_end(self):
        """
        Verifications after each job loop
        """
        condition_reached = False
        if ...:
            condition_reached = True

        return condition_reached

Note: All lemmings classes have to be named LemmingJob and inherit the mother class LemmingJobBase

Step 7: Complete Lemmings methods

Now you can complete all Lemmings methods to fit your project. The check_on_end and check_on_startmethods have to return a boolean that will determine the next method used (as explain in the scheme in the class description).

  • Create your batch with lemmings: As Lemmings is a job scheduler, you have to create a batch which will be executed by your machine. You can create a sub-method or write it directly in lemmings methods. No matter which case you choose, it have to be executed it in the prior_to_joband prior_to_new_iteration methods as follow:
    def prior_to_job(self):
        self._create_batch()

    def prior_to_new_iteration(self):
        self._create_batch()

    def _create_batch(self, batch_j="./batch_job", batch_pj="./batch_pjob"):
        """
        Create the batch that will launch the postjob loop of lemmings.
        The construction is based on namedtuple that are unique for each machine.
        So the user, if not already done, have to set up those namedtuple for his machine(cluster).
        """
        batch_job = self.machine.job_template.batch + #whatever you need

        batch_pjob = (self.machine.pj_template.batch + '\n'
                      + "lemmings run "
                      + str(self.workflow)
                      + " -s post_job" + '\n')

        with open(batch_j, 'w') as fout:
            fout.write(batch_job)
        with open(batch_pj, 'w') as fout:
            fout.write(batch_pjob)

Note:

  1. The batch_pjob must be written as below without any addition unlike batch_job.

  2. The self.machine.job_template.batch correspond to the defined machine batch header. You can display it using lemmings infocommand.

  3. Use .yml custom parameters : to use the customs_runparameters defined earlier, call it as follow :

{your_param} = self.machine.user.custom_run["{your_param}"]

Step 8: Complete your workflow according to your case

Finally, complete, write and order your workflow to fit your case.

Few tips:

  • Use lemmings database : The right way to exchange/store parameters between loops is to use the lemmings database. There are 6 database methods.
self.database.update_current_loop('key', value)
self.database.update_previous_loop('key', value)
self.database.update_first_loop('key', value)

self.database.get_current_loop_val('key')
self.database.get_previous_loop_val('key')
self.database.get_first_loop_val('key')
  • If you want to make post-processings that don’t need to relaunch another loop, write it in the after_end_job() function.

  • Prefere sub-functions rather than overload main functions

For example:

def after_end_job(self):
    """
    Actions just before lemmings end
    """
    time = []
    ib_force_y = []
    with open("concatenated_results.yml", 'r') as fin:
        data_dict = yaml.load(fin, Loader=yaml.FullLoader)

    for step in data_dict:
        time.append(step["time"])
        ib_force_y.append(step["ib_force_y"])

    plt.plot(time, ib_force_y)
    plt.savefig("result.png")
    plt.clf()

    self.compute_fft(ib_force_y, time)

Step 9: Launch your lemmings case

When your workflow (.yml + .py) is completed, You can launch it by using lemmings run {workflow_name}. All your lemmings files must be in your current folder. If you want to try lemmings without writing a workflow you can find a complete case at : lemmings/tuto_barbatruc.

When lemmings ends you can show the log, typing lemmings status

Like this post? Share on: TwitterFacebookEmail


Keep Reading


Published

Category

Tutorials

Tags

Stay in Touch