-2

I have a black box legacy FORTRAN package for solving PDEs (partial differential equations) with a python wrapper. Sometimes the FORTRAN PDE solver takes a long time to converge. If the FORTRAN is taking too long to converge, I would like my python script to be able to force the FORTRAN to stop so the python can finish running, perhaps with an error message.

Any thoughts on how to automate this watchdog timer sort of behavior in python when working with a wrapped FORTRAN black box? Would it be possible with multiprocessing?

  • I'm no fortran expert but you might be able to use a callback function to return progress values of the fortran code. This might be relevant https://stackoverflow.com/questions/17198642/callback-python-from-fortran – Lucas Roberts Feb 24 '22 at 15:46
  • How is the wrapping done? Is the FORTRAN package a separate executable altogether? – jjramsey Feb 24 '22 at 15:50
  • I did not create the wrapper, but as far as I can tell the python code calls the FORTRAN executable. – Michael Mortenson Feb 24 '22 at 20:58

1 Answers1

0

I found a solution that worked using python's built-in multiprocessing module. Here is a simplified version of my solution. The FORTRAN blackbox has been replaced in the code below with the do_calculation() method. I would be interested in better ways to answer this question, but for now, this is the way I am doing it. Here is the most helpful youtube video I found: https://www.youtube.com/watch?v=iwFGC_3sVio&t=622s

import multiprocessing as mp
import time
import numpy as np

def timer_func(seconds, queue):
    print(f" {seconds}-second timer started")
    time.sleep(seconds)
    print("Time up!")
    queue.put("Time up!")
    pass

def do_calculation(listy_list, queue):
    print("Starting Calculation!")
    time.sleep(10)
    output = 0
    for i in listy_list:
        output = np.sqrt((output+i)*i)
    print("Done Calculating!")
    queue.put(output)
    pass

def main():
    in_list = np.arange(0,10000)

    queue = mp.Queue()

    p1 = mp.Process(target=do_calculation, args=[in_list, queue])
    p2 = mp.Process(target=timer_func, args=[3, queue])

    p1.start()
    p2.start()

    result = queue.get()
    print(f"Queue returned {result}")
    if result == "Time up!":
        p1.terminate()
        print("p1 terminated")
    else:
        p2.terminate()
        print(f"Queue resturned {result}")

    p1.join()
    p2.join()

    # print(f"result of p1 {result}")
    pass

if __name__ == '__main__':
    main()
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 25 '22 at 20:59
  • Updated to include the main resource I used besides the multiprocessing module docs. – Michael Mortenson Feb 25 '22 at 23:47