"""API for running a SMITER case. This is meant to be used in SALOME batch mode
or script mode. This will run the SMITER computation and perform basically the
same as the GUI SMITER_API.ComputeCase, except it is not using PyQt5, to avoid
raising the complexity when writing batch scripts.
"""
import subprocess
try:
from SMESH_utils import createVTKfromSMESH
import SMITER_utils
import salome
except Exception as e:
print(e)
import os
from glob import glob
def findall(string, char):
out = []
i = string.find(char)
while i != -1:
out.append(i)
i = string.find(char, i+1)
return out
def parseMpiCommand(mpiComm):
# Find all quotes
indexes = findall(mpiComm, '\'')
if not indexes:
return mpiComm.split()
out = []
start = 0
for i, j in zip(indexes[::2], indexes[1::2]):
end = i
out += mpiComm[start:end].split()
out += [mpiComm[i:j]]
start = j
return out
class ComputeProcess(object):
"""Runs SMARDDA executables with subprocess module.
"""
compPsiRef, compTarg, compShad, compHdsg, compPowc, compMag = range(6)
def __init__(self):
self.runDir = ''
self.smiterDir = ''
self.smarddaExec = {}
self.smarddaArgs = {}
self.runPaths = {}
self.queue = []
self.useMPI = False
self.commandMPI = ''
self._currentCommand = -1
self._currentTarget = -1
self.completionStatus = True
def outputLog(self, msg=None):
if msg is None:
print('\n')
else:
print(msg)
def setMPI(self, bool):
self.useMPI = bool
def setMPICommand(self, command):
self.commandMPI = str(command).replace('%', '$')
def setRunDir(self, runDir):
self.runDir = runDir
def setSmiterDir(self, smiterDir):
self.smiterDir = smiterDir
self.setExecPaths()
def setExecPaths(self):
execDir = os.path.join(self.smarddaDir, 'exec')
self.smarddaExec[self.compPsiRef] = os.path.join(execDir, 'geoq')
self.smarddaExec[self.compTarg] = os.path.join(execDir, 'geoq')
self.smarddaExec[self.compShad] = os.path.join(execDir, 'geoq')
self.smarddaExec[self.compHdsg] = os.path.join(execDir, 'hdsgen')
self.smarddaExec[self.compPowc] = os.path.join(execDir, 'powcal')
self.smarddaExec[self.compMag] = os.path.join(execDir, 'magtfm')
self.smarddaExec[self.compCase] = os.path.join(execDir, 'smiter')
def checkForSMARDDAexecutables(self):
"""This function checks if SMARDDA modules exists (geoq, powcal,
hdsgen) and warns the user if they do not exist.
"""
geoq = os.path.join(self.smarddaDir, 'exec', 'geoq')
hdsgen = os.path.join(self.smarddaDir, 'exec', 'hdsgen')
powcal = os.path.join(self.smarddaDir, 'exec', 'powcal')
magtfm = os.path.join(self.smarddaDir, 'exec', 'magtfm')
smiter = os.path.join(self.smarddaDir, 'exec', 'smiter')
PASSED = True
missing = []
if os.path.isfile(geoq) and os.access(geoq, os.X_OK):
pass
else:
PASSED = False
missing.append(geoq)
if os.path.isfile(hdsgen) and os.access(hdsgen, os.X_OK):
pass
else:
PASSED = False
missing.append(hdsgen)
if os.path.isfile(powcal) and os.access(powcal, os.X_OK):
pass
else:
PASSED = False
missing.append(powcal)
if os.path.isfile(magtfm) and os.access(magtfm, os.X_OK):
pass
else:
PASSED = False
missing.append(magtfm)
if os.path.isfile(smiter) and os.access(smiter, os.X_OK):
pass
else:
PASSED = False
missing.append(smiter)
if not PASSED:
self.outputLog.emit('Missing executables:')
for exe in missing:
self.outputLog.emit('\t%s' % exe)
self.outputLog.emit('Check if SMARDDA is compiled.')
self.outputLog.emit('Or check if the SMARDDA path is correctly set'
' in SMITER preferences!')
self.outputLog.emit('cd $SMITER_DIR')
self.outputLog.emit('./exec/build')
return PASSED
def setComputeCommands(self, computeCommands):
self.queue = computeCommands
def setCurrComm(self, command):
self._currentCommand = command
def getCurrComm(self):
return self._currentCommand
def setCurrTarg(self, target):
"""Set the current target. Not to be confused with target GEOQ. This
is simply the name of the current ctl
"""
self._currentTarget = target
def getCurrTarg(self):
return self._currentTarget
def compute(self):
if self.queue:
# Reset completion status
self.completionStatus = True
# Run a subprocess
command, arg = self.queue.pop(0)
executable = self.smarddaExec[command]
wholeCommand = ''
if self.useMPI:
# Check if $SMITER is inside
if '$SMITER' in self.commandMPI:
wholeCommand = self.commandMPI.replace('$SMITER',
f'{executable} {arg}')
if '$JOBNAME' in self.commandMPI:
if wholeCommand:
wholeCommand = wholeCommand.replace('$JOBNAME',
executable)
else:
wholeCommand = self.commandMPI.replace('$JOBNAME',
executable)
else:
wholeCommand = f'{self.commandMPI} {executable} {arg}'
if self.shell:
executable = self.shell
args = ['-c', wholeCommand]
wholeCommand = f'{executable} -c "{wholeCommand}"'
else:
split = parseMpiCommand(wholeCommand)
executable = split[0]
args = split[1:]
else:
wholeCommand = f"{executable} {arg}"
args = [arg]
split = [executable] + args
print('Running command %s' % wholeCommand)
# Both executable and arg are lists!
proc = subprocess.Popen(split,
cwd=self.runDir, stdout=subprocess.PIPE)
while 1:
output = proc.stdout.readline()
returnCode = proc.poll()
if output == '' and returnCode is not None:
break
else:
self.outputLog(output.strip())
returnCode = proc.poll()
path = self.runPaths[command]
target = arg # Name of the CTL
if returnCode:
self.completionStatus = False
# Command failed!
self.outputLog('Command %s failed!' % ' '.join(executable +
[arg]))
logFile = path + '/' + target + '.log'
if os.access(logFile, os.F_OK | os.R_OK):
with open(logFile, 'r') as f:
self.outputLog(f.read())
self.queue = []
self.completionStatus = False
return
# Check if command == self.compPsiRef
if command == self.compPsiRef:
# Read the *_geoq.out to read the psibdry value, to assign the
# value to the target and shadow beq_psiref parameter.
outFile = os.path.join(self.runDir, f'wall/geoq_geoq.out')
psiRef = None
if os.path.isfile(outFile) and os.access(outFile, os.R_OK):
with open(outFile, 'r') as f:
READ_PSIBDRY = False
for line in f:
# Strip white spaces
sline = line.lstrip()
if sline.startswith('psibdry'):
READ_PSIBDRY = True
continue
if READ_PSIBDRY:
# Read psibdry and finish reading the output file.
psiRef = line.strip()
break
else:
self.outputLog.emit('Missing output file to read PSIREF from!')
if psiRef:
# It might be dangerous but, usually there is no cause to have
# PSIREF in a ctl.
targetCtl = [os.path.join(self.runDir, _, 'geoq.ctl') for _
in ['target', 'shadow']]
for file in targetCtl:
with open(file, 'r') as f:
ctl = f.read()
ctl = ctl.replace('PSIREF', psiRef)
with open(file, 'w') as f:
f.write(ctl)
if command == self.compMag:
# Link the resulting sp3 file to Powcal directory
magDir = os.path.join(self.runDir, 'mag')
powcalDir = os.path.join(self.runDir, 'power')
shadowDir = os.path.join(self.runDir, 'shadow')
targetDir = os.path.join(self.runDir, 'target')
if os.path.exists(self.runPaths[self.compPowc]):
sp3File = glob('%s/*.sp3' % magDir)
for file in sp3File:
if os.name == 'posix':
targetLink = os.path.join(powcalDir,
os.path.basename(file))
if os.path.exists(targetLink):
os.unlink(targetLink)
os.symlink(file, targetLink)
targetLink = os.path.join(targetDir,
os.path.basename(file))
if os.path.exists(targetLink):
os.unlink(targetLink)
os.symlink(file, targetLink)
targetLink = os.path.join(shadowDir,
os.path.basename(file))
if os.path.exists(targetLink):
os.unlink(targetLink)
os.symlink(file, targetLink)
self.outputLog('test')
self.compute()
else:
# Finished with commands
passed = 'Passed' if self.completionStatus else 'Failed'
self.outputLog('Finished batch of commands. Status: %s.' %
passed)
[docs]class ComputeCase(object):
"""The attributes are the same of SMITER_API.ComputeCase
"""
compPsiRef, compTarg, compShad, compHdsg, compPowc, compMag = range(6)
def __init__(self):
self.smiterCase = None
self.smiterDir = ''
self.caseDirectory = ''
self.tabIndex = 0
self.commands = []
self.openInParaVieW = False
self.savePowcalResults = False
self.clean = False # Flag if you wish to rewrite meshes.
self.preparationsFlag = False
self.batchPrepare = False
self.computeLock = False
self.computeFieldlineFlag = False
self.previousPlotFlinx = ''
self.previousOpen_PV = None
self.runDir = ''
self.computeCommands = []
self.computeProcess = ComputeProcess()
self.saveToCase = False
def outputLog(self, msg=None):
if msg == None:
print('\n')
else:
print(msg)
[docs] def setSmiterDir(self, smiterDir):
"""Setter for SMITER directory.
"""
self.smiterDir = smiterDir
[docs] def setCaseDir(self, caseDirectory):
"""Setter for directories where the cases will be run.
"""
self.caseDirectory = caseDirectory
def setMPI(self, bool):
self.computeProcess.setMPI(bool)
def setMPICommand(self, command):
self.computeProcess.setMPICommand(command)
[docs] def getSettings(self):
"""Does nothing since batch mode is run in non-GUI mode and thus no
settings can be retrieved from SMITER-GUI preferences
"""
pass
[docs] def setCase(self, case):
"""Receives reference to SMITERcase object.
Arguments:
case (SMITER_ORB__POA.SMITERcase): Reference to CORBA object that
holds all the information about the case.
"""
self.smiterCase = case
[docs] def findAndSetCase(self, caseName):
"""Function that searches a case with the name ``caseName`` under the
SMITER component. Works only when GUI is enabled!
Arguments:
caseName (str): Name of the case. A Salome object holds the name
of the case and the reference to the CORBA object
``SMITER_ORB__POA.SMITERcase``.
"""
study = salome.myStudy
comp = SMITER_utils.findOrCreateComponent()
iter = study.NewChildIterator(comp)
while iter.More():
sObj = iter.Value()
name = sObj.GetName()
if name == caseName:
self.setCase(sObj.GetObject())
return True
iter.Next()
return False
[docs] def prepareRunDirectory(self):
"""Runs the QThread to first prepare the directory for the case. Then
it goes through the :attr:`commands`
"""
# Check if we have a case object
# Flag that is put on True at the end of the fuction if everything
# prepared correctly.
self.preparationsFlag = False
# Flag for force writing the meshes again.
rewriteMesh = self.clean
if self.smiterCase is None:
# If for any reason start is being run
return
# Set the input parameters for each object (geoq, hdsgen, powcal)
if not self.smiterCase.setInputParameters():
self.outputLog('SMITERcase object failed to set parameters'
' for input files.')
return
if self.caseDirectory is None:
self.outputLog('No run directory set. Check preferences,'
' if the settings are correctly set.')
return
# Rename the tab in output viewer in case the case has been renamed.
self.renameTab.emit(self.tabIndex, self.smiterCase.getName())
runDirPath = os.path.join(self.caseDirectory,
self.smiterCase.getName())
# Check if directory exists
ok = os.path.isdir(runDirPath)
# Case status tells us if we have already run the case, in which case
# we do not necessarily write the VTK files. VTK files are first
# created by reading the SMESH objects, which can take some time.
if ok:
# Check if it is writable
if os.access(runDirPath, os.W_OK):
# See if there is a .status file
self.outputLog(f'Directory {runDirPath} already exists,')
self.outputLog('no need to create it.')
else:
# Directory is not writable. Perhaps a directory of other user?
# Cancel everything!
self.commands = []
msg = 'Write permission error with directory %s' % runDirPath
msg += '. Check if you are the owner of the directory or if'
msg += ' the path is valid.'
self.outputLog(msg)
return
else:
# No directory for this case yet.
self.outputLog('Creating run directory %s' % runDirPath)
os.makedirs(runDirPath)
# Create the directory structure here, in case there are future 'ideas'
# about new directory structure.
eqdskDir = os.path.join(runDirPath, 'eqdsk')
if not os.path.exists(eqdskDir):
self.outputLog('Creating eqdsk directory')
os.makedirs(eqdskDir)
else:
self.outputLog('Eqdsk directory already exists')
if self.compMag in self.commands:
magDir = os.path.join(runDirPath, 'mag')
if not os.path.exists(magDir):
self.outputLog('Creating mag directory')
os.makedirs(magDir)
else:
self.outputLog('Mag directory already exists')
self._t_cleanOutput(magDir)
if self.compPsiRef in self.commands or self.compCase in self.commands:
wallDir = os.path.join(runDirPath, 'wall')
if not os.path.exists(wallDir):
self.outputLog('Creating wall directory')
os.makedirs(wallDir)
else:
self.outputLog('Wall directory already exists')
self._t_cleanOutput(wallDir)
if self.compTarg in self.commands or self.compCase in self.commands:
targetDir = os.path.join(runDirPath, 'target')
if not os.path.exists(targetDir):
self.outputLog('Creating target directory')
os.makedirs(targetDir)
else:
self.outputLog('Target directory already exists')
self._t_cleanOutput(targetDir)
if self.compShad in self.commands or self.compCase in self.commands:
shadowDir = os.path.join(runDirPath, 'shadow')
if not os.path.exists(shadowDir):
self.outputLog('Creating shadow directory')
os.makedirs(shadowDir)
else:
self.outputLog('Shadow directory already exists')
self._t_cleanOutput(shadowDir)
if self.compHdsg in self.commands or self.compCase in self.commands:
hdsgenDir = os.path.join(runDirPath, 'hds')
if not os.path.exists(hdsgenDir):
self.outputLog('Creating hdsgen directory')
os.makedirs(hdsgenDir)
else:
self.outputLog('Hdsgen directory already exists')
self._t_cleanOutput(hdsgenDir)
if self.compPowc in self.commands or self.compCase in self.commands:
powcalDir = os.path.join(runDirPath, 'power')
if not os.path.exists(powcalDir):
self.outputLog('Creating powcal directory')
os.makedirs(powcalDir)
else:
self.outputLog('Powcal directory already exists')
self._t_cleanOutput(powcalDir)
# Go to directory
os.chdir(runDirPath)
self.outputLog('')
# 0. step. Check if EQDSK is written
eqdsk = self.smiterCase.getEQDSK()
eqdskName = eqdsk.getName().rsplit('/', 1)[-1]
eqdskPath = os.path.join(eqdskDir, eqdskName)
self.outputLog('Writing EQDSK file if necessary.')
if os.path.exists(eqdskPath):
self.outputLog('EQDSK file already exists.')
else:
self.outputLog('Writing EQDSK file.')
with open(eqdskPath, 'w') as f:
f.write(eqdsk.generateText())
# 0b. step. Check if PsiRef has to be computed
if self.compPsiRef in self.commands:
self.outputLog('')
wall = self.smiterCase.getWall()
wallName = wall.getName()
wallPath = os.path.join(wallDir, f"{wallName}.vtk")
if os.path.exists(wallPath) and not rewriteMesh:
self.outputLog('Wall mesh %s already exists.' %
wallPath)
else:
self.outputLog('Writing wall mesh to %s' % wallPath)
self._t_writeVTK(wallPath, wall)
self.outputLog('Writing CTL for wall GEOQ.')
self._t_writeCTL(os.path.join(wallDir, 'geoq.ctl'), wall)
# 0c. step. Check for Magnetigc ripple field data. If there is no data
# skip this step.
if self.compMag in self.commands:
self.outputLog('')
self.outputLog('Checking for magnetic ripple field data.')
magtfm = self.smiterCase.getMAGTFM()
magName = magtfm.getName()
magPath = os.path.join(magDir, magName)
if os.path.exists(magPath):
self.outputLog('Magnetic ripple field data %s is '
'already written.' % magName)
else:
self.outputLog('Writing magnetig ripple field data:'
' %s' % magName)
with open('%s.txt' % magPath, 'w') as f:
f.write(magtfm.getMAG())
self._t_writeCTL(os.path.join(magDir, 'magtfm.ctl'), magtfm)
# 1. step. Check if target GEOQ needs to be run
if self.compTarg in self.commands or self.compCase in self.commands:
self.outputLog('')
self.outputLog('Preparing directory for target GEOQ.')
# Now check if the VTK is written in the directory.
target = self.smiterCase.getTarget()
targetName = target.getName()
targetPath = os.path.join(targetDir, f"{targetName}.vtk")
if os.path.exists(targetPath) and not rewriteMesh:
self.outputLog('Target mesh %s already exists.' %
targetPath)
else:
self.outputLog('Writing target mesh to %s.' % targetPath)
self._t_writeVTK(targetPath, target)
# Write CTL. This is performed ALWAYS, since the file is small and
# is changed the most.
self.outputLog('Writing CTL for target GEOQ.')
self._t_writeCTL(os.path.join(targetDir, 'geoq.ctl'), target)
# 2. step. Check if shadow GEOQ needs to be run
if self.compShad in self.commands or self.compCase in self.commands:
self.outputLog('')
self.outputLog('Preparing directory for shadow GEOQ.')
# Now check if the VTK is written in the directory.
shadow = self.smiterCase.getShadow()
shadowName = shadow.getName()
shadowPath = os.path.join(shadowDir, f"{shadowName}.vtk")
if os.path.exists(shadowPath) and not rewriteMesh:
self.outputLog('Shadow mesh %s already exists.' %
shadowPath)
else:
self.outputLog('Writing shadow mesh to %s' % shadowPath)
self._t_writeVTK(shadowPath, shadow)
# Write CTL. This is performed ALWAYS, since the file is small and
# is changed the most.
self.outputLog('Writing CTL for shadow GEOQ.')
self._t_writeCTL(os.path.join(shadowDir, 'geoq.ctl'), shadow)
# 3. step. Check if HDSGEN needs to be run
if self.compHdsg in self.commands or self.compCase in self.commands:
self.outputLog('')
self.outputLog('Preparing directory for HDSGEN.')
hdsgen = self.smiterCase.getHDSGEN()
self.outputLog('Writing CTL for HDSGEN.')
self._t_writeCTL(os.path.join(hdsgenDir, 'hdsgen.ctl'), hdsgen)
# 4. step. Check if POWCAL needs to be run
if self.compPowc in self.commands or self.compCase in self.commands:
self.outputLog('')
powcal = self.smiterCase.getPOWCAL()
self.outputLog('Writing CTL for POWCAL.')
self._t_writeCTL(os.path.join(powcalDir, 'powcal.ctl'), powcal)
# Prepare commands
computeCommands = []
if self.compPsiRef in self.commands:
computeCommands.append((self.compPsiRef, 'wall/geoq'))
if self.compMag in self.commands:
computeCommands.append((self.compMag, 'mag/magtfm'))
if self.compCase in self.commands:
computeCommands.append((self.compCase,
'shadow/geoq target/geoq hds/hdsgen pow/powcal'))
else:
if self.compTarg in self.commands:
computeCommands.append((self.compTarg, 'target/geoq'))
if self.compShad in self.commands:
computeCommands.append((self.compShad, 'shadow/geoq'))
if self.compHdsg in self.commands:
computeCommands.append((self.compHdsg, 'hds/hdsgen'))
if self.compPowc in self.commands:
computeCommands.append((self.compPowc, 'pow/powcal'))
# Purge the :attr:`commands` list.
self.commands = []
self.runDir = runDirPath
self.computeCommands = computeCommands
self.preparationsFlag = True
return 0
def _t_cleanOutput(self, path):
"""Function used in the thread. Not to be used by the user, unless you
know what they do.
This function cleans the ``run`` directory of *.out, *.log, *.gnu, ...
Arguments:
path (str): Path, in which to clean the output files..
"""
# patterns = ["*.out", ".*log", "*.gnu", "*_geo*", "*_hds*", "*_pow*",
# "*.sp3", "*_bx.txt"]
patterns = ["mag*", "geoq*", "powcal*", "hdsgen*"]
files = []
for p in patterns:
files += glob(os.path.join(path, p))
for file in files:
os.remove(file)
def _t_writeVTK(self, path, object):
"""Function used in the thread. Not to be used by the user, unless you
know what they do.
This function writes a mesh in VTK format in the specified ``path``
directory.
Arguments:
path (str): Path where to save the mesh in VTK format.
object (SMITER_ORB__POA.GEOQ): Provided geoq object that holds
the function :func:`createVTK`, which reads the mesh object
it refers to and create a VTK file out of it.
"""
meshEntry = object.getMeshEntry()
sObj = salome.myStudy.FindObjectID(meshEntry)
from salome.smesh import smeshBuilder
sb = smeshBuilder.New()
meshObj = sObj.GetObject()
VTK = createVTKfromSMESH(meshObj, sObj.GetName(), writeEdges=False)
with open(path, 'w') as f:
f.write(VTK)
def _t_writeCTL(self, path, object):
"""Function used in the thread. Not to be used by the user, unless you
know what they do.
This function writes the CTL file of the provided object in the
provided ``path`` directory.
Arguments:
path (str): Path where to save the CTL file.
object : Either SMITER_ORB__POA.GEOQ, SMITER_ORB__POA.HDSGEN or
SMITER_ORB__POA.POWCAL object from which we extract the CTL
with the call of :func:`createCTL`
"""
CTL = object.createCTL()
with open(path, 'w') as f:
f.write(CTL)
def setCleanCase(self, bool):
self.clean = bool
[docs] def initialCheck(self):
"""Checks whether the computeLock is set and if there is a CORBA
instance of SMITER case.
"""
if self.computeLock:
self.outputLog.emit("Compute lock is set. A case is already "
"running!")
return False
if self.smiterCase is None:
self.outputLog.emit("No CORBA instance for SMITER case!")
return False
if self.smiterCase.getEQDSK() is None:
self.outputLog.emit("No EQDSK instance for SMITER case!")
return False
return True
def computeGEOQ(self):
if not self.initialCheck():
return
commands = ()
if self.smiterCase.getWall() is not None:
commands += (self.compPsiRef,)
if self.smiterCase.getTarget() is not None:
commands += (self.compTarg,)
else:
self.outputLog.emit("No target GEOQ instance in SMITER case!")
return
if self.smiterCase.getShadow() is not None:
commands += (self.compShad,)
else:
self.outputLog.emit("Not shadow GEOQ instance in SMITER case!")
return
self.computeLock = True
self.batchPrepare = False
self.commands = commands
self.start()
[docs] def computeHDSGEN(self):
"""Runs the case ONLY for HDSGEN. Means only the HDSGEN for the case
will be run.
Requirements:
* computeTarget
* computeShadow
"""
if not self.initialCheck():
return
commands = ()
if self.smiterCase.getHDSGEN() is not None:
commands = (self.compHdsg,)
else:
self.outputLog.emit("No HDSGEN instance in SMITER case!")
return
self.computeLock = True
self.batchPrepare = False
self.commands = commands
self.start()
[docs] def computePOWCAL(self):
"""Runs the case ONLY for POWCAL. Means only the POWCAL for the case
will be run.
Requirements:
* computeTarget
* computeShadow
* computeHdsgen
"""
if not self.initialCheck():
return
commands = ()
if self.smiterCase.getPOWCAL() is not None:
commands = (self.compPowc,)
else:
self.outputLog.emit("No POWCAL instance in SMITER case")
return
self.computeLock = True
self.batchPrepare = False
self.commands = commands
self.start()
[docs] def computeMAG(self):
"""Runs the magtfm module of SMARDDA.
"""
if not self.initialCheck():
return
commands = ()
if self.smiterCase.getMAGTFM() is not None:
commands = (self.compMag,)
else:
self.outputLog.emit("No MAGTFM instance in SMITER case")
return
self.computeLock = True
self.batchPrepare = False
self.commands = commands
self.start()
[docs] def compute(self):
"""Computes the whole case, starting with the GEOQ for wall, target and
shadow, then HDSGEN and finally POWCAL.
"""
if not self.initialCheck():
return
commands = ()
if self.smiterCase.getWall() is not None:
commands += (self.compPsiRef,)
if self.smiterCase.getMAGTFM() is not None:
commands = (self.compMag,)
if self.smiterCase.getTarget() is None:
self.outputLog.emit("No target GEOQ instance in SMITER case")
return
if self.smiterCase.getShadow() is None:
self.outputLog.emit("No shadow GEOQ instance in SMITER case")
return
if self.smiterCase.getHDSGEN() is None:
self.outputLog.emit("No HDSGEN instance in SMITER case")
return
if self.smiterCase.getPOWCAL() is None:
self.outputLog.emit("No POWCAl instance in SMITER case")
return
commands += (self.compCase,)
self.computeLock = True
self.batchPrepare = False
self.commands = commands
self.start()
def start(self):
# Prepare the case
notOk = self.prepareRunDirectory()
if notOk:
print('Run dir preparation failed!')
return
self.computeProcess.completionStatus = True
self.computeProcess.setSmiterDir(self.smiterDir)
self.computeProcess.setRunDir(self.runDir)
self.computeProcess.setComputeCommands(self.computeCommands)
self.outputLog('Checking for SMARDDA executables...')
ok = self.computeProcess.checkForSMARDDAexecutables()
if not ok:
self.outputLog('No SMARDDA executables, stopping '
' run!')
self.computeLock = False
return
self.outputLog('Now starting compute.')
self.computeProcess.compute()
self.outputLog('Compute finished.')
if self.saveToCase:
self.outputLog('Saving POWCAL result to case!')
# Name for POWCAL VTK result
import time
powcalName = self.smiterCase.getPOWCAL().getName()
caseName = self.smiterCase.getName()
name = caseName + '_' + time.strftime('%Y-%m-%d-%H-%M')
powcalDir = self.runDir + '/P/'
path = powcalDir + '/%s_powx.vtk' % powcalName
if not os.access(path, os.F_OK | os.R_OK):
self.outputLog('Files %s does not exist!' % path)
else:
with open(path, 'r') as f:
text = f.read()
ok = self.smiterCase.saveResult(name, text)
if ok:
self.outputLog('Saved POWCAL vtk results to case as '
'%s.' % name)
else:
self.outputLog('Failed to save vtk results to case!')
self.outputLog('Maybe there is a result with the '
'same name already saved.')
def getAvailableCases():
study = salome.myStudy
comp = SMITER_utils.findOrCreateComponent()
iter = study.NewChildIterator(comp)
cases = []
while iter.More():
name = iter.Value().GetName()
if name:
cases.append(name)
iter.Next()
return cases