patme 0.4.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of patme might be problematic. Click here for more details.
- patme/__init__.py +52 -0
- patme/buildtools/__init__.py +7 -0
- patme/buildtools/rce_releasecreator.py +336 -0
- patme/buildtools/release.py +26 -0
- patme/femtools/__init__.py +5 -0
- patme/femtools/abqmsgfilechecker.py +137 -0
- patme/femtools/fecall.py +1092 -0
- patme/geometry/__init__.py +0 -0
- patme/geometry/area.py +124 -0
- patme/geometry/coordinatesystem.py +635 -0
- patme/geometry/intersect.py +284 -0
- patme/geometry/line.py +183 -0
- patme/geometry/misc.py +420 -0
- patme/geometry/plane.py +464 -0
- patme/geometry/rotate.py +244 -0
- patme/geometry/scale.py +152 -0
- patme/geometry/shape2d.py +50 -0
- patme/geometry/transformations.py +1831 -0
- patme/geometry/translate.py +139 -0
- patme/mechanics/__init__.py +4 -0
- patme/mechanics/loads.py +435 -0
- patme/mechanics/material.py +1260 -0
- patme/service/__init__.py +7 -0
- patme/service/decorators.py +85 -0
- patme/service/duration.py +96 -0
- patme/service/exceptionhook.py +104 -0
- patme/service/exceptions.py +36 -0
- patme/service/io/__init__.py +3 -0
- patme/service/io/basewriter.py +122 -0
- patme/service/logger.py +375 -0
- patme/service/mathutils.py +108 -0
- patme/service/misc.py +71 -0
- patme/service/moveimports.py +217 -0
- patme/service/stringutils.py +419 -0
- patme/service/systemutils.py +290 -0
- patme/sshtools/__init__.py +3 -0
- patme/sshtools/cara.py +435 -0
- patme/sshtools/clustercaller.py +420 -0
- patme/sshtools/facluster.py +350 -0
- patme/sshtools/sshcall.py +168 -0
- patme-0.4.4.dist-info/LICENSE +21 -0
- patme-0.4.4.dist-info/LICENSES/MIT.txt +9 -0
- patme-0.4.4.dist-info/METADATA +168 -0
- patme-0.4.4.dist-info/RECORD +46 -0
- patme-0.4.4.dist-info/WHEEL +4 -0
- patme-0.4.4.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Created on 25.01.2017
|
|
7
|
+
|
|
8
|
+
@author: freu_se
|
|
9
|
+
"""
|
|
10
|
+
import getpass
|
|
11
|
+
import os
|
|
12
|
+
import re
|
|
13
|
+
import shutil
|
|
14
|
+
import subprocess
|
|
15
|
+
import tarfile
|
|
16
|
+
import zlib
|
|
17
|
+
from datetime import datetime
|
|
18
|
+
|
|
19
|
+
from patme.service.duration import Duration
|
|
20
|
+
from patme.service.logger import log
|
|
21
|
+
from patme.service.systemutils import dos2unix, tarGzDirectory
|
|
22
|
+
from patme.sshtools.cara import copyClusterFilesSCP, get_default_slurm_args, sshCluster, sshClusterJob
|
|
23
|
+
from patme.sshtools.sshcall import callSSH
|
|
24
|
+
|
|
25
|
+
duration = Duration()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ClusterCaller:
|
|
29
|
+
"""This class represents a general interface to call several fe and other functions on the cluster.
|
|
30
|
+
|
|
31
|
+
The remote jobs are performed by copying the files of the local input directory to the
|
|
32
|
+
cluster on "\\\\cluster.fa.bs.dlr.de\\<username>\\job\\<runDirName>".
|
|
33
|
+
Then the program creates an ssh connection to the cluster. More information about
|
|
34
|
+
the ssh connection can be found in service.utilities.callSSH.
|
|
35
|
+
After the completion of the job the result is copied back to the local runDir.
|
|
36
|
+
|
|
37
|
+
:param runDir: absolute or relative path to the folder where the fe run should be executed
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
REMOTE_SCRIPT = "run_sbatch.sh"
|
|
41
|
+
|
|
42
|
+
clusterFuncDict = {
|
|
43
|
+
"cara": {
|
|
44
|
+
"copyClusterFilesSCP": copyClusterFilesSCP,
|
|
45
|
+
"sshCluster": sshCluster,
|
|
46
|
+
"sshClusterJob": sshClusterJob,
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def __init__(self, runDir, **kwargs):
|
|
51
|
+
self.runDir = runDir
|
|
52
|
+
self.remoteBaseDir = None
|
|
53
|
+
"""Directory where files will be copied remotely. Defaults to solverName in runRemote
|
|
54
|
+
remoteRunDir = ~/remoteBaseDir/self.runDir[-1]"""
|
|
55
|
+
self.remoteCmds = None
|
|
56
|
+
self.solverName = None
|
|
57
|
+
self.preCommands = []
|
|
58
|
+
"""List of commands that are sent to the cluster prior to the remote command.
|
|
59
|
+
It is intended to setup the environment for the call that will be done
|
|
60
|
+
"""
|
|
61
|
+
self.ignorePatternsHostToLocal = {".svn"}
|
|
62
|
+
"""Files and folders that shall not copied from the cluster to the local machine on remote runs."""
|
|
63
|
+
|
|
64
|
+
self.reuseResults = False
|
|
65
|
+
"""If True, the resulting tar.gz file is also extracted on the remote machine.
|
|
66
|
+
This way, the result folder can be reused on a next remote call without copying inputs."""
|
|
67
|
+
|
|
68
|
+
self._clusterName = kwargs.pop("clusterName", "cara")
|
|
69
|
+
self.__checkClusterName(self._clusterName)
|
|
70
|
+
|
|
71
|
+
if "wsl" in self.clusterName:
|
|
72
|
+
self.remoteCmds = [
|
|
73
|
+
"bash",
|
|
74
|
+
"-i",
|
|
75
|
+
self.REMOTE_SCRIPT,
|
|
76
|
+
]
|
|
77
|
+
elif "cara" in self.clusterName:
|
|
78
|
+
self.remoteCmds = [
|
|
79
|
+
f"chmod a+x {self.REMOTE_SCRIPT} ; ",
|
|
80
|
+
"sbatch",
|
|
81
|
+
self.REMOTE_SCRIPT,
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
def _getClusterFunc(self, funcName):
|
|
85
|
+
"""doc"""
|
|
86
|
+
if self.clusterName not in self.clusterFuncDict:
|
|
87
|
+
raise Exception(f"Unknown cluster {self.clusterName}")
|
|
88
|
+
|
|
89
|
+
if funcName not in self.clusterFuncDict[self.clusterName]:
|
|
90
|
+
raise Exception(f"Unknown cluster func {funcName}")
|
|
91
|
+
|
|
92
|
+
return self.clusterFuncDict[self.clusterName][funcName]
|
|
93
|
+
|
|
94
|
+
def runRemote(self, copyFilesLocalToHost=True, jobName="job", **kwargs):
|
|
95
|
+
"""doc"""
|
|
96
|
+
log.info(f"call {self.solverName} remotely on '{self.clusterName}'")
|
|
97
|
+
|
|
98
|
+
self.addClusterSpecificBatchCmds()
|
|
99
|
+
|
|
100
|
+
remoteRunDir = kwargs.get("remoteRunDir", None)
|
|
101
|
+
if not remoteRunDir:
|
|
102
|
+
ws_dir_name, remoteRunDir = self.getRemoteRunDir(**kwargs)
|
|
103
|
+
|
|
104
|
+
# copy rundir to network folder
|
|
105
|
+
if copyFilesLocalToHost:
|
|
106
|
+
log.info(f"Copy files to remote machine '{self.clusterName}'")
|
|
107
|
+
with log.switchLevelTemp(log.WARN):
|
|
108
|
+
self._transferInputToCluster(remoteRunDir, **kwargs)
|
|
109
|
+
|
|
110
|
+
# Replace <jobName> two times since it used two times in the command list
|
|
111
|
+
remoteCmds = [re.sub("<jobName>", jobName, elem) for elem in self.remoteCmds]
|
|
112
|
+
|
|
113
|
+
# change to run dir of fe call
|
|
114
|
+
remoteCmdsJoin = " ".join(remoteCmds)
|
|
115
|
+
if "wsl" not in self.clusterName:
|
|
116
|
+
command = f"cd {remoteRunDir};{remoteCmdsJoin}"
|
|
117
|
+
else:
|
|
118
|
+
command = remoteCmdsJoin
|
|
119
|
+
|
|
120
|
+
if self.preCommands:
|
|
121
|
+
precmd = ";".join(self.preCommands)
|
|
122
|
+
command = f"{precmd};{command}"
|
|
123
|
+
|
|
124
|
+
log.debug(f'Call "{self.solverName}" with the following command:')
|
|
125
|
+
log.debug(f"{command}", longMesageDelim=";")
|
|
126
|
+
|
|
127
|
+
if "cara" in self.clusterName:
|
|
128
|
+
# =======================================================================
|
|
129
|
+
# run remote
|
|
130
|
+
# =======================================================================
|
|
131
|
+
if self.clusterName not in self.clusterFuncDict:
|
|
132
|
+
raise Exception(f"Unknown cluster {self.clusterName}")
|
|
133
|
+
|
|
134
|
+
sshClusterFunc = self._getClusterFunc("sshClusterJob")
|
|
135
|
+
|
|
136
|
+
jobId = sshClusterFunc(command, printOutput=False, **kwargs)
|
|
137
|
+
else:
|
|
138
|
+
|
|
139
|
+
jobId = "WSL_NOJOBID"
|
|
140
|
+
command += " > cluster.r00.log"
|
|
141
|
+
remoteRunDirAsWinPath = self.__getWSLRemoteDirAsWinPath(remoteRunDir)
|
|
142
|
+
wsl_cmd = f"wsl --cd {remoteRunDirAsWinPath} {command}"
|
|
143
|
+
p = subprocess.run(wsl_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
144
|
+
|
|
145
|
+
log.debug(f"Transfer files from remote to local working dir")
|
|
146
|
+
with log.switchLevelTemp(log.WARN):
|
|
147
|
+
self._transferFromCluster(remoteRunDir, jobId, **kwargs)
|
|
148
|
+
|
|
149
|
+
self.cleanRemoteDir(ws_dir_name, remoteRunDir, **kwargs)
|
|
150
|
+
|
|
151
|
+
log.info(f"Remote call {self.solverName} with jobId {str(jobId)} done")
|
|
152
|
+
|
|
153
|
+
def cleanRemoteDir(self, ws_name, remoteRunDir, **kwargs):
|
|
154
|
+
"""Clean scratch directory and release scratch"""
|
|
155
|
+
if self.clusterName == "cara":
|
|
156
|
+
|
|
157
|
+
from patme.sshtools.cara import _getClusterAuthentication
|
|
158
|
+
|
|
159
|
+
hostname, hostKeyString, privateKey = _getClusterAuthentication()
|
|
160
|
+
username = kwargs.get("username", getpass.getuser())
|
|
161
|
+
cmd = f"rm -rf {remoteRunDir}/*;ws_release {ws_name}"
|
|
162
|
+
_ = callSSH(hostname, cmd, privateKey, hostKeyString=hostKeyString, username=username, printOutput=False)
|
|
163
|
+
|
|
164
|
+
elif "wsl" in self.clusterName:
|
|
165
|
+
|
|
166
|
+
shutil.rmtree(self.__getWSLRemoteDirAsWinPath(remoteRunDir))
|
|
167
|
+
|
|
168
|
+
def getRemoteRunDir(self, **kwargs):
|
|
169
|
+
"""doc"""
|
|
170
|
+
if self.clusterName == "cara":
|
|
171
|
+
|
|
172
|
+
from patme.sshtools.cara import _getClusterAuthentication
|
|
173
|
+
|
|
174
|
+
hostname, hostKeyString, privateKey = _getClusterAuthentication()
|
|
175
|
+
username = kwargs.get("username", getpass.getuser())
|
|
176
|
+
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
177
|
+
ws_dir_name = f"run_{timestamp}"
|
|
178
|
+
cmd = f"ws_allocate {ws_dir_name}"
|
|
179
|
+
log.info("Allocate workspace: " + ws_dir_name)
|
|
180
|
+
with log.switchLevelTemp(log.WARN):
|
|
181
|
+
scratch_dir = callSSH(
|
|
182
|
+
hostname, cmd, privateKey, hostKeyString=hostKeyString, username=username, printOutput=False
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
remoteRunDir = scratch_dir.strip()
|
|
186
|
+
|
|
187
|
+
elif "wsl" in self.clusterName:
|
|
188
|
+
|
|
189
|
+
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
190
|
+
ws_dir_name = f"run_{timestamp}"
|
|
191
|
+
remoteRunDir = f"~/tmp/{ws_dir_name}"
|
|
192
|
+
os.makedirs(self.__getWSLRemoteDirAsWinPath(remoteRunDir))
|
|
193
|
+
|
|
194
|
+
else:
|
|
195
|
+
raise Exception(f"Cluster with name {self.clusterName} not supported!")
|
|
196
|
+
|
|
197
|
+
return ws_dir_name, remoteRunDir
|
|
198
|
+
|
|
199
|
+
def _transferInputToCluster(self, remoteRunDir, **kwargs):
|
|
200
|
+
"""Transfer the input to the cluster by performing 4 steps.
|
|
201
|
+
|
|
202
|
+
1. tar.gz the whole input directory
|
|
203
|
+
2. transfer this tarfile to the cluster via sftp
|
|
204
|
+
3. extract the file on the cluster
|
|
205
|
+
4. remove the tarfiles on both ends
|
|
206
|
+
"""
|
|
207
|
+
log.info(f"Copy files to remote machine: {remoteRunDir}")
|
|
208
|
+
tarFileName = "clusterInput.tar.gz"
|
|
209
|
+
tarFileNameFull = tarGzDirectory(self.runDir, tarFileName)
|
|
210
|
+
|
|
211
|
+
if "cara" in self.clusterName:
|
|
212
|
+
username = kwargs.get("username", getpass.getuser())
|
|
213
|
+
if self.clusterName not in self.clusterFuncDict:
|
|
214
|
+
raise Exception(f"Unknown cluster {self.clusterName}")
|
|
215
|
+
|
|
216
|
+
clusterFuncCopy = self._getClusterFunc("copyClusterFilesSCP")
|
|
217
|
+
sshClusterFunc = self._getClusterFunc("sshCluster")
|
|
218
|
+
|
|
219
|
+
clusterFuncCopy(
|
|
220
|
+
[tarFileName], srcBaseDir=self.runDir, destBaseDir=remoteRunDir, mode="put", username=username
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
# unzip files at cluster and remove zip files on both sides
|
|
224
|
+
extract = [f"cd {remoteRunDir}", f"tar -xf {tarFileName}", f"rm {tarFileName}"]
|
|
225
|
+
|
|
226
|
+
sshClusterFunc(";".join(extract), printOutput=False, username=username)
|
|
227
|
+
|
|
228
|
+
elif "wsl" in self.clusterName:
|
|
229
|
+
|
|
230
|
+
remoteRunDirAsWinPath = self.__getWSLRemoteDirAsWinPath(remoteRunDir)
|
|
231
|
+
shutil.copy(tarFileNameFull, remoteRunDirAsWinPath)
|
|
232
|
+
|
|
233
|
+
cmd = f"wsl --cd {remoteRunDir} tar -xf {tarFileName} -C .;rm {tarFileName}"
|
|
234
|
+
subprocess.run(cmd, shell=True)
|
|
235
|
+
|
|
236
|
+
else:
|
|
237
|
+
raise NotImplementedError(f"Unknown cluster name or wsl: {self.clusterName}")
|
|
238
|
+
|
|
239
|
+
os.remove(os.path.join(self.runDir, tarFileName))
|
|
240
|
+
|
|
241
|
+
log.debug(f"Copy files to remote machine '{self.clusterName}' done")
|
|
242
|
+
|
|
243
|
+
def __getWSLRemoteDirAsWinPath(self, remoteDir):
|
|
244
|
+
"""doc"""
|
|
245
|
+
p = subprocess.run(["wsl", "wslpath", "-w", remoteDir], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
246
|
+
return p.stdout.decode().strip()
|
|
247
|
+
|
|
248
|
+
def _transferFromCluster(self, remoteRunDir, jobId, **kwargs):
|
|
249
|
+
"""Transfer the calculation result from the cluster by performing these steps.
|
|
250
|
+
|
|
251
|
+
1. copy the result tar.gz file to self.runDir
|
|
252
|
+
2. extract the file locally
|
|
253
|
+
3. extract tar file remotely if the remote folder should be reused
|
|
254
|
+
4. remove the tarfile locally
|
|
255
|
+
4.1 optionally extract tarfile remotely to reuse the calculation results
|
|
256
|
+
5. remove the tarfile remote"""
|
|
257
|
+
|
|
258
|
+
def getFileAndExtract(tarFileName, tarFileNamePath, clusterLog, remoteRunDir, copyFunc, username=None):
|
|
259
|
+
"""doc"""
|
|
260
|
+
for ffile in [tarFileName, clusterLog]:
|
|
261
|
+
copyFunc([ffile], remoteRunDir, self.runDir, "get", username=username)
|
|
262
|
+
|
|
263
|
+
with tarfile.open(tarFileNamePath) as f:
|
|
264
|
+
f.extractall(self.runDir, filter="data")
|
|
265
|
+
|
|
266
|
+
if "wsl" in self.clusterName:
|
|
267
|
+
|
|
268
|
+
remoteRunDirAsWinPath = self.__getWSLRemoteDirAsWinPath(remoteRunDir)
|
|
269
|
+
dir_creation_time = os.path.getctime(remoteRunDirAsWinPath)
|
|
270
|
+
for dirpath, _, filenames in os.walk(remoteRunDirAsWinPath):
|
|
271
|
+
for filename in filenames:
|
|
272
|
+
|
|
273
|
+
filepath = os.path.join(dirpath, filename)
|
|
274
|
+
try:
|
|
275
|
+
file_mtime = os.path.getmtime(filepath)
|
|
276
|
+
# Compare the file's modification time with the directory's creation time
|
|
277
|
+
if file_mtime > dir_creation_time:
|
|
278
|
+
rel_dir = os.path.relpath(dirpath, remoteRunDirAsWinPath)
|
|
279
|
+
dirInRunDir = os.path.join(self.runDir, rel_dir)
|
|
280
|
+
os.makedirs(dirInRunDir, exist_ok=True)
|
|
281
|
+
shutil.copy(filepath, dirInRunDir)
|
|
282
|
+
|
|
283
|
+
except FileNotFoundError:
|
|
284
|
+
# Skip files that might disappear during walk
|
|
285
|
+
continue
|
|
286
|
+
|
|
287
|
+
else:
|
|
288
|
+
username = kwargs.get("username", getpass.getuser())
|
|
289
|
+
copyFunc = self._getClusterFunc("copyClusterFilesSCP")
|
|
290
|
+
sshClusterFunc = self._getClusterFunc("sshCluster")
|
|
291
|
+
|
|
292
|
+
try:
|
|
293
|
+
log.info("copy result from cluster")
|
|
294
|
+
prefix = f"cluster.r{jobId}"
|
|
295
|
+
tarFileName = f"{prefix}.tar.gz"
|
|
296
|
+
clusterLog = f"{prefix}.log"
|
|
297
|
+
tarFileNamePath = os.path.join(self.runDir, tarFileName)
|
|
298
|
+
|
|
299
|
+
try:
|
|
300
|
+
getFileAndExtract(
|
|
301
|
+
tarFileName, tarFileNamePath, clusterLog, remoteRunDir, copyFunc, username=username
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
except tarfile.ReadError:
|
|
305
|
+
msg = "Could not open the result tar file. "
|
|
306
|
+
msg += "Probably the calculation was cancelled."
|
|
307
|
+
log.error(msg)
|
|
308
|
+
return # retruning to make a local calculation possible
|
|
309
|
+
|
|
310
|
+
except zlib.error:
|
|
311
|
+
msg = "Got error while extracting result file. "
|
|
312
|
+
msg += "Try again to copy and extract"
|
|
313
|
+
log.error(msg)
|
|
314
|
+
try:
|
|
315
|
+
getFileAndExtract(tarFileName, tarFileNamePath, clusterLog, remoteRunDir)
|
|
316
|
+
except tarfile.ReadError:
|
|
317
|
+
msg = "Could not open the result tar file. "
|
|
318
|
+
msg += "Probably the calculation was cancelled."
|
|
319
|
+
log.error(msg)
|
|
320
|
+
return # retruning to make a local calculation possible
|
|
321
|
+
|
|
322
|
+
os.remove(tarFileNamePath)
|
|
323
|
+
|
|
324
|
+
cleanupCommand = f"cd {remoteRunDir}"
|
|
325
|
+
if self.reuseResults:
|
|
326
|
+
cleanupCommand += f";tar -xf {tarFileName}"
|
|
327
|
+
|
|
328
|
+
cleanupCommand += f";rm {tarFileName}"
|
|
329
|
+
|
|
330
|
+
sshClusterFunc(cleanupCommand, printOutput=False, username=username)
|
|
331
|
+
log.debug("copy result from cluster done")
|
|
332
|
+
|
|
333
|
+
except OSError as exception:
|
|
334
|
+
|
|
335
|
+
msg = "Retrieved IOError when copying results from remote computer. "
|
|
336
|
+
msg += "Maybe some items are not copied properly. "
|
|
337
|
+
msg += "See debug.log for more details."
|
|
338
|
+
|
|
339
|
+
log.warning(msg)
|
|
340
|
+
log.debug("error message to the above warning: " + str(exception))
|
|
341
|
+
|
|
342
|
+
def addClusterSpecificBatchCmds(self, *args, **kwargs):
|
|
343
|
+
"""Create bash cmds which for remote sbatch call"""
|
|
344
|
+
runScriptCmds = ["#!/bin/bash"]
|
|
345
|
+
if self.clusterName == "cara":
|
|
346
|
+
|
|
347
|
+
slurm_args = get_default_slurm_args()
|
|
348
|
+
cara_partion = os.environ.get("CARA_PARTITION", slurm_args["partition"])
|
|
349
|
+
slurm_args["partition"] = cara_partion
|
|
350
|
+
if cara_partion == "ppp":
|
|
351
|
+
slurm_args["ntasks"] = "1"
|
|
352
|
+
|
|
353
|
+
for sarg, sval in slurm_args.items():
|
|
354
|
+
cmd = f"#SBATCH --{sarg}"
|
|
355
|
+
cmd += "" if not sval else f"={sval}"
|
|
356
|
+
runScriptCmds.append(cmd)
|
|
357
|
+
|
|
358
|
+
runScriptCmds += [
|
|
359
|
+
". /usr/share/lmod/lmod/init/sh",
|
|
360
|
+
". /etc/profile.d/10-dlr-modulepath.sh",
|
|
361
|
+
"module --force purge",
|
|
362
|
+
]
|
|
363
|
+
|
|
364
|
+
runScriptCmds += [
|
|
365
|
+
'curtime=$(date +"%Y-%m-%d %H:%M:%S")',
|
|
366
|
+
# find can only distinguish between timestamps which have seconds as highest precision
|
|
367
|
+
"sleep 1s",
|
|
368
|
+
'tarFile="cluster.r$SLURM_JOB_ID.tar.gz"',
|
|
369
|
+
]
|
|
370
|
+
runScriptCmds += self.generateSolverSpecificRemoteCmds()
|
|
371
|
+
runScriptCmds += [
|
|
372
|
+
'tar -czf $tarFile -C . $(find . -newermt "$curtime" -type f)',
|
|
373
|
+
]
|
|
374
|
+
|
|
375
|
+
runScriptFile = os.path.join(self.runDir, self.REMOTE_SCRIPT)
|
|
376
|
+
with open(runScriptFile, "w") as f:
|
|
377
|
+
f.write("\n".join(runScriptCmds))
|
|
378
|
+
|
|
379
|
+
dos2unix(runScriptFile)
|
|
380
|
+
|
|
381
|
+
def __checkClusterName(self, cname):
|
|
382
|
+
if not re.search("cara|wsl", cname):
|
|
383
|
+
raise NotImplementedError(f"No remote caller implemented for cluster '{cname}'")
|
|
384
|
+
|
|
385
|
+
def _getClusterName(self):
|
|
386
|
+
return self._clusterName
|
|
387
|
+
|
|
388
|
+
def _setClusterName(self, cname):
|
|
389
|
+
self.__checkClusterName(cname)
|
|
390
|
+
self._clusterName = cname
|
|
391
|
+
|
|
392
|
+
clusterName = property(fget=_getClusterName, fset=_setClusterName)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
class PythonModuleCaller(ClusterCaller):
|
|
396
|
+
"""This class handles calling target functions like those in buckling.bucklingtargetfunction on the cluster"""
|
|
397
|
+
|
|
398
|
+
def __init__(self, runDir, jobCommands):
|
|
399
|
+
"""
|
|
400
|
+
:param jobCommands: list with strings defining the command to call a python script excluding the leading python executable
|
|
401
|
+
"""
|
|
402
|
+
ClusterCaller.__init__(self, runDir)
|
|
403
|
+
self.solverName = "python35"
|
|
404
|
+
clusterCmds = ["py35", "-d", "-O", "tgz", "-J", "<jobName>"]
|
|
405
|
+
self.remoteCmds = clusterCmds + jobCommands
|
|
406
|
+
self.preCommands = [". ${HOME}/.profile;echo PYTHONPATH:${PYTHONPATH}"]
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
class MatlabCaller(ClusterCaller):
|
|
410
|
+
"""This class handles calling target functions like those in buckling.bucklingtargetfunction on the cluster"""
|
|
411
|
+
|
|
412
|
+
solverName = "matlab"
|
|
413
|
+
|
|
414
|
+
def __init__(self, runDir, jobCommands):
|
|
415
|
+
"""
|
|
416
|
+
:param jobCommands: list with strings defining the command to call a matlab script excluding the leading matlabe executable
|
|
417
|
+
"""
|
|
418
|
+
ClusterCaller.__init__(self, runDir)
|
|
419
|
+
clusterCmds = ["mat2013a", "-d", "-O", "tgz", "-J", "<jobName>", "--", "-r"]
|
|
420
|
+
self.remoteCmds = clusterCmds + jobCommands
|