5

I need to run multiple times the same abaqus .inp file (slightly changed within runs) and after each run ends I need to submit a abaqus python script that will read the results.

I've done the following:

#run the programme
os.system('abaqus job=file_name cpus=2')

#get results and write them to myresults.txt
os.system('abaqus viewer noGUI=python_name.py')

However, the main program executes the second line before the program started in the first line ends. As a result I get an error. How can I solve this?

Philipp
  • 222
  • 3
  • 9
jpcgandre
  • 1,487
  • 5
  • 31
  • 55
  • possible duplicate: http://stackoverflow.com/questions/8953119/python-waiting-for-external-launched-process-finish – Sean Mar 11 '12 at 19:56
  • Yes, but my case is: "the process you are launching is likely detaching itself to run in the background in which case the subprocess.Popen + wait example Dor gave won't help." – jpcgandre Mar 11 '12 at 20:18
  • This worked for me (however I've not tried interactive yet and maybe it will work): os.system('abaqus job=file_name') PATH='...\\file_name.lck' if not path.exists(PATH): time.sleep(1) while path.exists(PATH) and path.isfile(PATH) and access(PATH, R_OK): temp = 0 else: odb = openOdb(path='file_name.odb') Hope this helps others – jpcgandre Mar 12 '12 at 16:34

7 Answers7

7

I guess the problem here is not about subprocess waiting (indeed it waits) but the fact that after running the solver, Abaqus takes some seconds to delete some temp files and close its odb. I suggest one of the following:

  • run the solver from the command line with 'interactive' as @glenn_gould proposed

    strCommandLine = 'abaqus interactive job=jobname'  
    subprocess.call(strCommandLine)
    
  • run an abaqus python script

    strCommandLine = 'abaqus python ScriptToRun.py -- (jobname)'  
    subprocess.call(strCommandLine)
    

    and within ScriptToRun.py use waitForCompletion() as @ellumini proposed

    from abaqus import *
    import job
    import sys
    
    jobname = mdb.JobFromInputFile(sys.argv[-1], sys.argv[-1]+".inp") 
    jobname.submit() 
    jobname.waitForCompletion()
    
  • use a try statement to run while file jobname.023 or jobname.lck exist, something like:

    strCommandLine = 'abaqus job=jobname'  
    subprocess.call(strCommandLine)
    
    while os.path.isfile('jobname.023') == True:
        sleep(0.1)
    

This was my first post in this magnificent community, I'd be glad to know if I did something wrong.

Francisco Cruz
  • 314
  • 3
  • 13
3

I think you need system('abaqus job=inputfile.inp interactive')

interactive does not consider the system command finished until abaqus has finished running.

Without interactive abaqus runs in the background while the system command is over and we have moved to the next one which is what we do not want.

1

not sure if you've already found an adequate solution, but the job object:

Jobxy.waitForCompletion() 

awaits the completion of a job and then continues executing the pyhton script; for example with commands regarding post processing. See abaqus scripting users manual for further details...

Kevin Brown-Silva
  • 40,873
  • 40
  • 203
  • 237
ellumini
  • 11
  • 1
1

Take a look at the subprocess module. The call methods waits until the process is finished. You can also get a much better control over the child process than using os.system().

El Barto
  • 919
  • 1
  • 5
  • 18
  • Hi! Yes there's another thread about this but it seems that it is not OK for my problem since I don't get the second line to run. Maybe the subprocess module needs to have an ouput. In my case I just need it to finish because it will not return anything. Many thanks! – jpcgandre Mar 11 '12 at 20:16
  • 1
    AFAIK, `subprocess` is the current recommended way to work with system calls (as @Multimedia Mike mentioned in the other answer). The thing is if abaqus starts running un background, which would mean that detaches from the process that subprocess called. If that the case, as someone said in another question, you should check how to make abaqus run in foreground. If this can't be done, then you should code your own loop that monitors the abaqus background process to see when it ends. – El Barto Mar 11 '12 at 21:36
  • 2
    I think the argument you need is "abaqus interactive" , presumably as opposed to the default "abaqus background" ( http://www-h.eng.cam.ac.uk/help/amb/programs/fe/faq68/abaqusf2.html ) – TimStaley Mar 12 '12 at 13:32
1

The subprocess module has been recommended in another answer. That's the officially recommended way to do this. However, a quicker and easier method (and also deprecated in Python 3, but still works fine in 2.x, so take that into consideration) is the commands module.

import commands
(return_code, output) = commands.getstatusoutput('abaqus job=file_name cpus=2')
Multimedia Mike
  • 12,660
  • 5
  • 46
  • 62
  • Hi! The thing is that the first program does not return nothing, it has only to finish. Once it has the second line will do the rest. Is this what I should do? subprocess.call([os.system('abaqus job=file_name cpus=2')]) subprocess.call([os.system('abaqus viewer noGUI=python_name.py')]) – jpcgandre Mar 11 '12 at 20:12
  • I'm getting a bit confused at this point-- it sounds like you want to call the first command, block until that command finishes, then call the second command. I just tested both os.system() and commands.getstatusoutput()-- both of them cheerfully block until the command finishes execution. Does your command fork background processes and return immediately? – Multimedia Mike Mar 11 '12 at 20:18
  • Hi! The program I call runs as a background program so as I've read in another thread: "the process you are launching is likely detaching itself to run in the background in which case the subprocess.Popen + wait example Dor gave won't help." Any comments would be very appreciated. – jpcgandre Mar 11 '12 at 20:20
  • You have a few options: 1) Modify the source code of abaqus to not exit until its subprocesses have finished (perhaps add a command line option to run the program in blocking mode). 2) Modify abaqus to write a file when it's running and delete it when it's finished; poll/select that file. 3) Obtain the PIDs of the abaqus subprocesses and check when they are finished before proceeding. – Multimedia Mike Mar 11 '12 at 20:25
  • OK! I'll try but maybe it is better to clarify my problem. I'm using a given program that reads python to control my analysis. So this main python script calls abaqus and submits a job (job=file_name), then after abaqus finishes the job, the main python script submits an abaqus python script which will read th abaqus results file and extract some results to a txt file. Finally, the main python script will read the txt file. My problem is that the main program does this without checking if abaqus has finished and I get an error. – jpcgandre Mar 11 '12 at 20:32
1

About running in the background, are you sure it is?

This site suggests that os.system('abaqus job=file_name cpus=2') would be running in the foreground.

Using Abaqus in Batch Mode To invoke the Abaqus System in batch mode, you must specify a filename in the Abaqus >command. For example, if you want myProg.inp to excute:

abaqus job=myProg

(Note that no extension should follow the file name)

This command should start Abaqus in batch mode. The command will run the program in the foreground. If you want to run the program in the background add the ampersand to the end of the command:

abaqus job=myProg &

Maybe there is a local configuration setting that is forcing background processing? If so perhaps you can add a switch to make sure processing is in the foreground.

Community
  • 1
  • 1
Sean
  • 15,561
  • 4
  • 37
  • 37
  • OK. This helped. So I used subprocess.call([os.system('abaqus job=file_name cpus=2')]) subprocess.call([os.system('abaqus viewer noGUI=python_name.py')]) but the second line is never called. I don't know why it does that. I'm sure it does not read the second line since if I call the second line without the first (insert a comment symbol) it runs and I get the expected results (because the output files exist). – jpcgandre Mar 11 '12 at 20:39
  • I also get an error "argument of type 'int' is not iterable" if I use subprocess.call([os.system('abaqus job=file_name cpus=2')]) – jpcgandre Mar 11 '12 at 20:44
  • Whoa! Don't do that. :-) Use subprocess or os.system(), but not both in tandem. – Multimedia Mike Mar 11 '12 at 20:49
  • Yes, sorry for this. I runs nevertheless. ALthough the second line does not. If I use subprocess.call(['abaqus job=file_name cpus=2']) I get an error: system cannot find the file specified... If I use os.system it will not run the second line and hangs. – jpcgandre Mar 11 '12 at 20:57
  • You may need to specify the full path for abaqus if it's not on your `PATH`. – El Barto Mar 11 '12 at 21:33
  • Indeed, if you haven't already check to see the first command is actually doing something (from the command line, it produces a file right?). – Sean Mar 11 '12 at 21:45
  • The first command does what it's supposed to do. The job ends. What happens is that the second command which would submit a abaqus python script to read the results file does not start. – jpcgandre Mar 11 '12 at 21:52
0

Try using subprocess but without the os.call option. You can use this method to run Abaqus in the background:

import subprocess
path = location of file in any directory 
abaqusCall = 'abaqus job=file_name cpus=2'
runCommand = 'cmd.exe /c ' + abaqusCall
process = subprocess.Popen(runCommand, cwd=path)

The problem with Abaqus is that it takes a long time to run the analysis, so if you try to run your "python_name.py" file in order to get results, the program might get errors because the *.odb file either has not been created yet, or does not contain the data that need extraction.

You can use the command:

process.wait()

to tell Python to wait for Abaqus to finish the analysis before executing your "python_name.py", but this will hang your python command (or GUI) until Abaqus is done, which will take a long time.

One method I use is to read the *.sta file from Abaqus which has the solution time and progress. So, you can write a sequence to read the file every 5 seconds for example, and monitor when the job ends before executing your result extraction file.

Another trick for data extraction is that as long you do not use (import) classes from the CAE module, you can run your Python script using this command:

#get results and write them to myresults.txt
os.system('abaqus python python_name.py')
Nader
  • 660
  • 1
  • 11
  • 17