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.

Files changed (46) hide show
  1. patme/__init__.py +52 -0
  2. patme/buildtools/__init__.py +7 -0
  3. patme/buildtools/rce_releasecreator.py +336 -0
  4. patme/buildtools/release.py +26 -0
  5. patme/femtools/__init__.py +5 -0
  6. patme/femtools/abqmsgfilechecker.py +137 -0
  7. patme/femtools/fecall.py +1092 -0
  8. patme/geometry/__init__.py +0 -0
  9. patme/geometry/area.py +124 -0
  10. patme/geometry/coordinatesystem.py +635 -0
  11. patme/geometry/intersect.py +284 -0
  12. patme/geometry/line.py +183 -0
  13. patme/geometry/misc.py +420 -0
  14. patme/geometry/plane.py +464 -0
  15. patme/geometry/rotate.py +244 -0
  16. patme/geometry/scale.py +152 -0
  17. patme/geometry/shape2d.py +50 -0
  18. patme/geometry/transformations.py +1831 -0
  19. patme/geometry/translate.py +139 -0
  20. patme/mechanics/__init__.py +4 -0
  21. patme/mechanics/loads.py +435 -0
  22. patme/mechanics/material.py +1260 -0
  23. patme/service/__init__.py +7 -0
  24. patme/service/decorators.py +85 -0
  25. patme/service/duration.py +96 -0
  26. patme/service/exceptionhook.py +104 -0
  27. patme/service/exceptions.py +36 -0
  28. patme/service/io/__init__.py +3 -0
  29. patme/service/io/basewriter.py +122 -0
  30. patme/service/logger.py +375 -0
  31. patme/service/mathutils.py +108 -0
  32. patme/service/misc.py +71 -0
  33. patme/service/moveimports.py +217 -0
  34. patme/service/stringutils.py +419 -0
  35. patme/service/systemutils.py +290 -0
  36. patme/sshtools/__init__.py +3 -0
  37. patme/sshtools/cara.py +435 -0
  38. patme/sshtools/clustercaller.py +420 -0
  39. patme/sshtools/facluster.py +350 -0
  40. patme/sshtools/sshcall.py +168 -0
  41. patme-0.4.4.dist-info/LICENSE +21 -0
  42. patme-0.4.4.dist-info/LICENSES/MIT.txt +9 -0
  43. patme-0.4.4.dist-info/METADATA +168 -0
  44. patme-0.4.4.dist-info/RECORD +46 -0
  45. patme-0.4.4.dist-info/WHEEL +4 -0
  46. patme-0.4.4.dist-info/entry_points.txt +3 -0
patme/__init__.py ADDED
@@ -0,0 +1,52 @@
1
+ # Copyright (C) 2020 Deutsches Zentrum fuer Luft- und Raumfahrt(DLR, German Aerospace Center) <www.dlr.de>
2
+ # SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
3
+ #
4
+ # SPDX-License-Identifier: MIT
5
+
6
+ """
7
+ Utilities for software builds, documentation, cluster interaction, calling fem tools, logging, exceptions and simple geometric and mechanical operations.
8
+
9
+ """
10
+ from pathlib import Path
11
+
12
+ import importlib_metadata
13
+ import tomlkit
14
+
15
+ name = Path(__file__).parent.name
16
+
17
+
18
+ def getPyprojectMeta(initPath):
19
+ """Returns project data from pyproject.toml
20
+
21
+ :param initPath: path to the packages main __init__.py file
22
+ :return: dict with entries from tool.poetry in pyproject.toml
23
+ """
24
+ with open(Path(Path(initPath).parents[2], "pyproject.toml")) as pyproject:
25
+ file_contents = pyproject.read()
26
+
27
+ contents_dict = tomlkit.parse(file_contents)
28
+ try:
29
+ return contents_dict["project"]
30
+ except:
31
+ return contents_dict["tool"]["poetry"]
32
+
33
+
34
+ try:
35
+ # package is installed
36
+ version = importlib_metadata.version(name)
37
+ programDir = str(Path(__file__).parent)
38
+ except importlib_metadata.PackageNotFoundError:
39
+ # package is not installed, read pyproject.toml
40
+ try:
41
+ # We have the full GitLab repository
42
+ pkgMeta = getPyprojectMeta(__file__)
43
+ version = str(pkgMeta["version"])
44
+ programDir = str(Path(__file__).parents[3])
45
+ except FileNotFoundError:
46
+ # We have only the source code
47
+ version = str("version not provided")
48
+ programDir = str(Path(__file__).parent)
49
+
50
+
51
+ # Variables
52
+ epsilon = 1e-8
@@ -0,0 +1,7 @@
1
+ # SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """
6
+ The modules of this package support the build and deployment of python packages.
7
+ """
@@ -0,0 +1,336 @@
1
+ # Copyright (C) 2013 Deutsches Zentrum fuer Luft- und Raumfahrt(DLR, German Aerospace Center) <www.dlr.de>
2
+ # SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
3
+ #
4
+ # SPDX-License-Identifier: MIT
5
+
6
+ """Create RCE components and publish them on an rce toolserver.
7
+
8
+ This script is meant for the deployment of tools in various versions and configuration variants.
9
+ To create all inputs to the main function, one must create one tool configuration using the rce- "integrate tool" wizard first.
10
+ Then, extract all neccessary information (toolInput, toolOutput, preScript, postScript, runCmd) from the configuration file.
11
+
12
+ Perform the following
13
+
14
+ - Create documentation pdf
15
+ - Clone the respective git tag
16
+ - Create the RCE-Component:
17
+ - Create the configuration folder, file and documentation
18
+ - Upload configuration to the toolserver (using file shares)
19
+ - Publish the component in RCE to "public"
20
+
21
+ Prerequisites and restrictions:
22
+
23
+ - The RCE-toolserver must be accessible via ssh
24
+ - The Configuration (in the rc-profile dir) of the RCE-toolserver must be accessible via file share
25
+ - Only "common" components creatable - no "cpacs" components
26
+ - In the folder "toolDirToolserver" (parameter of releaseCreatorMain), there should be a subdirectory called "programName"
27
+ for the nightly version. This folder must be created by the user when createNightly=True.
28
+ In "toolDirToolserver", tag folders will be created using "versionString" as folder name.
29
+ """
30
+
31
+ import os
32
+ import shutil
33
+ import subprocess
34
+ import sys
35
+
36
+ from patme.buildtools.release import hasTag
37
+ from patme.service.exceptions import ImproperParameterError
38
+ from patme.service.logger import log
39
+ from patme.sshtools.sshcall import callSSH
40
+
41
+
42
+ def releaseCreatorMain(
43
+ # program settings
44
+ versionString,
45
+ programDir,
46
+ programName,
47
+ gitRepo,
48
+ iconPath,
49
+ description,
50
+ # rce tool settings
51
+ runCmd,
52
+ preScript,
53
+ postScript,
54
+ rceInputs,
55
+ rceOutputs,
56
+ toolProperties,
57
+ # doc settings
58
+ docCommand,
59
+ docResultPdfPath,
60
+ # remote settings
61
+ username,
62
+ privateKeyFile,
63
+ hostnameRce10,
64
+ hostKeyStringRce10,
65
+ portRce10,
66
+ toolDirToolserver,
67
+ toolDirToolserverRemote,
68
+ configDirToolserver,
69
+ # run behavior
70
+ createDoc=True,
71
+ cloneTag=True,
72
+ createRceConfig=True,
73
+ createNightly=False,
74
+ ):
75
+ """Main function for creating the whole configuration
76
+
77
+ :param versionString: version
78
+ :param programDir: directory of the local program
79
+ :param programName: name of the program
80
+ :param gitRepo: https address of git repository
81
+ :param icoPath: name and path (relative to programDir) to the programs icon. May be None
82
+ :param description: description of the program
83
+
84
+ :param runCmd: command to run the tool on the rce toolserver
85
+ :param preScript: pre command on rce toolserver
86
+ :param postScript: post command on rce toolserver
87
+ :param rceInputs: inputs of the rce component
88
+ :param rceOutputs: outputs of the rce component
89
+ :param toolProperties: string, section toolProperties in rce configuration
90
+
91
+ :param docCommand: setup.py command to create doc
92
+ :param docResultPdfPath: name and path (relative to programDir) with the created pdf file. If None, no documentation will be included.
93
+
94
+ :param username: username to login to rce using ssh
95
+ :param privateKeyFile: path to the private key for ssh access
96
+ :param hostnameRce10: hostname of the computer running the toolserver
97
+ :param hostKeyStringRce10: ssh host key for authentication
98
+ :param portRce10: port of the rce server
99
+ :param toolDirToolserver: local path to tool on toolserver.
100
+ :param toolDirToolserverRemote: remote path to tool on toolserver
101
+ :param configDirToolserver: tool directory on toolserver (local path to remote machine)
102
+
103
+ :param createDoc: flag if the documentation should be created. Otherwise, the documentaion must be created manually.
104
+ :param cloneTag: flag if the tag folder should be created. Otherwise the folder must be created manually.
105
+ :param createRceConfig: flag if the rce configuration folder/file should be created
106
+ :param createNightly: flag if the nightly configuration should be created. Has only effect, if createRceConfig=True
107
+ """
108
+ if not hasTag(versionString, programDir):
109
+ raise ImproperParameterError(f'There is no tag "{versionString}" in {programName} in folder {programDir}')
110
+
111
+ connectInfo = (username, privateKeyFile, hostnameRce10, hostKeyStringRce10, portRce10)
112
+ rceInfo = description, runCmd, preScript, postScript, rceInputs, rceOutputs, docResultPdfPath, toolProperties
113
+
114
+ # ===============================================================================================
115
+ # create documentation
116
+ # ===============================================================================================
117
+ if createDoc:
118
+ log.infoHeadline("Making documentation")
119
+ subprocess.call([sys.executable, "setup.py", docCommand], cwd=programDir)
120
+
121
+ # ===========================================================================
122
+ # create a clone of the tag on the toolserver
123
+ # ===========================================================================
124
+ tagPath = os.path.join(toolDirToolserverRemote, versionString)
125
+ if cloneTag:
126
+ if os.path.exists(tagPath):
127
+ log.info(f"Not performing git clone: tag already exists at: {tagPath}")
128
+ else:
129
+ os.makedirs(tagPath)
130
+ gitBin = shutil.which("git")
131
+ cloneCmd = [gitBin, "clone", "--depth", "1", "--branch", versionString, gitRepo, tagPath]
132
+ subprocess.run(cloneCmd, stdout=sys.stdout)
133
+
134
+ # ===========================================================================
135
+ # rce tool configuration
136
+ # ===========================================================================
137
+ if createRceConfig:
138
+ createToolConfigurations(
139
+ toolDirToolserver,
140
+ versionString,
141
+ programName,
142
+ programDir,
143
+ connectInfo,
144
+ configDirToolserver,
145
+ iconPath,
146
+ rceInfo,
147
+ createNightly,
148
+ )
149
+
150
+
151
+ def createToolConfigurations(
152
+ toolDirToolserver,
153
+ versionString,
154
+ programName,
155
+ programDir,
156
+ connectInfo,
157
+ configDirToolserver,
158
+ iconPath,
159
+ rceInfo,
160
+ createNightly,
161
+ rceVersion="rce10",
162
+ ):
163
+ """Creates the configuration files for RCE"""
164
+ if rceVersion == "rce10":
165
+ createToolConfiguration = createRCE10ToolConfiguration
166
+ else:
167
+ raise Exception(f'RCE version "{rceVersion}" not supported')
168
+
169
+ toolDir = os.path.join(toolDirToolserver, versionString).replace(
170
+ "\\", "\\\\"
171
+ ) # using 4backslashes since it is parsed by python 2 times
172
+ createToolConfiguration(
173
+ versionString, programName, programDir, toolDir, connectInfo, configDirToolserver, iconPath, rceInfo
174
+ )
175
+
176
+ if createNightly:
177
+ toolDir = os.path.join(toolDirToolserver, programName).replace("\\", "\\\\")
178
+ createToolConfiguration(
179
+ "nightly", programName, programDir, toolDir, connectInfo, configDirToolserver, iconPath, rceInfo
180
+ )
181
+
182
+
183
+ def createRCE10ToolConfiguration(
184
+ versionString, programName, programDir, toolDir, connectInfo, configDirToolserver, iconPath, rceInfo
185
+ ):
186
+ """Create the RCE8 configuration folder and all necessary files"""
187
+
188
+ username, privateKeyFile, hostnameRce10, hostKeyStringRce10, portRce10 = connectInfo
189
+ # create configuration dir
190
+ versionName = programName + "_" + versionString # e.g. results in str: DELiS_14.7.2
191
+ rceConfigToolserver = os.path.join(configDirToolserver, versionName)
192
+ log.info(f"Create rce tool configurations in folder {rceConfigToolserver}")
193
+ if not os.path.exists(os.path.join(rceConfigToolserver, "docs")):
194
+ os.makedirs(os.path.join(rceConfigToolserver, "docs"))
195
+
196
+ # ===========================================================================
197
+ # create conf dir, write conf
198
+ # ===========================================================================
199
+ docResultPdfPath = rceInfo[-2]
200
+ if docResultPdfPath is not None:
201
+ docFile = os.path.join(programDir, docResultPdfPath)
202
+ if os.path.exists(docFile):
203
+ shutil.copy2(docFile, os.path.join(rceConfigToolserver, "docs"))
204
+ else:
205
+ log.warning("The documentation pdf is not existing: " + docFile)
206
+ docResultPdfPath = ""
207
+ else:
208
+ docResultPdfPath = ""
209
+ shutil.copy2(os.path.join(programDir, iconPath), rceConfigToolserver)
210
+ # write Config
211
+ configString = getRCE10ConfigString(versionName, versionString, toolDir, os.path.basename(iconPath), rceInfo)
212
+ with open(rceConfigToolserver + "/configuration.json", "w") as f:
213
+ f.write(configString)
214
+
215
+ # ===========================================================================
216
+ # publish RCE component
217
+ # ===========================================================================
218
+ log.info(f"publish RCE component {versionName}")
219
+ remoteCommand = f"components set-auth common/{versionName} public"
220
+ output = callSSH(hostnameRce10, remoteCommand, privateKeyFile, username, hostKeyStringRce10, port=portRce10)
221
+ if not "Set access authorization for component id" in output:
222
+ log.error("Publish component failed")
223
+
224
+
225
+ def getRCE10ConfigString(versionName, versionString, toolDir, iconFilename, rceInfo):
226
+ description, runCmd, preScript, postScript, rceInputs, rceOutputs, docResultPdfPath, toolProperties = rceInfo
227
+
228
+ return (
229
+ '''{
230
+ "commandScriptLinux" : "",
231
+ "commandScriptWindows" : "'''
232
+ + runCmd
233
+ + '''",
234
+ "copyToolBehavior" : "never",
235
+ "deleteWorkingDirectoriesNever" : true,
236
+ "documentationFilePath" : "'''
237
+ + os.path.basename(docResultPdfPath)
238
+ + """",
239
+ "enableCommandScriptWindows" : true,
240
+ "groupName" : "DLR-FA",
241
+ "iconHash" : "bbca83a88b19e9c05524ec3f5df1553b",
242
+ "iconModified" : 1482484234043,
243
+ "imitationScript" : "",
244
+ "imitationToolOutputFilename" : "",
245
+ "inputs" : [ """
246
+ + rceInputs
247
+ + """ ],
248
+ "isActive" : true,
249
+ "launchSettings" : [ {
250
+ "limitInstallationInstancesNumber" : "10",
251
+ "limitInstallationInstances" : "true",
252
+ "rootWorkingDirectory" : "D:\\\\DELiS_tools\\\\tmp\\\\"""
253
+ + versionName
254
+ + '''",
255
+ "host" : "RCE",
256
+ "toolDirectory" : "'''
257
+ + toolDir
258
+ + '''",
259
+ "version" : "'''
260
+ + versionString
261
+ + """"
262
+ } ],
263
+ "outputs" : [ """
264
+ + rceOutputs
265
+ + ''' ],
266
+ "postScript" : "'''
267
+ + postScript
268
+ + '''",
269
+ "preScript" : "'''
270
+ + preScript
271
+ + '''",
272
+ "toolDescription" : "'''
273
+ + description
274
+ + '''",
275
+ "toolIconPath" : "'''
276
+ + iconFilename
277
+ + '''",
278
+ "toolIntegrationVersion" : 1,
279
+ "toolIntegratorE-Mail" : "sebastian.freund@dlr.de",
280
+ "toolIntegratorName" : "Sebastian Freund",
281
+ "toolName" : "'''
282
+ + versionName
283
+ + """",
284
+ "toolProperties" : {"""
285
+ + toolProperties
286
+ + """},
287
+ "uploadIcon" : true,
288
+ "useIterationDirectories" : true
289
+ }"""
290
+ )
291
+
292
+
293
+ if __name__ == "__main__":
294
+ from patme import name, programDir, version
295
+
296
+ iconPath = "doc/icon.png"
297
+ rceRunCommand = 'rem setting paths \\r\\nD:\\\\DELiS_tools\\\\delis_3rd_party\\\\64\\\\delis_vars.bat \\r\\nC:\\\\Miniconda3\\\\envs\\\\py36\\\\python.exe src\\\\delis\\\\main\\\\aircraftmain.py --configFile=\\"${in:optionalConfigFileName}\\"'
298
+
299
+ username = "default"
300
+ password = "default"
301
+ hostnameRce10 = "fa-jenkins2.intra.dlr.de"
302
+ portRce10 = 31008
303
+ hostKeyStringRce10 = "AAAAB3NzaC1yc2EAAAADAQABAAABAQCI1DvxZ3gC9437WjXebxZ5HOjru51ur0OlTgHAbHiPpIue\ng0F231NpRs/4Q8TvhkJpepb83EfE2xMyaZNIW6vf8BoKB+Jz7VEi609pI5aNzLdnrRCPXXUIdcLv\neMOvS1vez+KREp+5rLbvPvUfFwkOk0jvT95aFFgFnqoLu/zxIEvKN7TIR9z1S1Gy98Y7h4UHHYrV\nn156nvbnU2sMhwH7Lzl7zGbn+nYPki5oFXxloSJiwHbjPIYGqKGp0tzuV8bCmJUTt9q9SknCi3jY\n40TlXl25vRjjF7oLuIaFFWcYPSBp0nSgkJyGK3Cc3zv1hkztrZ19yzD8a6tDCZFzV+ht"
304
+
305
+ docCommand = "doc_latex"
306
+ docResultPdfPath = f"build/sphinx/latex/{name}.pdf"
307
+
308
+ toolDirToolserver = "D:\\DELiS_tools\\DELiS_git"
309
+ configDirToolserver = (
310
+ "\\\\fa-jenkins2\\DELiS_tools\\RCE\\Profiles\\RCE10_stm_toolserver\\integration\\tools\\common"
311
+ )
312
+ # configDirToolserver = 'C:\\RCE\\Profiles\\RCE10_client\\integration\\tools\\common'
313
+
314
+ toolDirToolserverRemote = "\\\\fa-jenkins2\\DELiS_tools\\DELiS_git"
315
+
316
+ releaseCreatorMain(
317
+ version,
318
+ programDir,
319
+ name,
320
+ "https://gitlab.dlr.de/fa_sw/patme.git",
321
+ iconPath,
322
+ "description",
323
+ rceRunCommand,
324
+ # doc settings
325
+ docCommand,
326
+ docResultPdfPath,
327
+ # remote settings
328
+ username,
329
+ password,
330
+ hostnameRce10,
331
+ hostKeyStringRce10,
332
+ portRce10,
333
+ toolDirToolserver,
334
+ toolDirToolserverRemote,
335
+ configDirToolserver,
336
+ )
@@ -0,0 +1,26 @@
1
+ # SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """
6
+ Provides functions for release automation
7
+ """
8
+
9
+ import subprocess
10
+
11
+ from patme.service.logger import log
12
+
13
+
14
+ def hasTag(tagName, runDir="."):
15
+ """Returns True if tagName is a tag in the loacal git"""
16
+ output = subprocess.check_output(["git", "tag", "-l"], encoding="utf_8", cwd=runDir)
17
+ return tagName in output
18
+
19
+
20
+ def gitTagAndPush(tagName):
21
+ """create and push git tag"""
22
+ if hasTag(tagName):
23
+ log.error(f"Tag {tagName} already exists")
24
+ return
25
+ subprocess.call(["git", "tag", tagName])
26
+ subprocess.call(["git", "push", "--tags"])
@@ -0,0 +1,5 @@
1
+ # SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """support for FEM tools"""
@@ -0,0 +1,137 @@
1
+ # SPDX-FileCopyrightText: 2022 German Aerospace Center (DLR)
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """Checks for the abaqus message file"""
6
+
7
+ from patme.service.logger import log
8
+
9
+
10
+ def getElementsWithLargestResForces(msgString):
11
+ """Check Abq message file for largest residual force
12
+
13
+ ABAQUS prints information to the msg-file which could be useful to identify the reasons
14
+ for divergence. One kind of information is at which node of which instance the highes
15
+ residual force occurs per iteration. The script extracts all nodes (and their instances)
16
+ which are at least once the nodes with the highest residual force. The result is plotted
17
+ to a txt-file of the form:
18
+
19
+ Input Example:
20
+
21
+ .. code-block:: none
22
+
23
+ <Instance_Name 2>
24
+ <Node nr 1>, <node nr 2>, ...
25
+ <Instance_Name 2>
26
+ <Node nr 1>, <node nr 2>, ...
27
+
28
+ :param msgString: string of the message file
29
+ :return: string, overview about elements with largest residual forces
30
+ """
31
+ lines = msgString.split("\n")
32
+
33
+ elementList = list(list())
34
+ instanceList = list()
35
+
36
+ lineNo = -1
37
+ for line in lines:
38
+ lineNo = lineNo + 1
39
+ if "LARGEST RESIDUAL FORCE" in line:
40
+ words = line.split()
41
+ element = list()
42
+ element.append(int(words[6]))
43
+
44
+ nextLine = lines[lineNo + 1]
45
+ words = nextLine.split()
46
+ instanceName = words[1]
47
+
48
+ if instanceName in instanceList:
49
+ index = instanceList.index(instanceName)
50
+ if element[0] not in elementList[index]:
51
+ elementList[index].append(element[0])
52
+ else:
53
+ instanceList.append(instanceName)
54
+ elementList.append(element)
55
+
56
+ outString = ""
57
+ for instanceName in instanceList:
58
+ outString += instanceName + "\n"
59
+ index = instanceList.index(instanceName)
60
+ outString += "\n".join(["%s, " % item for item in elementList[index]] + [""])
61
+ log.info("Elements with largest residual force:\n" + outString)
62
+ return outString
63
+
64
+
65
+ def getOverconstrainedNodes(msgString):
66
+ """ "Check abq message file for overconstrained nodes
67
+
68
+ ABAQUS prints information to the msg-file which could be useful to identify the reasons
69
+ for divergence. Sometimes overconstraints exists in the model (nodes are constrains by
70
+ too many constraints). These overconstraints are identified by PIVOT messages. This scripts
71
+ extracts all nodes (and the instances they belong to) for which pivots are idendified.
72
+
73
+ Input Example:
74
+
75
+ .. code-block:: none
76
+
77
+ ***WARNING: SOLVER PROBLEM. ZERO PIVOT WHEN PROCESSING A (TIED) CONTACT
78
+ CONSTRAINT D.O.F. 1 FOR SLAVE NODE 3288 INSTANCE MANDREL1_LAYER_9.
79
+ THIS MAY BE DUE TO THE UNIT USED FOR THE DISPLACEMENT DIFFERS BY
80
+ MORE THAN 10 ORDER OF MAGNITUDE THAN THE UNIT USED FOR THE
81
+ MATERIAL STIFFNESS. IF THIS IS THE CASE, PLEASE USE A DIFFERENT
82
+ UNIT SYSTEM.
83
+
84
+ :param msgString: string of the message file
85
+ :return: string, overview about overconstraint nodes
86
+ """
87
+
88
+ lines = msgString.split("\n")
89
+
90
+ nodeList = list(list())
91
+ instanceList = list()
92
+
93
+ lineNo = -1
94
+ for line in lines:
95
+ lineNo = lineNo + 1
96
+ if "PIVOT" in line:
97
+ nextLine = lines[lineNo + 1]
98
+ if "D.O.F." in nextLine and "NODE" in nextLine and "INSTANCE" in nextLine:
99
+ words = nextLine.split()
100
+ node = words[6]
101
+ try: # instance name mentioned in next line; maybe too long for current line --> take first word of next line
102
+ instanceName = words[8]
103
+ except IndexError:
104
+ overNextLine = lines[lineNo + 2]
105
+ overNextWords = overNextLine.split()
106
+ instanceName = overNextWords[0]
107
+
108
+ if instanceName in instanceList:
109
+ index = instanceList.index(instanceName)
110
+ if node not in nodeList[index]:
111
+ nodeList[index].append(node)
112
+ else:
113
+ instanceList.append(instanceName)
114
+ nodeList.append([node])
115
+
116
+ outString = ""
117
+ # nodes and their instances are written to the given file
118
+ for instanceName in instanceList:
119
+ outString += instanceName + "\n"
120
+ index = instanceList.index(instanceName)
121
+ outString += "\n".join(["%s, " % item for item in nodeList[index]] + [""])
122
+ log.info("Overconstrained nodes:\n" + outString)
123
+ return outString
124
+
125
+
126
+ if __name__ == "__main__":
127
+ # please provide name of abaqus message file
128
+ filename = "Job_NGT-BIT-small_Solid3D_C3D8R_noDamage_TiedContact.msg"
129
+ with open(filename) as f:
130
+ msgString = f.read()
131
+ getElementsWithLargestResForces(msgString)
132
+
133
+ # please provide name of abaqus message file
134
+ filename = "Job_NGT-BIT-small_Solid3D_C3D8R_noDamage_TiedContact.msg"
135
+ with open(filename) as f:
136
+ msgString = f.read()
137
+ getOverconstrainedNodes(msgString)