From 6f6c96c26a4416b6ad1a025622e284d5fc79d8e4 Mon Sep 17 00:00:00 2001
From: "Kenneth C. Kleissl"
Date: Thu, 17 Jan 2019 21:07:13 +0100
Subject: [PATCH] Fixed shear flow for zero N and M, incorporated version
check, validity check of geometry thickness, wall length and clockwise def.
---
Analysis.py | 7 +--
MyMainWindow.py => AppWindows.py | 86 ++++++++++++++++++++++++--------
Geometry.py | 14 ++++++
convert_ui.bat | 1 +
design.py | 46 ++++++++++-------
design.ui | 57 ++++++++++++++-------
main.py | 4 +-
7 files changed, 150 insertions(+), 65 deletions(-)
rename MyMainWindow.py => AppWindows.py (92%)
diff --git a/Analysis.py b/Analysis.py
index d8bf4f2..188f546 100644
--- a/Analysis.py
+++ b/Analysis.py
@@ -421,12 +421,13 @@ def dualSection(section, SF, Mat):
dx = 0.001 # [m] Offset
SF2 = SectionForces.SectionForces(SF.N, SF.Mx + dx * SF.Vy, SF.My - dx * SF.Vx)
# SF2 = prep_dual_section(SF, dx) # nabouring SF
-
+
# --------------- Optimize plane strain variables for the secondary section ---------------
opt2 = nlopt.opt(nlopt.LN_NELDERMEAD, len(x))
opt2.set_min_objective(lambda x, grad: errorFunBending(x, section, SF2, Mat))
opt2.set_xtol_rel(1e-8)
- x2 = opt2.optimize(x)
+ x0 = [0 if abs(x)<1e-6 else x for x in x0] # the initial guess may not contain extremely small values such as 3e-169
+ x2 = opt2.optimize(x0)
print("Optimized strain state2 =", x2)
print("Minimized error2 value = ", opt.last_optimum_value())
@@ -434,7 +435,7 @@ def dualSection(section, SF, Mat):
_, dist = BendingEQ(section, Mat, x[0], x[1], x[2]) # get distributions from first section
_, dist2 = BendingEQ(section, Mat, x2[0], x2[1], x2[2]) # get distributions from first section
H = shear_flow(dist, dist2, SF, section, dx)
-
+
# --------------- SLS verification ---------------
# Disk stress components
theta, sigma_c, sigma_sx, sigma_sy = [], [], [], []
diff --git a/MyMainWindow.py b/AppWindows.py
similarity index 92%
rename from MyMainWindow.py
rename to AppWindows.py
index b6982f3..f53daf2 100644
--- a/MyMainWindow.py
+++ b/AppWindows.py
@@ -1,8 +1,6 @@
# -*- coding: utf-8 -*-
"""
-MainWindow class for the "Hollow section analysis tool" GUI
-
-Script defining the MainWindow class including functions for any interactive element
+This module containes all the application window classes for the "Hollow section analysis tool" GUI
History log:
Version 0.1 - first working build based on UI from Qt Designer
@@ -25,15 +23,19 @@
import Material
import Results
import Geometry
-#import TableInterface
import pickle
+#import TableInterface
-class MyMainWindow(QtWidgets.QMainWindow, design.Ui_MainWindow): # PyQt5 compatible
+class HollowRCWindow(QtWidgets.QMainWindow, design.Ui_MainWindow): # PyQt5 compatible
def __init__(self):
super().__init__() # initialize the QMainWindow parent object from the Qt Designer file
self.setupUi(self) # setup layout and widgets defined in design.py by Qt Designer
#self.geometry_table = TableInterface.MyTable(self.coordinates_tableWidget)
+ # version tag and label
+ self.tag = 'v1.1'
+ self.label_version.setText(self.tag)
+
# --- Triggers --- (interactive elements such as actions and buttons with a custom function)
self.exitAct.triggered.connect(self.exit_app)
self.saveAct.triggered.connect(self.save_file)
@@ -83,6 +85,11 @@ def __init__(self):
viewStatusAct.setChecked(True)
viewStatusAct.triggered.connect(self.toggle_menu)
viewMenu.addAction(viewStatusAct)
+
+ aboutMenu = self.menuBar().addMenu('About')
+ aboutVersionAct = QtWidgets.QAction('Check version', self)
+ aboutVersionAct.triggered.connect(self.version_check)
+ aboutMenu.addAction(aboutVersionAct)
# Correcting QT Designer bug sometimes making table headers invisible
self.coordinates_tableWidget.horizontalHeader().setVisible(True) # show horizontal header in Geometry table
@@ -100,6 +107,9 @@ def __init__(self):
# make sure to start at first tab (overrules Qt designer)
self.tabWidget.setCurrentIndex(0)
+ # check if version is up-to-date
+ # self.version_check()
+
def tab_changed(self): # signal function
if self.checkBox_analSLS_1.isChecked():
self.pushButton_analyse.setText('Analyse SLS')
@@ -127,10 +137,6 @@ def refresh_plots(self): # signal/normal function
except:
None
- def not_yet_implemented_popup(self):
- msg_string = 'This feature has not yet men implemented'
- self.show_msg_box(msg_string)
-
def save_file(self):
try: # try to save file
openfile = QtWidgets.QFileDialog.getSaveFileName(filter='*.pkj') # save file dialog
@@ -167,21 +173,24 @@ def load_file(self):
print(e)
self.show_msg_box('Failed to open file')
- def show_msg_box(self, info_str):
+ def show_msg_box(self, msg_str, title="Error Message", set_load_fac_label=False):
msg = QtWidgets.QMessageBox()
msg.setIcon(QtWidgets.QMessageBox.Information)
- msg.setWindowTitle("Error Message")
- if isinstance(info_str, str):
- msg.setText(info_str)
- self.load_fac_label.setText(info_str)
- elif isinstance(info_str, list):
- msg.setText(info_str[0])
- print(info_str)
- self.load_fac_label.setText(info_str[0])
- if len(info_str) > 1:
- msg.setInformativeText(info_str[1])
- self.load_fac_label.setText(info_str[0]+' '+info_str[1])
+ msg.setWindowTitle(title)
+ if isinstance(msg_str, str):
+ msg.setText(msg_str)
+ if set_load_fac_label:
+ self.load_fac_label.setText(msg_str)
+ elif isinstance(msg_str, list): # if a list
+ msg.setText(msg_str[0]) # set text in msg box
+ print(msg_str)
+ if set_load_fac_label:
+ self.load_fac_label.setText(msg_str[0]) # update label
+ if len(msg_str) > 1:
+ msg.setInformativeText(msg_str[1]) # set info text
+ if set_load_fac_label:
+ self.load_fac_label.setText(msg_str[0] + ' ' + msg_str[1])
# msg.setDetailedText("The details are as follows: ")
msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
@@ -202,6 +211,13 @@ def initiate_analysis(self):
SF = self.getSF()
Mat = self.getMaterial()
+ # check if geometry is valid
+ if not section.valid():
+ self.show_msg_box(['Geometry error', 'The defined geometry is not valid'])
+ self.Res = None
+ self.refresh_plots()
+ return
+
# print(Geometry)
print('SF: ' + SF.print_str())
@@ -224,7 +240,7 @@ def initiate_analysis(self):
# Show message
if error_msg:
- self.show_msg_box(error_msg)
+ self.show_msg_box(error_msg, set_load_fac_label=True)
else:
self.load_fac_label.setText('No load-factor currently applied')
@@ -809,6 +825,32 @@ def closeEvent(self, event): # reimplementing the QWidget closeEvent() event ha
else:
event.ignore()
+ def version_check(self):
+ # This method retreivings the latest release version from GitHub
+ import requests
+ r = requests.get('https://api.github.com/repos/Kleissl/HollowRC/releases/latest')
+ # print(r)
+ if r.status_code == 200:
+ # print(r.headers['content-type'])
+ data = r.json()
+ # print(data.keys())
+ # for key in data:
+ # print(key, 'corresponds to', data[key])
+ latest_tag = data['tag_name']
+ published = data['published_at']
+ print('The latest release (' + latest_tag +') was published at ' + published)
+ if latest_tag == self.tag:
+ print('version up-to-date')
+ msg_str = 'version up-to-date'
+ msg_info_str = 'The current version ('+ self.tag +') matches the latest release'
+ else:
+ msg_str = 'The application ('+ self.tag +') is NOT up-to-date!'
+ msg_info_str = 'There is a newer release (' + latest_tag + ') from ' + published + ' available for download at https://github.com/Kleissl/HollowRC/releases/latest'
+ print(msg_str)
+ self.show_msg_box([msg_str, msg_info_str], title='Information')
+ else:
+ print('Github API requests returned statuscode', r.status_code)
+
# # Creating my own GraphicsScene class so I can overwrite its mousePressEvent
# class MyGraphicsScene(QtWidgets.QGraphicsScene):
# def __init__(self, parent=None):
diff --git a/Geometry.py b/Geometry.py
index 7c038ba..1bc4c67 100644
--- a/Geometry.py
+++ b/Geometry.py
@@ -133,6 +133,20 @@ def get_e(self, local_data=False):
else:
return e
+ def valid(self):
+ for T in self.get_thick():
+ if T <= 0:
+ print('Negative or zero wall thickness!')
+ return False
+ for L in self.get_wallLength():
+ if L <= 0:
+ print('Negative or zero wall length!')
+ return False
+ if self.get_enclosed_area() > 0: # note that the correct clockwise definition yields a negative enclosed area
+ print('Counter-clockwise definition of cross-section!')
+ return False
+ return True
+
# Second Moment of Area
#Ix.append(wallLength[i]*T[i]/12 * ( wallLength[i]**2 * math.cos(wallAngle[i])**2 + T[i]**2 * math.sin(wallAngle[i])**2 ))
#Ix.append(wallLength[i] * T[i] / 12 * (
diff --git a/convert_ui.bat b/convert_ui.bat
index 40ecd8a..6997680 100644
--- a/convert_ui.bat
+++ b/convert_ui.bat
@@ -1,4 +1,5 @@
"C:\Users\Kenneth\Anaconda3\Library\bin\pyside2-uic.bat" -x design.ui -o design.py
"C:\Users\kekl\Anaconda3\Library\bin\pyside2-uic.bat" -x design.ui -o design.py
"C:\Program Files (x86)\Python37-32\Scripts\pyside2-uic.exe" -x design.ui -o design.py
+"C:\Users\kekl\AppData\Local\Programs\Python\Python37-32\Scripts\pyside2-uic.exe" -x design.ui -o design.py
pause
diff --git a/design.py b/design.py
index 73df284..30db39d 100644
--- a/design.py
+++ b/design.py
@@ -3,7 +3,7 @@
# Form implementation generated from reading ui file 'design.ui',
# licensing of 'design.ui' applies.
#
-# Created: Tue Nov 6 21:55:00 2018
+# Created: Thu Jan 17 20:10:14 2019
# by: pyside2-uic running on PySide2 5.11.2
#
# WARNING! All changes made in this file will be lost!
@@ -74,7 +74,7 @@ def setupUi(self, MainWindow):
self.label_31.setWordWrap(True)
self.label_31.setObjectName("label_31")
self.label_33 = QtWidgets.QLabel(self.tab)
- self.label_33.setGeometry(QtCore.QRect(10, 10, 751, 31))
+ self.label_33.setGeometry(QtCore.QRect(10, 10, 521, 31))
font = QtGui.QFont()
font.setPointSize(12)
font.setWeight(75)
@@ -99,6 +99,13 @@ def setupUi(self, MainWindow):
self.label_38 = QtWidgets.QLabel(self.tab)
self.label_38.setGeometry(QtCore.QRect(930, 450, 111, 101))
self.label_38.setObjectName("label_38")
+ self.label_version = QtWidgets.QLabel(self.tab)
+ self.label_version.setGeometry(QtCore.QRect(20, 630, 61, 31))
+ font = QtGui.QFont()
+ font.setPointSize(9)
+ font.setItalic(True)
+ self.label_version.setFont(font)
+ self.label_version.setObjectName("label_version")
self.tabWidget.addTab(self.tab, "")
self.tab_geometry = QtWidgets.QWidget()
self.tab_geometry.setObjectName("tab_geometry")
@@ -731,6 +738,7 @@ def retranslateUi(self, MainWindow):
self.label_36.setText(QtWidgets.QApplication.translate("MainWindow", "
", None, -1))
self.label_37.setText(QtWidgets.QApplication.translate("MainWindow", "", None, -1))
self.label_38.setText(QtWidgets.QApplication.translate("MainWindow", "", None, -1))
+ self.label_version.setText(QtWidgets.QApplication.translate("MainWindow", "v1.0", None, -1))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QtWidgets.QApplication.translate("MainWindow", "About", None, -1))
self.label.setText(QtWidgets.QApplication.translate("MainWindow", "Define starting coordinates and properties of each wall element here:", None, -1))
self.coordinates_tableWidget.setSortingEnabled(False)
@@ -746,24 +754,24 @@ def retranslateUi(self, MainWindow):
__sortingEnabled = self.coordinates_tableWidget.isSortingEnabled()
self.coordinates_tableWidget.setSortingEnabled(False)
self.coordinates_tableWidget.item(0, 0).setText(QtWidgets.QApplication.translate("MainWindow", "0", None, -1))
- self.coordinates_tableWidget.item(0, 1).setText(QtWidgets.QApplication.translate("MainWindow", "2250", None, -1))
- self.coordinates_tableWidget.item(0, 2).setText(QtWidgets.QApplication.translate("MainWindow", "400", None, -1))
- self.coordinates_tableWidget.item(0, 3).setText(QtWidgets.QApplication.translate("MainWindow", "0.013", None, -1))
+ self.coordinates_tableWidget.item(0, 1).setText(QtWidgets.QApplication.translate("MainWindow", "2000", None, -1))
+ self.coordinates_tableWidget.item(0, 2).setText(QtWidgets.QApplication.translate("MainWindow", "300", None, -1))
+ self.coordinates_tableWidget.item(0, 3).setText(QtWidgets.QApplication.translate("MainWindow", "0.01", None, -1))
self.coordinates_tableWidget.item(0, 4).setText(QtWidgets.QApplication.translate("MainWindow", "0.01", None, -1))
- self.coordinates_tableWidget.item(1, 0).setText(QtWidgets.QApplication.translate("MainWindow", "4000", None, -1))
- self.coordinates_tableWidget.item(1, 1).setText(QtWidgets.QApplication.translate("MainWindow", "2250", None, -1))
- self.coordinates_tableWidget.item(1, 2).setText(QtWidgets.QApplication.translate("MainWindow", "400", None, -1))
- self.coordinates_tableWidget.item(1, 3).setText(QtWidgets.QApplication.translate("MainWindow", "0.013", None, -1))
+ self.coordinates_tableWidget.item(1, 0).setText(QtWidgets.QApplication.translate("MainWindow", "1500", None, -1))
+ self.coordinates_tableWidget.item(1, 1).setText(QtWidgets.QApplication.translate("MainWindow", "2000", None, -1))
+ self.coordinates_tableWidget.item(1, 2).setText(QtWidgets.QApplication.translate("MainWindow", "200", None, -1))
+ self.coordinates_tableWidget.item(1, 3).setText(QtWidgets.QApplication.translate("MainWindow", "0.01", None, -1))
self.coordinates_tableWidget.item(1, 4).setText(QtWidgets.QApplication.translate("MainWindow", "0.01", None, -1))
- self.coordinates_tableWidget.item(2, 0).setText(QtWidgets.QApplication.translate("MainWindow", "4000", None, -1))
+ self.coordinates_tableWidget.item(2, 0).setText(QtWidgets.QApplication.translate("MainWindow", "1500", None, -1))
self.coordinates_tableWidget.item(2, 1).setText(QtWidgets.QApplication.translate("MainWindow", "0", None, -1))
- self.coordinates_tableWidget.item(2, 2).setText(QtWidgets.QApplication.translate("MainWindow", "400", None, -1))
- self.coordinates_tableWidget.item(2, 3).setText(QtWidgets.QApplication.translate("MainWindow", "0.013", None, -1))
+ self.coordinates_tableWidget.item(2, 2).setText(QtWidgets.QApplication.translate("MainWindow", "300", None, -1))
+ self.coordinates_tableWidget.item(2, 3).setText(QtWidgets.QApplication.translate("MainWindow", "0.01", None, -1))
self.coordinates_tableWidget.item(2, 4).setText(QtWidgets.QApplication.translate("MainWindow", "0.01", None, -1))
self.coordinates_tableWidget.item(3, 0).setText(QtWidgets.QApplication.translate("MainWindow", "0", None, -1))
self.coordinates_tableWidget.item(3, 1).setText(QtWidgets.QApplication.translate("MainWindow", "0", None, -1))
- self.coordinates_tableWidget.item(3, 2).setText(QtWidgets.QApplication.translate("MainWindow", "400", None, -1))
- self.coordinates_tableWidget.item(3, 3).setText(QtWidgets.QApplication.translate("MainWindow", "0.013", None, -1))
+ self.coordinates_tableWidget.item(3, 2).setText(QtWidgets.QApplication.translate("MainWindow", "200", None, -1))
+ self.coordinates_tableWidget.item(3, 3).setText(QtWidgets.QApplication.translate("MainWindow", "0.01", None, -1))
self.coordinates_tableWidget.item(3, 4).setText(QtWidgets.QApplication.translate("MainWindow", "0.01", None, -1))
self.coordinates_tableWidget.setSortingEnabled(__sortingEnabled)
self.addRowButton.setToolTip(QtWidgets.QApplication.translate("MainWindow", "Insert new row at the bottom", None, -1))
@@ -820,11 +828,11 @@ def retranslateUi(self, MainWindow):
self.SectionForces_tableWidget.horizontalHeaderItem(5).setText(QtWidgets.QApplication.translate("MainWindow", "T [kNm]", None, -1))
__sortingEnabled = self.SectionForces_tableWidget.isSortingEnabled()
self.SectionForces_tableWidget.setSortingEnabled(False)
- self.SectionForces_tableWidget.item(0, 0).setText(QtWidgets.QApplication.translate("MainWindow", "-38000", None, -1))
- self.SectionForces_tableWidget.item(0, 1).setText(QtWidgets.QApplication.translate("MainWindow", "0", None, -1))
- self.SectionForces_tableWidget.item(0, 2).setText(QtWidgets.QApplication.translate("MainWindow", "50000", None, -1))
- self.SectionForces_tableWidget.item(0, 3).setText(QtWidgets.QApplication.translate("MainWindow", "5000", None, -1))
- self.SectionForces_tableWidget.item(0, 4).setText(QtWidgets.QApplication.translate("MainWindow", "0", None, -1))
+ self.SectionForces_tableWidget.item(0, 0).setText(QtWidgets.QApplication.translate("MainWindow", "-15000", None, -1))
+ self.SectionForces_tableWidget.item(0, 1).setText(QtWidgets.QApplication.translate("MainWindow", "20000", None, -1))
+ self.SectionForces_tableWidget.item(0, 2).setText(QtWidgets.QApplication.translate("MainWindow", "0", None, -1))
+ self.SectionForces_tableWidget.item(0, 3).setText(QtWidgets.QApplication.translate("MainWindow", "0", None, -1))
+ self.SectionForces_tableWidget.item(0, 4).setText(QtWidgets.QApplication.translate("MainWindow", "5000", None, -1))
self.SectionForces_tableWidget.item(0, 5).setText(QtWidgets.QApplication.translate("MainWindow", "0", None, -1))
self.SectionForces_tableWidget.setSortingEnabled(__sortingEnabled)
self.load_fac_label.setText(QtWidgets.QApplication.translate("MainWindow", "No load-factor currently applied", None, -1))
diff --git a/design.ui b/design.ui
index 5cd5af0..078c814 100644
--- a/design.ui
+++ b/design.ui
@@ -23,7 +23,7 @@
-
- 2
+ 0
@@ -168,7 +168,7 @@
10
10
- 751
+ 521
31
@@ -243,6 +243,25 @@
<html><head/><body><p><img src=":/Figures/moment_sign_convention.PNG"/></p></body></html>
+
+
+
+ 20
+ 630
+ 61
+ 31
+
+
+
+
+ 9
+ true
+
+
+
+ v1.0
+
+
@@ -401,17 +420,17 @@
-
- 2250
+ 2000
-
- 400
+ 300
-
- 0.013
+ 0.01
-
@@ -421,22 +440,22 @@
-
- 4000
+ 1500
-
- 2250
+ 2000
-
- 400
+ 200
-
- 0.013
+ 0.01
-
@@ -446,7 +465,7 @@
-
- 4000
+ 1500
-
@@ -456,12 +475,12 @@
-
- 400
+ 300
-
- 0.013
+ 0.01
-
@@ -481,12 +500,12 @@
-
- 400
+ 200
-
- 0.013
+ 0.01
-
@@ -1289,27 +1308,27 @@
-
- -38000
+ -15000
-
- 0
+ 20000
-
- 50000
+ 0
-
- 5000
+ 0
-
- 0
+ 5000
-
diff --git a/main.py b/main.py
index c0046a3..f4d2c7f 100644
--- a/main.py
+++ b/main.py
@@ -16,7 +16,7 @@
# Third-party library modules
from PySide2 import QtWidgets
# Local source tree modules
-from MyMainWindow import MyMainWindow # import the MainWindow class
+from AppWindows import HollowRCWindow # import the MainWindow class
def main():
@@ -24,7 +24,7 @@ def main():
app = QtWidgets.QApplication(sys.argv) # PyQT5 compatible
# The QWidget widget is the base class of all user interface objects in PyQt4.
- window = MyMainWindow() # We set the form to be our ExampleApp (design)
+ window = HollowRCWindow() # We set the form to be our ExampleApp (design)
window.show() # Show the window/form
# Exception handling