├── README.md ├── LICENSE ├── .gitignore ├── making_list_with_floats.py ├── Analysis_2D_Combined_V2.py ├── 2D_backend_analysis.py └── Analysis_3D_Combined_V2.py /README.md: -------------------------------------------------------------------------------- 1 | # UIUC-3D-LEM-Analysis 2 | Python analysis scripts using limit equilibrium method (LEM) for 2D and 3D slope stability analysis 3 | 4 | This repository deals with the back-end process (analysis and functions) of the software 5 | 6 | The GUI repository is at the following link: https://github.com/swha0901/3D-LEM-GUI 7 | 8 | Following Python3 libraries are required: 9 | 10 | - Pykrige v1.4.0 (link: https://github.com/bsmurphy/PyKrige) 11 | 12 | - Scipy v1.1.0 13 | 14 | - Numpy v1.15.0 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Enok Cheon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /making_list_with_floats.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue May 1 2018 4 | 5 | Completed on Tue May 1 2018 6 | 7 | @author: Enok C. 8 | 9 | making list with floats 10 | """ 11 | ''' 12 | def txt2numInList(listName): 13 | totalRow = len(listName) 14 | ''' 15 | 16 | def csv2txtlistSlide3(fileName): 17 | import csv 18 | with open(fileName, 'r') as f: 19 | reader = csv.reader(f) 20 | csvListTxt = list(reader) 21 | 22 | csvList = [] 23 | tempList = [] 24 | for idR in range(len(csvListTxt)): 25 | csvListTxt[idR] = [x for x in csvListTxt[idR] if x != ''] 26 | 27 | for i in range(len(csvListTxt[idR])): 28 | if csvListTxt[idR][i] == '': 29 | continue 30 | 31 | elif i==0 and (idR==0 or idR%22 ==0): 32 | indList = list(csvListTxt[idR][i]) 33 | blankInx = indList.index(' ') 34 | columnID = ''.join(csvListTxt[idR][i][(blankInx+1):]) 35 | tempList.append(int(columnID)) 36 | 37 | elif i!=0 and csvListTxt[idR][i].find(',') == -1: 38 | tempList.append(float(csvListTxt[idR][i])) 39 | 40 | elif i!=0 and csvListTxt[idR][i].find(',') != -1: 41 | commaIdx = csvListTxt[idR][i].index(',') 42 | tempList.append(float(csvListTxt[idR][i][0:commaIdx])) 43 | tempList.append(float(csvListTxt[idR][i][(commaIdx+2):])) 44 | 45 | if idR!=0 and len(tempList)==22: 46 | csvList.append(tempList) 47 | tempList = [] 48 | 49 | return csvList 50 | 51 | def csv2list(fileName): 52 | import csv 53 | with open(fileName, 'r') as f: 54 | reader = csv.reader(f) 55 | csvListTxt = list(reader) 56 | 57 | csvListNum = [] 58 | for idR in range(len(csvListTxt)): 59 | csvListTxt[idR] = [x for x in csvListTxt[idR] if x != ''] 60 | tempList = [float(i) for i in csvListTxt[idR]] 61 | csvListNum.append(tempList) 62 | 63 | return csvListNum 64 | 65 | def making_float_list(startNum, endNum, spacing): 66 | result = [] 67 | length = 1 + abs(startNum - endNum)/abs(spacing) 68 | for i in range(int(length)): 69 | x = startNum + spacing*i 70 | result.append(float(x)) 71 | return result 72 | 73 | def concatenate_lists(parentList, addingList): 74 | result = parentList[:] 75 | for i in range(len(addingList)): 76 | result.append(float(addingList[i])) 77 | return result 78 | 79 | def listAtColNum(listName,colNum): 80 | result = [] 81 | for i in range(len(listName)): 82 | result.append(float(listName[i][colNum])) 83 | return result 84 | 85 | def listAtColNumTxt(listName,colNum): 86 | result = [] 87 | for i in range(len(listName)): 88 | result.append(listName[i][colNum]) 89 | return result 90 | 91 | def arrayAtColNum(arrayName,colNum): 92 | import numpy as np 93 | result = [] 94 | for i in range(len(arrayName)): 95 | result.append(float(arrayName[i][colNum])) 96 | result = np.array(result) 97 | return result 98 | 99 | # csv_file = filename of csv exported from list 100 | # csv_column = column titles 101 | # data_list = list data 102 | def exportList2CSV(csv_file,data_list,csv_columns=None): 103 | # export files 104 | import csv 105 | 106 | with open(csv_file, 'w',newline='') as csvfile: 107 | writer = csv.writer(csvfile, delimiter=',') 108 | if csv_columns != None: 109 | writer.writerow(csv_columns) 110 | for data in data_list: 111 | writer.writerow(data) 112 | 113 | #example of exportList2CSV function input files 114 | #csv_columns = ['Row','Name','Country'] 115 | #csv_data_list = [['1', 'Alex', 'India'], ['2', 'Ben', 'USA'], ['3', 'Shri Ram', 'India'], ['4', 'Smith', 'USA'], ['5', 'Yuva Raj', 'India'], ['6', 'Suresh', 'India']] 116 | #csv_file = "test.csv" 117 | 118 | #exportList2CSV('slide3columns.csv',csv2txtlistSlide3('ColumnResults.csv')) 119 | -------------------------------------------------------------------------------- /Analysis_2D_Combined_V2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 2D LEM Slope Analysis: 3 | 1. Ordinary Method of Slices 4 | 2. Modified Bishop Method 5 | 3. Spencer Method (1967) 6 | 4. Morgenstern-Price Method (1965) 7 | ''' 8 | 9 | ''' 10 | purpose: Compute 2D FS 11 | Input: slice geometry, interslice function, shear strength, external load, seismic load, water, tension crack, center point, ... 12 | Output: FS, interslice scaling factor, interslice force angle 13 | 14 | description of the input file - subjected to change 15 | 16 | ## Input file column legend for very first row 1 17 | 0(A) - 2D or 3D analysis (2 = 2D; 3 = 3D) 18 | 1(B) - id of analysis (id links to a specific model) 19 | 2(C) - total number of slip surfaces 20 | 21 | ## Input file column legend for row 1 22 | 0(A) - 2D or 3D analysis (2 = 2D; 3 = 3D) 23 | 1(B) - id of analysis (id links to a specific model) 24 | 2(C) - id of slip surface (id links to a particular slip surface) 25 | 3(D) - number of slices 26 | 4(E) - Direction of slope movement (0 = right to left; 1 = left to right) 27 | 5(F) - X coordinate of center of rotation (Pt0x) 28 | 6(G) - Y coordinate of center of rotation (Pt0y) 29 | 7(H) - seismic coefficient for horizontal force (k) 30 | 8(I) - resultant water forces - from tension crack or submersion (A) 31 | 9(J) - perpendicular distance from the resultant water force to the center of rotation (a) 32 | 10(K) - shear strength id (each id links to certain shear strength: 33 | 1 = Mohr-Coulomb 34 | 2 = undrained (Su) 35 | 3 = stress-(c & phi') relationship 36 | 4 = stress-shear relationship 37 | 11(L) - L factor - janbu corrected 38 | 12(M) - d factor - janbu corrected 39 | 40 | ## Input file column legend for row 2 and below 41 | 0(A) - slice number 42 | 1(B) - slice horizontal width (b) 43 | 2(C) - slice base length (l) 44 | 3(D) - slice base angle from horizontal (alpha) 45 | 4(E) - slice top angle from horizontal (beta) 46 | 5(F) - radius (R) 47 | 6(G) - perpendicular offset from center of rotation(f) 48 | 7(H) - horizontal distance from slice to the center of rotation (x) 49 | 8(I) - vertical distance from C.G. of slice to the center of rotation (e) 50 | 9(J) - slice total weight force (W) 51 | 10(K) - pore-water force at the top of slice (U_t) 52 | 11(L) - pore-water force at normal to the base of slice (U_b) 53 | 12(M) - pore-water force at the left side of slice (U_l) 54 | 13(N) - pore-water force at the right side of slice (U_r) 55 | 14(O) - external load - line load (L) 56 | 15(P) - line load orientation from horizontal (omega) 57 | 16(Q) - perpendicular distance from the line load to the center of rotation (L-d) 58 | 17(R) - resultant maximum tensile force from support (T) 59 | 18(S) - angle of support force from horizontal (i) 60 | 19(T) - Soil Shear Strength force (Sm) 61 | 20(U) - Mohr-Coulomb shear strength - cohesion (c') 62 | 21(V) - Mohr-Coulomb shear strength - angle for friction (phi') 63 | 22(W) - tension crack coefficient 64 | 1 = no tension crack 65 | 0 = all base tension cracked 66 | in-between = partial tension crack on the base length 67 | 23(X) - Ru coefficient 68 | ''' 69 | 70 | # making_list_with_floats.py 71 | 72 | def csv2txtlistSlide3(fileName): 73 | import csv 74 | with open(fileName, 'r') as f: 75 | reader = csv.reader(f) 76 | csvListTxt = list(reader) 77 | 78 | csvList = [] 79 | tempList = [] 80 | for idR in range(len(csvListTxt)): 81 | csvListTxt[idR] = [x for x in csvListTxt[idR] if x != ''] 82 | 83 | for i in range(len(csvListTxt[idR])): 84 | if csvListTxt[idR][i] == '': 85 | continue 86 | 87 | elif i==0 and (idR==0 or idR%22 ==0): 88 | indList = list(csvListTxt[idR][i]) 89 | blankInx = indList.index(' ') 90 | columnID = ''.join(csvListTxt[idR][i][(blankInx+1):]) 91 | tempList.append(int(columnID)) 92 | 93 | elif i!=0 and csvListTxt[idR][i].find(',') == -1: 94 | tempList.append(float(csvListTxt[idR][i])) 95 | 96 | elif i!=0 and csvListTxt[idR][i].find(',') != -1: 97 | commaIdx = csvListTxt[idR][i].index(',') 98 | tempList.append(float(csvListTxt[idR][i][0:commaIdx])) 99 | tempList.append(float(csvListTxt[idR][i][(commaIdx+2):])) 100 | 101 | if idR!=0 and len(tempList)==22: 102 | csvList.append(tempList) 103 | tempList = [] 104 | 105 | return csvList 106 | 107 | def csv2list(fileName): 108 | import csv 109 | with open(fileName, 'r') as f: 110 | reader = csv.reader(f) 111 | csvListTxt = list(reader) 112 | 113 | csvListNum = [] 114 | for idR in range(len(csvListTxt)): 115 | csvListTxt[idR] = [x for x in csvListTxt[idR] if x != ''] 116 | tempList = [float(i) for i in csvListTxt[idR]] 117 | csvListNum.append(tempList) 118 | 119 | return csvListNum 120 | 121 | def making_float_list(startNum, endNum, spacing): 122 | result = [] 123 | length = 1 + abs(startNum - endNum)/abs(spacing) 124 | for i in range(int(length)): 125 | x = startNum + spacing*i 126 | result.append(float(x)) 127 | return result 128 | 129 | def concatenate_lists(parentList, addingList): 130 | result = parentList[:] 131 | for i in range(len(addingList)): 132 | result.append(float(addingList[i])) 133 | return result 134 | 135 | def listAtColNum(listName,colNum): 136 | result = [] 137 | for i in range(len(listName)): 138 | result.append(float(listName[i][colNum])) 139 | return result 140 | 141 | def listAtColNumTxt(listName,colNum): 142 | result = [] 143 | for i in range(len(listName)): 144 | result.append(listName[i][colNum]) 145 | return result 146 | 147 | def arrayAtColNum(arrayName,colNum): 148 | import numpy as np 149 | result = [] 150 | for i in range(len(arrayName)): 151 | result.append(float(arrayName[i][colNum])) 152 | result = np.array(result) 153 | return result 154 | 155 | # csv_file = filename of csv exported from list 156 | # csv_column = column titles 157 | # data_list = list data 158 | def exportList2CSV(csv_file,data_list,csv_columns=None): 159 | # export files 160 | import csv 161 | 162 | with open(csv_file, 'w',newline='') as csvfile: 163 | writer = csv.writer(csvfile, delimiter=',') 164 | if csv_columns != None: 165 | writer.writerow(csv_columns) 166 | for data in data_list: 167 | writer.writerow(data) 168 | 169 | # Analysis_2D_Ordinary_V4_06_09_2018.py 170 | def ordinary_method(filename): 171 | import math 172 | 173 | # converting the input csv file into a list 174 | analysisInput = csv2list(filename) 175 | 176 | # total number of slip surfaces 177 | totalSlipSurface = int(analysisInput[0][2]) 178 | 179 | # create an empty list for FS of all slip surfaces 180 | FS = [] 181 | 182 | # cut inputfile into separate lists 183 | for surface_num in range(totalSlipSurface): 184 | if surface_num == 0: 185 | startingRowN=1 186 | else: 187 | startingRowN = endingRowN+1 188 | endingRowN = startingRowN + int(analysisInput[startingRowN][3]) 189 | 190 | analysisInfo= analysisInput[startingRowN] 191 | sliceInfo= analysisInput[startingRowN+1:endingRowN+1] 192 | 193 | # create variables used in ordinary method equation 194 | numerator=0 #numerator of the equation 195 | sum_Wx=0 196 | sum_Pf=0 197 | sum_kWe=0 198 | sum_Aa=analysisInfo[8]*analysisInfo[9] 199 | sum_Ld=0 200 | 201 | # add values from each slice to the total 202 | for slice in sliceInfo: 203 | # water forces 204 | u=slice[11]-slice[10] 205 | l=slice[2]*slice[22] 206 | P=(slice[9] + slice[10])*math.cos(math.radians(slice[3])) - analysisInfo[7]*slice[9]*math.sin(math.radians(slice[3])) 207 | numerator+=(slice[20]*l+(P-u)*math.tan(math.radians(slice[21])))*slice[5] 208 | sum_Wx+=(slice[9])*slice[7] 209 | sum_Pf+=slice[6]*P 210 | sum_kWe+=analysisInfo[7]*slice[9]*slice[8] 211 | sum_Ld+=slice[14]*slice[16] 212 | 213 | # add the FS of each slip surface to the list 214 | FS.append(numerator/(sum_Wx-sum_Pf+sum_kWe+sum_Aa+sum_Ld)) 215 | 216 | return FS 217 | 218 | # Analysis_2D_Modified_Bishop_Method_V6.py 219 | def modified_bishop(filename,tol=0.0001,iterationNMax=100): 220 | import math 221 | 222 | # converting the input csv file into a list 223 | analysisInput= csv2list(filename) 224 | 225 | # total number of slip surfaces 226 | totalSlipSurface= int(analysisInput[0][2]) 227 | 228 | # using ordinary method as a first guess 229 | FSguess = ordinary_method(filename) 230 | 231 | # create an empty list for FS of all slip surfaces 232 | FS=[] 233 | 234 | # cut inputfile into separate lists 235 | for surface_num in range(totalSlipSurface): 236 | iterationN=0 237 | if surface_num == 0: 238 | startingRowN=1 239 | else: 240 | startingRowN= endingRowN+1 241 | endingRowN=startingRowN + int(analysisInput[startingRowN][3]) 242 | 243 | analysisInfo=analysisInput[startingRowN] 244 | sliceInfo= analysisInput[startingRowN+1:endingRowN+1] 245 | 246 | # set initial difference bigger than the tolerance 247 | difference = tol+1 248 | 249 | while difference > tol: 250 | 251 | # create variables used in ordinary method equation 252 | numerator=0 253 | sum_Wx=0 254 | sum_Pf=0 255 | sum_kWe=0 256 | sum_Aa=analysisInfo[8]*analysisInfo[9] 257 | sum_Ld=0 258 | sum_T=0 259 | 260 | # add values from each slice to the total 261 | for slice in sliceInfo: 262 | # water forces 263 | l=slice[2]*slice[22] #slice[1]/math.cos(math.radians(slice[3])) 264 | u=(slice[11]-slice[10]) 265 | m_alpha=math.cos(math.radians(slice[3]))+(math.sin(math.radians(slice[3]))*math.tan(math.radians(slice[21])))/FSguess[surface_num] 266 | P=(slice[9]-(slice[20]*l*math.sin(math.radians(slice[3])))/FSguess[surface_num] + (u*math.tan(math.radians(slice[21]))*math.sin(math.radians(slice[3])))/FSguess[surface_num])/m_alpha 267 | numerator+=(slice[20]*l*slice[5]+(P-u)*slice[5]*math.tan(math.radians(slice[21]))) 268 | sum_Wx+=slice[9]*slice[7] 269 | sum_Pf+=slice[6]*P 270 | sum_kWe+=analysisInfo[7]*slice[9]*slice[8] 271 | sum_Ld+=slice[14]*slice[16] 272 | sum_T+=slice[17] 273 | 274 | F=numerator/(sum_Ld-sum_Pf+sum_Wx+sum_Aa+sum_kWe) 275 | # find the difference between the guess and the result 276 | difference=abs(FSguess[surface_num]-F) 277 | if difference <= tol: 278 | FS.append(F) 279 | iterationN+=1 280 | # stop the loop when number of iterations is over the limit 281 | elif iterationN >=iterationNMax: 282 | if 'NONE' in FS: 283 | FS.append('NONE') 284 | break 285 | else: 286 | FS.append('NONE') 287 | print ('too many iterations (iterationNN) - check code or increase maximum iteration number') 288 | break 289 | else: 290 | FSguess[surface_num]=F 291 | iterationN+=1 292 | return FS 293 | 294 | #main function - 2D slope stability analysis using Janbu's Simplified Method 295 | def janbu_simplified(filename,tol,iterationNMax,f0_used): 296 | import math 297 | import statistics 298 | 299 | # converting the input csv file into a list 300 | analysisInput= csv2list(filename) 301 | 302 | # total number of slip surfaces 303 | totalSlipSurface= int(analysisInput[0][2]) 304 | 305 | # using ordinary method as a first guess 306 | FSguess=ordinary_method(filename) 307 | 308 | # create an empty list for FS of all slip surfaces 309 | FS=[] 310 | 311 | # cut inputfile into separate lists 312 | for surface_num in range(totalSlipSurface): 313 | iterationN=0 314 | if surface_num == 0: 315 | startingRowN=1 316 | else: 317 | startingRowN= endingRowN+1 318 | endingRowN=startingRowN + int(analysisInput[startingRowN][3]) 319 | 320 | analysisInfo=analysisInput[startingRowN] 321 | sliceInfo= analysisInput[startingRowN+1:endingRowN+1] 322 | 323 | # set initial difference bigger than the tolerance 324 | difference = tol+1 325 | 326 | # put all cohesion factor and friction angles into lists and find the most common element 327 | c_list=[] 328 | phi_list=[] 329 | for slice in sliceInfo: 330 | c_list.append(slice[20]) 331 | phi_list.append(slice[21]) 332 | 333 | # using the most common element in the lists, find the according b1 values 334 | ''' 335 | if statistics.mode(c_list) != 0 and statistics.mode(phi_list) !=0: 336 | b1=0.5 337 | elif statistics.mode(c_list) ==0 and statistics.mode(phi_list) !=0: 338 | b1=0.31 339 | elif statistics.mode(c_list) !=0 and statistics.mode(phi_list) ==0: 340 | b1=0.69 341 | ''' 342 | if round(sum(c_list)) != 0 and round(sum(phi_list)) !=0: 343 | b1=0.5 344 | elif round(sum(c_list)) ==0 and round(sum(phi_list)) !=0: 345 | b1=0.31 346 | elif round(sum(c_list)) !=0 and round(sum(phi_list)) ==0: 347 | b1=0.69 348 | 349 | # if we don't want correction, set f0 to 1 350 | if f0_used== True: 351 | f0=1+b1*(analysisInfo[12]/analysisInfo[11]-1.4*(analysisInfo[12]/analysisInfo[11])**2) 352 | else: 353 | f0=1 354 | 355 | while difference>tol: 356 | numerator=0 357 | sum_Psina=0 358 | sum_kW=0 359 | sum_A=analysisInfo[8] 360 | sum_Lcosw=0 361 | for slice in sliceInfo: 362 | l=slice[2]*slice[22] #slice[1]/math.cos(math.radians(slice[3])) 363 | u=(slice[11]-slice[10])/slice[2] 364 | m_alpha=math.cos(math.radians(slice[3]))+(math.sin(math.radians(slice[3]))*math.tan(math.radians(slice[21])))/FSguess[surface_num] 365 | P=(slice[9]-(slice[20]*l*math.sin(math.radians(slice[3])))/FSguess[surface_num]+(u*l*math.tan(math.radians(slice[21]))*math.sin(math.radians(slice[3])))/FSguess[surface_num])/m_alpha 366 | numerator += slice[20]*l*math.cos(math.radians(slice[3]))+(P-u*l)*math.tan(math.radians(slice[21]))*math.cos(math.radians(slice[3])) 367 | sum_Psina += P*math.sin(math.radians(slice[3])) 368 | sum_kW += analysisInfo[7]*slice[9] 369 | sum_Lcosw += slice[14]*math.cos(math.radians(slice[15])) 370 | 371 | F_0=numerator/(sum_Psina+sum_kW+sum_A+sum_Lcosw) 372 | F=F_0*f0 373 | 374 | # find the difference between the guess and the result 375 | difference=abs(FSguess[surface_num]-F) 376 | if difference <= tol: 377 | FS.append(F) 378 | iterationN+=1 379 | # stop the loop when number of iterations is over the limit 380 | elif iterationN >=iterationNMax: 381 | if 'NONE' in FS: 382 | FS.append('NONE') 383 | break 384 | else: 385 | FS.append('NONE') 386 | print ('too many iterations (iterationNN) - check code or increase maximum iteration number') 387 | break 388 | else: 389 | FSguess[surface_num]=F 390 | iterationN+=1 391 | 392 | # tell the user whether the result was modified using the correction factor 393 | ''' 394 | if f0_used==True: 395 | message='correction factor was used' 396 | else: 397 | message='correction factor was not used' 398 | print(message) 399 | ''' 400 | return FS 401 | 402 | # Analysis_2D_Spencer_v2_06_05_2018.py 403 | def changeIntersliceTheta_Spencer(thetaInter, FS_moment_f, FS_force_f, tolaranceFS): 404 | # create total number of change criteria based on decimal points 405 | if tolaranceFS >= 1: 406 | decimalPoint = 1 407 | elif tolaranceFS < 0.0001: 408 | dpListed = list(str(tolaranceFS)) 409 | idx = dpListed.index('-') 410 | dPstring = ''.join(dpListed[idx+1:]) 411 | decimalPoint = int(dPstring) 412 | else: 413 | decimalPoint = len(list(str(tolaranceFS)))-2 414 | 415 | if decimalPoint >= 5: 416 | decimalPoint = 5 417 | tolaranceFS = 0.00001 418 | 419 | dFSLimList = [1] 420 | for loop1 in range(decimalPoint): 421 | if loop1 == decimalPoint-1: 422 | dFSLimList.append(tolaranceFS) 423 | elif tolaranceFS >= 0.0001 and loop1 == decimalPoint-2: 424 | dFSLimList.append(tolaranceFS*5) 425 | else: 426 | dFSLimList.append(0.1*float('1E-'+str(loop1))) 427 | 428 | # change the interslice force angle 429 | completeValueChangeSet = [10, 5, 1, 0.1, 0.01] 430 | valueChangeList = completeValueChangeSet[-(decimalPoint):] 431 | 432 | # changing thetaInter higher or lower value 433 | if FS_moment_f>FS_force_f: 434 | UorD = 1 435 | else: 436 | UorD = -1 437 | 438 | absDiffFS = abs(FS_moment_f - FS_force_f) 439 | #print(FS_moment_f) 440 | #print(FS_force_f) 441 | #print(absDiffFS) 442 | for loop2 in range(decimalPoint): 443 | if absDiffFS <= tolaranceFS: 444 | valueChange = valueChangeList[-1] 445 | break 446 | elif absDiffFS <= dFSLimList[loop2] and absDiffFS > dFSLimList[loop2+1]: 447 | valueChange = valueChangeList[loop2] 448 | break 449 | elif loop2 == decimalPoint-1 and absDiffFS > dFSLimList[0]: 450 | valueChange = valueChangeList[0] 451 | 452 | thetaInter += valueChange*UorD 453 | 454 | return thetaInter 455 | 456 | '''main function - Spencer Method 2D LEM slope stability analysis''' 457 | def analysis2DSpencer(inputFileName, tolaranceFS, iterationNMax, changeThetaInter=None): 458 | # import function from Math Library 459 | #import numpy as np 460 | import math 461 | 462 | # take the inputfile and convert it into list 463 | analysisInput = csv2list(inputFileName) 464 | 465 | # initial trial of FS 466 | FS_initials = ordinary_method(inputFileName) 467 | 468 | totalSlipSurface = int(analysisInput[0][2]) # total number of slip surfaces 469 | 470 | # cut into separate files 471 | results2DLEMSpencer = [] 472 | for loopSlip in range(totalSlipSurface): 473 | # starting and ending row numbers 474 | if loopSlip == 0: 475 | startingRowN = 1 476 | else: 477 | startingRowN = endingRowN+1 478 | endingRowN = startingRowN + int(analysisInput[startingRowN][3]) 479 | 480 | analysisInfo = analysisInput[startingRowN] 481 | sliceInfo = analysisInput[startingRowN+1:endingRowN+1] 482 | 483 | # trial interslice angle (theta) 484 | thetaInter = 0 485 | iterationNN = 1 486 | iteration1 = True 487 | 488 | while iteration1: 489 | 490 | FS_force_i = FS_initials[loopSlip] # inital trial value of FS for force equilibrium 491 | FS_moment_i = FS_initials[loopSlip] # inital trial value of FS for moment equilibrium 492 | iterationN = 1 493 | dE_list = [] 494 | iteration2 = True 495 | 496 | while iteration2: 497 | 498 | # FS for force calculated 499 | FS_force = 0 500 | FS_f_nom = 0 501 | sum_Psina=0 502 | sum_kW=0 503 | sum_A=analysisInfo[8] 504 | sum_Lcosw=0 505 | 506 | # FS for moment calculated 507 | FS_moment = 0 508 | FS_m_nom=0 509 | sum_Wx=0 510 | sum_Pf=0 511 | sum_kWe=0 512 | sum_Aa=analysisInfo[8]*analysisInfo[9] 513 | sum_Ld=0 514 | sum_T=0 515 | 516 | # iterate trough slice 517 | for loopSlice in range(len(sliceInfo)): 518 | 519 | # net pore-water pressure 520 | #u_net_base = (slice[11] - slice[10])/slice[2] 521 | u_net_side = 0 #abs(sliceInfo[loopSlice][12] - sliceInfo[loopSlice][13]) 522 | 523 | # interslice assumption for first analysis 524 | if iterationN == 1: 525 | dX_f = 0 #math.tan(math.radians(thetaInter))*u_net_side 526 | dX_m = 0 #math.tan(math.radians(thetaInter))*u_net_side # change in vertical interslice force (dX = X_L-X_R) 527 | # using FS from previous calculation dX is calculated 528 | else: 529 | dX_f = math.tan(math.radians(thetaInter))*dE_list[loopSlice][0] 530 | dX_m = math.tan(math.radians(thetaInter))*dE_list[loopSlice][1] 531 | #loopSlice += 1 532 | 533 | # actual resisting base length = base length * tension crack coefficient 534 | #b_len_r = sliceInfo[loopSlice][2]*sliceInfo[loopSlice][22] 535 | l=sliceInfo[loopSlice][2]*sliceInfo[loopSlice][22] #sliceInfo[loopSlice][1]/math.cos(math.radians(sliceInfo[loopSlice][3])) 536 | u=(sliceInfo[loopSlice][11]-sliceInfo[loopSlice][10]) 537 | 538 | # calcualte FS for moment 539 | m_alpha_m=math.cos(math.radians(sliceInfo[loopSlice][3]))+(math.sin(math.radians(sliceInfo[loopSlice][3]))*math.tan(math.radians(sliceInfo[loopSlice][21])))/FS_moment_i 540 | P_moment=(sliceInfo[loopSlice][9] - dX_m -(sliceInfo[loopSlice][20]*l*math.sin(math.radians(sliceInfo[loopSlice][3])))/FS_moment_i + (u*sliceInfo[loopSlice][22]*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.sin(math.radians(sliceInfo[loopSlice][3])))/FS_moment_i)/m_alpha_m 541 | FS_m_nom+=(sliceInfo[loopSlice][20]*l*sliceInfo[loopSlice][5]+(P_moment-u*sliceInfo[loopSlice][22])*sliceInfo[loopSlice][5]*math.tan(math.radians(sliceInfo[loopSlice][21]))) 542 | sum_Wx+=sliceInfo[loopSlice][9]*sliceInfo[loopSlice][7] 543 | sum_Pf+=sliceInfo[loopSlice][6]*P_moment 544 | sum_kWe+=analysisInfo[7]*sliceInfo[loopSlice][9]*sliceInfo[loopSlice][8] 545 | sum_Ld+=sliceInfo[loopSlice][14]*sliceInfo[loopSlice][16] 546 | sum_T+=sliceInfo[loopSlice][17] 547 | 548 | # calcualte FS for force 549 | m_alpha_f=math.cos(math.radians(sliceInfo[loopSlice][3]))+(math.sin(math.radians(sliceInfo[loopSlice][3]))*math.tan(math.radians(sliceInfo[loopSlice][21])))/FS_force_i 550 | P_force=(sliceInfo[loopSlice][9] - dX_f -(sliceInfo[loopSlice][20]*l*math.sin(math.radians(sliceInfo[loopSlice][3])))/FS_force_i + (u*sliceInfo[loopSlice][22]*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.sin(math.radians(sliceInfo[loopSlice][3])))/FS_force_i)/m_alpha_f 551 | FS_f_nom += sliceInfo[loopSlice][20]*l*math.cos(math.radians(sliceInfo[loopSlice][3]))+(P_force-u*sliceInfo[loopSlice][22])*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.cos(math.radians(sliceInfo[loopSlice][3])) 552 | sum_Psina += P_force*math.sin(math.radians(sliceInfo[loopSlice][3])) 553 | sum_kW += analysisInfo[7]*sliceInfo[loopSlice][9] 554 | sum_Lcosw += sliceInfo[loopSlice][14]*math.cos(math.radians(sliceInfo[loopSlice][15])) 555 | 556 | # calculate dE for next iteration 557 | # dE = change in horizontal interslice force (dE = E_L-E_R) 558 | dE_f = u_net_side + P_force*math.sin(math.radians(sliceInfo[loopSlice][3])) - (math.cos(math.radians(sliceInfo[loopSlice][3]))/FS_force_i)*(sliceInfo[loopSlice][20]*l +(P_force-u*sliceInfo[loopSlice][22])*math.tan(math.radians(sliceInfo[loopSlice][21]))) #+ analysisInfo[7]*sliceInfo[loopSlice][9] 559 | dE_m = u_net_side + P_moment*math.sin(math.radians(sliceInfo[loopSlice][3])) - (math.cos(math.radians(sliceInfo[loopSlice][3]))/FS_moment_i)*(sliceInfo[loopSlice][20]*l +(P_moment-u*sliceInfo[loopSlice][22])*math.tan(math.radians(sliceInfo[loopSlice][21]))) #+ analysisInfo[7]*sliceInfo[loopSlice][9] 560 | 561 | if iterationN == 1: 562 | dE_list.append([dE_f, dE_m]) 563 | else: 564 | dE_list[loopSlice] = [dE_f, dE_m] 565 | 566 | # calculated FS 567 | #FS_force = FS_f_nom/FS_f_de 568 | FS_force=FS_f_nom/(sum_Psina+sum_kW+sum_A+sum_Lcosw) 569 | #FS_moment = FS_m_nom/FS_m_de 570 | FS_moment=FS_m_nom/(sum_Ld-sum_Pf+sum_Wx+sum_Aa+sum_kWe) 571 | 572 | if iterationN >= iterationNMax: 573 | print('too many iterations - check code or increase maximum iteration number') 574 | iteration2 = False 575 | elif abs(FS_force_i - FS_force) > tolaranceFS or abs(FS_moment_i - FS_moment) > tolaranceFS: 576 | FS_force_i = FS_force 577 | FS_moment_i = FS_moment 578 | FS_force = 0 579 | FS_moment = 0 580 | iterationN += 1 581 | else: 582 | FS_force_i = FS_force 583 | FS_moment_i = FS_moment 584 | iteration2 = False 585 | 586 | FS_force_f = FS_force_i 587 | FS_moment_f = FS_moment_i 588 | #print(thetaInter, FS_force_f, FS_moment_f) 589 | 590 | if iterationN >= iterationNMax or iterationNN >= iterationNMax: 591 | print('too many iterations - check code or increase maximum iteration number') 592 | iteration1 = False 593 | FS_final = 'None' 594 | elif abs(FS_moment_f - FS_force_f) > tolaranceFS: 595 | iterationNN += 1 596 | if changeThetaInter == None: 597 | thetaInter = changeIntersliceTheta_Spencer(thetaInter, FS_moment_f, FS_force_f, tolaranceFS) 598 | elif changeThetaInter != None: 599 | thetaInter += changeThetaInter 600 | else: 601 | FS_final = FS_force_f 602 | iteration1 = False 603 | 604 | results2DLEMSpencer.append([analysisInfo[0:3], [FS_final, thetaInter]]) 605 | 606 | return results2DLEMSpencer 607 | 608 | # Analysis_2D_Morgenstern_Price_v1_06_03_2018.py 609 | 610 | '''change the interslice angle Lambda based on the difference of FS''' 611 | def changeIntersliceLambda_MP(scaleLambda, FS_moment_f, FS_force_f, tolaranceFS): 612 | # create total number of change criteria based on decimal points 613 | if tolaranceFS >= 1: 614 | decimalPoint = 1 615 | elif tolaranceFS < 0.0001: 616 | dpListed = list(str(tolaranceFS)) 617 | idx = dpListed.index('-') 618 | dPstring = ''.join(dpListed[idx+1:]) 619 | decimalPoint = int(dPstring) 620 | else: 621 | decimalPoint = len(list(str(tolaranceFS)))-2 622 | 623 | if decimalPoint >= 5: 624 | decimalPoint = 5 625 | tolaranceFS = 0.00001 626 | 627 | dFSLimList = [0.5] 628 | for loop1 in range(decimalPoint): 629 | if loop1 == decimalPoint-1: 630 | dFSLimList.append(tolaranceFS) 631 | #elif tolaranceFS >= 0.0001 and loop1 == decimalPoint-2: 632 | # dFSLimList.append(tolaranceFS*5) 633 | else: 634 | dFSLimList.append(0.1*float('1E-'+str(loop1))) 635 | 636 | # change the interslice force angle 637 | completeValueChangeSet = [0.5, 0.1, 0.05, 0.01, 0.001] 638 | valueChangeList = completeValueChangeSet[-(decimalPoint):] 639 | 640 | # changing Lambda higher or lower value 641 | if FS_moment_f > FS_force_f: 642 | UorD = 1 643 | else: 644 | UorD = -1 645 | 646 | absDiffFS = abs(FS_moment_f - FS_force_f) 647 | for loop2 in range(decimalPoint): 648 | if absDiffFS <= tolaranceFS: 649 | valueChange = valueChangeList[-1] 650 | break 651 | elif absDiffFS <= dFSLimList[loop2] and absDiffFS > dFSLimList[loop2+1]: 652 | valueChange = valueChangeList[loop2] 653 | break 654 | else: 655 | valueChange = valueChangeList[-1] 656 | break 657 | 658 | scaleLambda += valueChange*UorD 659 | 660 | return scaleLambda 661 | 662 | '''the interslice function''' 663 | def intersliceFx_MorgensternPrice(sliceInfo, FxType, inputFx): 664 | # import modules 665 | import math 666 | 667 | # designate x in F(x) interslice function to each slice 668 | interSliceFx = [] 669 | 670 | sumX = sum(listAtColNum(sliceInfo,1)) 671 | x = 0 672 | 673 | # when Fxtype = 4: parameters from the input to create linear line equations 674 | if FxType == 4: 675 | Fxline = [] 676 | for loopInFx in range(len(inputFx)-1): 677 | start_x = inputFx[loopInFx][0] 678 | end_x = inputFx[loopInFx+1][0] 679 | gradient = (inputFx[loopInFx+1][1]-inputFx[loopInFx][1])/(inputFx[loopInFx+1][0]-inputFx[loopInFx][0]) 680 | intercept = inputFx[loopInFx][1] - gradient*inputFx[loopInFx][0] 681 | Fxline.append([start_x, end_x, gradient, intercept]) 682 | 683 | for loopX in range(len(sliceInfo)): 684 | # x position of each slice 685 | x += 0.5*sliceInfo[loopX][1]/sumX # normalized to vary between 0 and 1 686 | 687 | # interslice function 688 | if FxType == 1: # constant 689 | Fx = 1.0 690 | 691 | elif FxType == 2: # half-sine 692 | Fx = round(math.sin((math.pi)*x),3) 693 | 694 | elif FxType == 3: # clipped sine 695 | # parameters from the input 696 | startFx = inputFx[0] 697 | endFx = inputFx[1] 698 | 699 | # find phase of sine curve 700 | start_x_angle = math.asin(startFx) 701 | end_x_angle = math.asin(endFx) 702 | if start_x_angle > end_x_angle: 703 | phase_angle = (math.pi - end_x_angle) - start_x_angle 704 | else: 705 | phase_angle = end_x_angle - start_x_angle 706 | 707 | Fx = round(math.sin(phase_angle*x + start_x_angle),3) 708 | 709 | elif FxType == 4: # general - user-defined 710 | for loopRow in range(len(Fxline)): 711 | if x >= Fxline[loopRow][0] and x <= Fxline[loopRow][1]: 712 | Fx = x*Fxline[loopRow][2] + Fxline[loopRow][3] 713 | break 714 | 715 | interSliceFx.append([sliceInfo[loopX][0], x, Fx]) 716 | 717 | return interSliceFx 718 | 719 | '''main function - Spencer Method 2D LEM slope stability analysis''' 720 | def analysis2DMorgensternPrice(inputFileName, tolaranceFS, FxType, inputFx, iterationNMax, changeScaleLambda=None): 721 | # import function from Math Library 722 | #import numpy as np 723 | import math 724 | 725 | # take the inputfile and convert it into list 726 | analysisInput = csv2list(inputFileName) 727 | 728 | # initial trial of FS 729 | FS_initials = ordinary_method(inputFileName) 730 | 731 | totalSlipSurface = int(analysisInput[0][2]) # total number of slip surfaces 732 | 733 | # cut into separate files 734 | results2DMP = [] 735 | for loopSlip in range(totalSlipSurface): 736 | # starting and ending row numbers 737 | if loopSlip == 0: 738 | startingRowN = 1 739 | else: 740 | startingRowN = endingRowN+1 741 | endingRowN = startingRowN + int(analysisInput[startingRowN][3]) 742 | 743 | analysisInfo = analysisInput[startingRowN] 744 | sliceInfo = analysisInput[startingRowN+1:endingRowN+1] 745 | 746 | # trial interslice angle (theta) 747 | scaleLambda = 0 #-0.5 748 | intersliceFxList = intersliceFx_MorgensternPrice(sliceInfo, FxType, inputFx) 749 | iterationNN = 1 750 | iteration1 = True 751 | 752 | while iteration1: 753 | 754 | FS_force_i = FS_initials[loopSlip] # inital trial value of FS for force equilibrium 755 | FS_moment_i = FS_initials[loopSlip] # inital trial value of FS for moment equilibrium 756 | iterationN = 1 757 | dE_list = [] 758 | iteration2 = True 759 | 760 | while iteration2: 761 | 762 | # FS for force calculated 763 | FS_force = 0 764 | FS_f_nom = 0 765 | sum_Psina=0 766 | sum_kW=0 767 | sum_A=analysisInfo[8] 768 | sum_Lcosw=0 769 | 770 | # FS for moment calculated 771 | FS_moment = 0 772 | FS_m_nom=0 773 | sum_Wx=0 774 | sum_Pf=0 775 | sum_kWe=0 776 | sum_Aa=analysisInfo[8]*analysisInfo[9] 777 | sum_Ld=0 778 | sum_T=0 779 | 780 | # iterate trough slice 781 | for loopSlice in range(len(sliceInfo)): 782 | 783 | # net pore-water pressure 784 | #u_net_base = (slice[11] - slice[10])/slice[2] 785 | u_net_side = 0 #abs(sliceInfo[loopSlice][12] - sliceInfo[loopSlice][13]) 786 | 787 | # interslice assumption for first analysis 788 | if iterationN == 1: 789 | dX_f = 0 #math.tan(math.radians(thetaInter))*u_net_side 790 | dX_m = 0 #math.tan(math.radians(thetaInter))*u_net_side # change in vertical interslice force (dX = X_L-X_R) 791 | # using FS from previous calculation dX is calculated 792 | else: 793 | dX_f = scaleLambda*intersliceFxList[loopSlice][2]*dE_list[loopSlice][0] 794 | dX_m = scaleLambda*intersliceFxList[loopSlice][2]*dE_list[loopSlice][1] 795 | #loopSlice += 1 796 | 797 | # actual resisting base length = base length * tension crack coefficient 798 | #b_len_r = sliceInfo[loopSlice][2]*sliceInfo[loopSlice][22] 799 | l=sliceInfo[loopSlice][2]*sliceInfo[loopSlice][22] #sliceInfo[loopSlice][1]/math.cos(math.radians(sliceInfo[loopSlice][3])) 800 | u=(sliceInfo[loopSlice][11]-sliceInfo[loopSlice][10]) 801 | 802 | # calcualte FS for moment 803 | m_alpha_m=math.cos(math.radians(sliceInfo[loopSlice][3]))+(math.sin(math.radians(sliceInfo[loopSlice][3]))*math.tan(math.radians(sliceInfo[loopSlice][21])))/FS_moment_i 804 | P_moment=(sliceInfo[loopSlice][9] - dX_m -(sliceInfo[loopSlice][20]*l*math.sin(math.radians(sliceInfo[loopSlice][3])))/FS_moment_i + (u*sliceInfo[loopSlice][22]*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.sin(math.radians(sliceInfo[loopSlice][3])))/FS_moment_i)/m_alpha_m 805 | FS_m_nom+=(sliceInfo[loopSlice][20]*l*sliceInfo[loopSlice][5]+(P_moment-u*sliceInfo[loopSlice][22])*sliceInfo[loopSlice][5]*math.tan(math.radians(sliceInfo[loopSlice][21]))) 806 | sum_Wx+=sliceInfo[loopSlice][9]*sliceInfo[loopSlice][7] 807 | sum_Pf+=sliceInfo[loopSlice][6]*P_moment 808 | sum_kWe+=analysisInfo[7]*sliceInfo[loopSlice][9]*sliceInfo[loopSlice][8] 809 | sum_Ld+=sliceInfo[loopSlice][14]*sliceInfo[loopSlice][16] 810 | sum_T+=sliceInfo[loopSlice][17] 811 | 812 | # calcualte FS for force 813 | m_alpha_f=math.cos(math.radians(sliceInfo[loopSlice][3]))+(math.sin(math.radians(sliceInfo[loopSlice][3]))*math.tan(math.radians(sliceInfo[loopSlice][21])))/FS_force_i 814 | P_force=(sliceInfo[loopSlice][9] - dX_f -(sliceInfo[loopSlice][20]*l*math.sin(math.radians(sliceInfo[loopSlice][3])))/FS_force_i + (u*sliceInfo[loopSlice][22]*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.sin(math.radians(sliceInfo[loopSlice][3])))/FS_force_i)/m_alpha_f 815 | FS_f_nom += sliceInfo[loopSlice][20]*l*math.cos(math.radians(sliceInfo[loopSlice][3]))+(P_force-u*sliceInfo[loopSlice][22])*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.cos(math.radians(sliceInfo[loopSlice][3])) 816 | sum_Psina += P_force*math.sin(math.radians(sliceInfo[loopSlice][3])) 817 | sum_kW += analysisInfo[7]*sliceInfo[loopSlice][9] 818 | sum_Lcosw += sliceInfo[loopSlice][14]*math.cos(math.radians(sliceInfo[loopSlice][15])) 819 | 820 | # calculate dE for next iteration 821 | # dE = change in horizontal interslice force (dE = E_L-E_R) 822 | dE_f = u_net_side + P_force*math.sin(math.radians(sliceInfo[loopSlice][3])) - (math.cos(math.radians(sliceInfo[loopSlice][3]))/FS_force_i)*(sliceInfo[loopSlice][20]*l +(P_force-u*sliceInfo[loopSlice][22])*math.tan(math.radians(sliceInfo[loopSlice][21]))) #+ analysisInfo[7]*sliceInfo[loopSlice][9] 823 | dE_m = u_net_side + P_moment*math.sin(math.radians(sliceInfo[loopSlice][3])) - (math.cos(math.radians(sliceInfo[loopSlice][3]))/FS_moment_i)*(sliceInfo[loopSlice][20]*l +(P_moment-u*sliceInfo[loopSlice][22])*math.tan(math.radians(sliceInfo[loopSlice][21]))) #+ analysisInfo[7]*sliceInfo[loopSlice][9] 824 | 825 | if iterationN == 1: 826 | dE_list.append([dE_f, dE_m]) 827 | else: 828 | dE_list[loopSlice] = [dE_f, dE_m] 829 | 830 | # calculated FS 831 | #FS_force = FS_f_nom/FS_f_de 832 | FS_force=FS_f_nom/(sum_Psina+sum_kW+sum_A+sum_Lcosw) 833 | #FS_moment = FS_m_nom/FS_m_de 834 | FS_moment=FS_m_nom/(sum_Ld-sum_Pf+sum_Wx+sum_Aa+sum_kWe) 835 | 836 | if iterationN >= iterationNMax: 837 | #print('too many iterations - check code or increase maximum iteration number') 838 | iteration2 = False 839 | elif abs(FS_force_i-FS_force) > tolaranceFS or abs(FS_moment_i-FS_moment) > tolaranceFS: 840 | FS_force_i = FS_force 841 | FS_moment_i = FS_moment 842 | FS_force = 0 843 | FS_moment = 0 844 | iterationN += 1 845 | else: 846 | FS_force_i = FS_force 847 | FS_moment_i = FS_moment 848 | iteration2 = False 849 | 850 | FS_force_f = FS_force_i 851 | FS_moment_f = FS_moment_i 852 | 853 | #print(scaleLambda, FS_force_f, FS_moment_f) 854 | 855 | if iterationNN >= iterationNMax: 856 | print('too many iterations (iterationNN) - check code or increase maximum iteration number') 857 | iteration1 = False 858 | FS_final = 0.5*(FS_force_f+FS_moment_f) 859 | 860 | elif abs(FS_moment_f-FS_force_f) > tolaranceFS: 861 | ''' 862 | if iterationNN == 1: 863 | absDiffFS_p, scaleLambda = changeIntersliceLambda_MP(0.1, scaleLambda, FS_moment_f, FS_force_f, tolaranceFS) 864 | else: 865 | absDiffFS_p, scaleLambda = changeIntersliceLambda_MP(absDiffFS_p, scaleLambda, FS_moment_f, FS_force_f, tolaranceFS) 866 | ''' 867 | iterationNN += 1 868 | 869 | if changeScaleLambda == None: 870 | scaleLambda = changeIntersliceLambda_MP(scaleLambda, FS_moment_f, FS_force_f, tolaranceFS) 871 | elif changeScaleLambda != None: 872 | scaleLambda += changeScaleLambda 873 | else: 874 | FS_final = FS_force_f 875 | iteration1 = False 876 | 877 | results2DMP.append([analysisInfo[0:3], [FS_final, scaleLambda, FxType]]) 878 | #print(iterationNN) 879 | 880 | return results2DMP 881 | 882 | # for input method: ordinary=1, modified bishop=2, simplified Janbu=3, corected Janbu=4, spencer=5, morgenstern price=6 883 | ''' 884 | FxType,inputFx 885 | interslice function options: 886 | 1 = constant 887 | 2 = half-sine 888 | 3 = clipped sine -> inputFx = [F(x=0), F(x=1)] 889 | 4 = user-specified -> inputFx = (format = (x,Fx)) [[0,F(x=0)], [x1,F(x=x1)], [x2,F(x=x2)], ... [1,F(x=1)] 890 | ''' 891 | def selectMethod(inputFileName,method,tolaranceFS,iterationNMax,FxType,inputFx): 892 | if method == 1: 893 | FS2D = ordinary_method(inputFileName) 894 | return FS2D#[0] 895 | elif method == 2: 896 | FS2D = modified_bishop(inputFileName,tolaranceFS,iterationNMax) 897 | return FS2D#[0] 898 | elif method == 3: 899 | FS2D = janbu_simplified(inputFileName,tolaranceFS,iterationNMax,False) 900 | return FS2D#[0] 901 | elif method == 4: 902 | FS2D = janbu_simplified(inputFileName,tolaranceFS,iterationNMax,True) 903 | return FS2D#[0] 904 | elif method == 5: 905 | FS2D = analysis2DSpencer(inputFileName, tolaranceFS, iterationNMax, changeThetaInter=0.5) 906 | return FS2D#[0][1][0] 907 | elif method == 6: 908 | FS2D = analysis2DMorgensternPrice(inputFileName, tolaranceFS, FxType, inputFx, iterationNMax, changeScaleLambda=0.005) 909 | return FS2D#[0][1][0] 910 | else: 911 | return 'Invalid Input Method' 912 | 913 | #testing 914 | 915 | ''' 916 | print('from initial input') 917 | print (selectMethod('test inputs for analysis.csv',1,0.001,1000,0,0)) 918 | print (selectMethod('test inputs for analysis.csv',2,0.001,1000,0,0)) 919 | print (selectMethod('test inputs for analysis.csv',3,0.001,1000,0,0)) 920 | #print (selectMethod('test inputs for analysis.csv',4,0.001,1000,0,0)) 921 | print (selectMethod('test inputs for analysis.csv',5,0.001,1000,0,0)) 922 | print (selectMethod('test inputs for analysis.csv',6,0.001,1000,2,0)) 923 | ''' 924 | 925 | import time 926 | time_start = time.clock() 927 | 928 | inputFileName = '2DanalysisInputFile.csv' 929 | #method = 2 930 | tolaranceFS = 0.001 931 | iterationNMax = 1000 932 | FxType = 1 933 | inputFx = 0 934 | ''' 935 | print('method=1') 936 | print (selectMethod(inputFileName,1,tolaranceFS,iterationNMax,FxType,inputFx)) 937 | print() 938 | print('method=2') 939 | print (selectMethod(inputFileName,2,tolaranceFS,iterationNMax,FxType,inputFx)) 940 | print() 941 | ''' 942 | print('method=3') 943 | print (selectMethod(inputFileName,3,tolaranceFS,iterationNMax,FxType,inputFx)) 944 | print() 945 | print('method=4') 946 | print (selectMethod(inputFileName,4,tolaranceFS,iterationNMax,FxType,inputFx)) 947 | print() 948 | ''' 949 | print('method=5') 950 | print (selectMethod(inputFileName,5,tolaranceFS,iterationNMax,FxType,inputFx)) 951 | print() 952 | print('method=6') 953 | print (selectMethod(inputFileName,6,tolaranceFS,iterationNMax,FxType,inputFx)) 954 | ''' 955 | 956 | time_elapsed = (time.clock() - time_start) 957 | print(time_elapsed) # tells us the computation time in seconds -------------------------------------------------------------------------------- /2D_backend_analysis.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on Wed 07/11/2018 3 | 4 | @author: Enok C., Yuming, Anthony 5 | 6 | ''' 7 | 8 | '''make_list_with_floats.py''' 9 | 10 | def csv2txtlistSlide3(fileName): 11 | import csv 12 | with open(fileName, 'r') as f: 13 | reader = csv.reader(f) 14 | csvListTxt = list(reader) 15 | 16 | csvList = [] 17 | tempList = [] 18 | for idR in range(len(csvListTxt)): 19 | csvListTxt[idR] = [x for x in csvListTxt[idR] if x != ''] 20 | 21 | for i in range(len(csvListTxt[idR])): 22 | if csvListTxt[idR][i] == '': 23 | continue 24 | 25 | elif i==0 and (idR==0 or idR%22 ==0): 26 | indList = list(csvListTxt[idR][i]) 27 | blankInx = indList.index(' ') 28 | columnID = ''.join(csvListTxt[idR][i][(blankInx+1):]) 29 | tempList.append(int(columnID)) 30 | 31 | elif i!=0 and csvListTxt[idR][i].find(',') == -1: 32 | tempList.append(float(csvListTxt[idR][i])) 33 | 34 | elif i!=0 and csvListTxt[idR][i].find(',') != -1: 35 | commaIdx = csvListTxt[idR][i].index(',') 36 | tempList.append(float(csvListTxt[idR][i][0:commaIdx])) 37 | tempList.append(float(csvListTxt[idR][i][(commaIdx+2):])) 38 | 39 | if idR!=0 and len(tempList)==22: 40 | csvList.append(tempList) 41 | tempList = [] 42 | 43 | return csvList 44 | 45 | def csv2list(fileName): 46 | import csv 47 | with open(fileName, 'r') as f: 48 | reader = csv.reader(f) 49 | csvListTxt = list(reader) 50 | 51 | csvListNum = [] 52 | for idR in range(len(csvListTxt)): 53 | csvListTxt[idR] = [x for x in csvListTxt[idR] if x != ''] 54 | tempList = [float(i) for i in csvListTxt[idR]] 55 | csvListNum.append(tempList) 56 | 57 | return csvListNum 58 | 59 | def making_float_list(startNum, endNum, spacing): 60 | result = [] 61 | length = 1 + abs(startNum - endNum)/abs(spacing) 62 | for i in range(int(length)): 63 | x = startNum + spacing*i 64 | result.append(float(x)) 65 | return result 66 | 67 | def concatenate_lists(parentList, addingList): 68 | result = parentList[:] 69 | for i in range(len(addingList)): 70 | result.append(float(addingList[i])) 71 | return result 72 | 73 | def listAtColNum(listName,colNum): 74 | result = [] 75 | for i in range(len(listName)): 76 | result.append(float(listName[i][colNum])) 77 | return result 78 | 79 | def listAtColNumTxt(listName,colNum): 80 | result = [] 81 | for i in range(len(listName)): 82 | result.append(listName[i][colNum]) 83 | return result 84 | 85 | def arrayAtColNum(arrayName,colNum): 86 | import numpy as np 87 | result = [] 88 | for i in range(len(arrayName)): 89 | result.append(float(arrayName[i][colNum])) 90 | result = np.array(result) 91 | return result 92 | 93 | # csv_file = filename of csv exported from list 94 | # csv_column = column titles 95 | # data_list = list data 96 | def exportList2CSV(csv_file,data_list,csv_columns=None): 97 | # export files 98 | import csv 99 | 100 | with open(csv_file, 'w',newline='') as csvfile: 101 | writer = csv.writer(csvfile, delimiter=',') 102 | if csv_columns != None: 103 | writer.writerow(csv_columns) 104 | for data in data_list: 105 | writer.writerow(data) 106 | 107 | 108 | ''' 109 | purpose: create slices with information at sides 110 | Input: DEM surface, slice parameters, slip surfaces 111 | Output: slices points 112 | 113 | Interpolation methods used: 114 | 1. scipy interpolation interp1d 115 | > linear - a1 116 | 117 | 2. kriging ordinary 118 | > linear - b1 119 | > power - b2 120 | > gaussian - b3 121 | > spherical - b4 122 | > exponentail - b5 123 | > hole-effect - b6 124 | 3. kriging universal 125 | > linear - c1 126 | > power - c2 127 | > gaussian - c3 128 | > spherical - c4 129 | > exponentail - c5 130 | > hole-effect - c6 131 | ''' 132 | # interpolation method 133 | def interpolation2D(interpolType, edgeXCoords, DEMname, stdMax, exportOption=0): 134 | import numpy as np 135 | 136 | tempArrayX, tempArrayY = np.array(csv2list(DEMname)).T 137 | csvXY = [] 138 | 139 | ''' interpolation method ''' 140 | #library import 141 | if interpolType[0] == 'a': 142 | from scipy.interpolate import interp1d 143 | elif interpolType[0] == 'b': 144 | from pykrige.ok import OrdinaryKriging 145 | elif interpolType[0] == 'c': 146 | from pykrige.uk import UniversalKriging 147 | 148 | # scipy interpol1d 149 | if interpolType == 'a1': 150 | tempInterpolated = interp1d(tempArrayX, tempArrayY, bounds_error=False) 151 | interpolY = tempInterpolated(edgeXCoords) 152 | 153 | # pykrige ordinary kriging 154 | elif interpolType == 'b1': 155 | tempInterpolated = OrdinaryKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='linear') 156 | interpolY, stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 157 | interpolY = interpolY[0] 158 | stdY = stdY[0] 159 | elif interpolType == 'b2': 160 | tempInterpolated = OrdinaryKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='power') 161 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 162 | interpolY = interpolY[0] 163 | stdY = stdY[0] 164 | elif interpolType == 'b3': 165 | tempInterpolated = OrdinaryKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='gaussian') 166 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 167 | interpolY = interpolY[0] 168 | stdY = stdY[0] 169 | elif interpolType == 'b4': 170 | tempInterpolated = OrdinaryKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='spherical') 171 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 172 | interpolY = interpolY[0] 173 | stdY = stdY[0] 174 | elif interpolType == 'b5': 175 | tempInterpolated = OrdinaryKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='exponential') 176 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 177 | interpolY = interpolY[0] 178 | stdY = stdY[0] 179 | elif interpolType == 'b6': 180 | tempInterpolated = OrdinaryKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='hole-effect') 181 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 182 | interpolY = interpolY[0] 183 | stdY = stdY[0] 184 | 185 | # pykrige universal kriging 186 | elif interpolType == 'c1': 187 | tempInterpolated = UniversalKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='linear') 188 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 189 | interpolY = interpolY[0] 190 | stdY = stdY[0] 191 | elif interpolType == 'c2': 192 | tempInterpolated = UniversalKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='power') 193 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 194 | interpolY = interpolY[0] 195 | stdY = stdY[0] 196 | elif interpolType == 'c3': 197 | tempInterpolated = UniversalKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='gaussian') 198 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 199 | interpolY = interpolY[0] 200 | stdY = stdY[0] 201 | elif interpolType == 'c4': 202 | tempInterpolated = UniversalKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='spherical') 203 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 204 | interpolY = interpolY[0] 205 | stdY = stdY[0] 206 | elif interpolType == 'c5': 207 | tempInterpolated = UniversalKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='exponential') 208 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 209 | interpolY = interpolY[0] 210 | stdY = stdY[0] 211 | elif interpolType == 'c6': 212 | tempInterpolated = UniversalKriging(tempArrayX, np.zeros(tempArrayX.shape), tempArrayY, variogram_model='hole-effect') 213 | interpolY,stdY = tempInterpolated.execute('grid', edgeXCoords, np.array([0.])) 214 | interpolY = interpolY[0] 215 | stdY = stdY[0] 216 | 217 | # for pykrige, eliminate points that has a large standard deviation 218 | #print(interpolY) 219 | #print(stdY) 220 | if interpolType[0] in ['b','c']: 221 | for loopYPred in range(len(interpolY)): 222 | if stdY[loopYPred] > stdMax: 223 | interpolY[loopYPred] = np.nan 224 | 225 | #print(interpolY) 226 | #print(stdY) 227 | interpolY = interpolY.tolist() 228 | 229 | for loopXY in range(len(interpolY)): 230 | csvXY.append([edgeXCoords[loopXY], interpolY[loopXY]]) 231 | 232 | # export the interpolated data into csv file 233 | if exportOption==0: 234 | exportList2CSV('interpolated_'+DEMname, csvXY) 235 | 236 | return csvXY 237 | 238 | # function that will calculate y-coordinates (from csv files) for given x-coordinates of slice edges 239 | def DEM_2D_slices(DEMNameList, DEMTypeList, DEMInterpolTypeList, canvasRange, sliceNumberMax, stdMax=10): 240 | # import python libraries 241 | import numpy as np 242 | #import scipy 243 | #import matplotlib.pyplot as plt 244 | 245 | # slice X coordinates 246 | edgeXCoords = np.linspace(canvasRange[0], canvasRange[1], sliceNumberMax+1) 247 | #print(edgeXCoords) 248 | 249 | '''Input file sorting''' 250 | Y_pred = [] 251 | for loopFile in range(len(DEMNameList)): 252 | Y_pred.append(interpolation2D(DEMInterpolTypeList[loopFile], edgeXCoords, DEMNameList[loopFile], stdMax, exportOption=0)) 253 | 254 | #print(Y_pred) 255 | edgesX = {} 256 | sliceN = {} 257 | for loopX in range(len(edgeXCoords)): 258 | tempPtY = [float(canvasRange[2])] 259 | tempPtM = ['bb'] 260 | 261 | # input information to dictionary of edgesX 262 | for loopFile in range(len(DEMNameList)): 263 | interpolY_edge = Y_pred[loopFile][loopX][1] 264 | #print(interpolY_edge) 265 | if not(np.isnan(interpolY_edge)): 266 | if DEMTypeList[loopFile] == 'tt' and interpolY_edge > canvasRange[3]: 267 | tempPtY.append(float(canvasRange[3])) 268 | tempPtM.append('tt') 269 | elif DEMTypeList[loopFile] == 'tt' and interpolY_edge <= canvasRange[3]: 270 | tempPtY.append(interpolY_edge) 271 | tempPtM.append('tt') 272 | elif DEMTypeList[loopFile] == 'rr' and interpolY_edge > canvasRange[2]: 273 | tempPtY[0] = interpolY_edge 274 | tempPtM[0] = 'rr' 275 | else: 276 | tempPtY.append(interpolY_edge) 277 | tempPtM.append(DEMTypeList[loopFile]) 278 | 279 | edgesX[edgeXCoords[loopX]] = [tempPtY, tempPtM] 280 | 281 | if loopX >= 1: 282 | sliceN[loopX] = [edgeXCoords[loopX-1], edgesX[edgeXCoords[loopX-1]], edgeXCoords[loopX], edgesX[edgeXCoords[loopX]]] 283 | 284 | #print(edgesX[36]) 285 | #print(sliceN[20]) 286 | 287 | return sliceN 288 | 289 | ''' DEM points of 2D slip surface ''' 290 | ''' 291 | SSTypeList = 1 -> user-defined surface 292 | SSTypeList = 2 -> grid circular search 293 | ''' 294 | # find base y-coordinates for a given slip surface 295 | def SS_2D_slices(SSTypeList, inputPara, canvasRange, sliceNumberMax, sliceN, stdMax=10): 296 | # import python libraries 297 | import numpy as np 298 | #import scipy 299 | #from scipy.interpolate import interp1d 300 | #from pykrige.ok import OrdinaryKriging 301 | #from pykrige.uk import UniversalKriging 302 | #import matplotlib.pyplot as plt 303 | 304 | newSliceN = {} 305 | ss_csv = [] 306 | 307 | # slice X coordinates 308 | edgeXCoords = np.linspace(canvasRange[0], canvasRange[1], sliceNumberMax+1) 309 | #print(edgeXCoords) 310 | 311 | '''Input SS for each slice X coordiantes''' 312 | ss_Y_pred = {} 313 | 314 | if SSTypeList == 2: # circular grid search 315 | # extract inputPara 316 | pt0X = inputPara[0] 317 | pt0Y = inputPara[1] 318 | R = inputPara[2] 319 | 320 | for loopX in range(len(edgeXCoords)): 321 | if (R**2 - (edgeXCoords[loopX] - pt0X)**2) >= 0: 322 | #tempPtYSS1 = pt0Y + np.sqrt(R**2 - (edgeXCoords[loopX] - pt0X)**2) 323 | tempPtYSS = pt0Y - np.sqrt(R**2 - (edgeXCoords[loopX] - pt0X)**2) 324 | else: 325 | tempPtYSS = np.nan 326 | 327 | ss_Y_pred[loopX] = [edgeXCoords[loopX], tempPtYSS] 328 | 329 | elif SSTypeList == 1: # user-defined surface 330 | # extract inputPara 331 | DEMNameList = inputPara[0] 332 | interpolType = inputPara[1] 333 | 334 | tempPtYSS = interpolation2D(interpolType, edgeXCoords, DEMNameList, stdMax, exportOption=0) 335 | for loopX in range(len(edgeXCoords)): 336 | ss_Y_pred[loopX] = tempPtYSS[loopX] 337 | 338 | #print(ss_Y_pred) 339 | firstLeft = np.nan 340 | lastRight = np.nan 341 | for loopSlice in range(1,sliceNumberMax+1): 342 | 343 | ssLY = ss_Y_pred[loopSlice-1][1] 344 | ssRY = ss_Y_pred[loopSlice][1] 345 | 346 | sliceLedgeY = sliceN[loopSlice] 347 | sliceLedgeY = sliceLedgeY[1][0] 348 | sliceRedgeY = sliceN[loopSlice] 349 | sliceRedgeY = sliceRedgeY[3][0] 350 | 351 | #print(ssLY, ssRY, max(sliceLedgeY), max(sliceRedgeY)) 352 | #print(loopSlice) 353 | #print(np.isnan(ssLY) or np.isnan(ssRY) or ssLY >= max(sliceLedgeY) or ssRY >= max(sliceRedgeY) or ssLY < min(sliceLedgeY) or ssRY < min(sliceRedgeY)) 354 | 355 | if np.isnan(ssLY) or np.isnan(ssRY) or ssLY >= max(sliceLedgeY) or ssRY >= max(sliceRedgeY) or ssLY < min(sliceLedgeY) or ssRY < min(sliceRedgeY): 356 | #if (np.isnan(ssLY) and not(np.isnan(ssRY))) or (not(np.isnan(ssLY)) and (np.isnan(ssRY))) 357 | 358 | if np.isnan(ssLY) or np.isnan(ssRY) or ssLY >= max(sliceLedgeY) or ssRY >= max(sliceRedgeY): 359 | if loopSlice == 1: 360 | ss_csv.append([ss_Y_pred[loopSlice-1][0], np.nan]) 361 | ss_csv.append([ss_Y_pred[loopSlice][0], np.nan]) 362 | 363 | elif ssLY < min(sliceLedgeY) or ssRY < min(sliceRedgeY): 364 | if loopSlice == 1: 365 | ss_csv.append([ss_Y_pred[loopSlice-1][0], min(sliceLedgeY)]) 366 | ss_csv.append([ss_Y_pred[loopSlice][0], min(sliceRedgeY)]) 367 | 368 | elif not(np.isnan(ssLY)) and not(np.isnan(ssRY)) and (min(sliceLedgeY) <= ssLY < max(sliceLedgeY)) and (min(sliceRedgeY) <= ssRY < max(sliceRedgeY)): 369 | if firstLeft == 0: 370 | firstLeft = loopSlice-1 371 | elif lastRight == 0 and firstLeft != 0: 372 | lastRight = loopSlice+1 373 | 374 | # add slip surface to slice edges - left 375 | nsliceLedgeY = [0] 376 | nsliceLedgeYtype = [0] 377 | 378 | sliceLedgeYtype = sliceN[loopSlice] 379 | sliceLedgeYtype = sliceLedgeYtype[1][1] 380 | 381 | tempYss = [] 382 | tempYssType = [] 383 | for loopLayer in range(len(sliceLedgeYtype)): 384 | if sliceLedgeYtype[loopLayer][0] in ['t','m','g']: 385 | nsliceLedgeY.append(sliceLedgeY[loopLayer]) 386 | nsliceLedgeYtype.append(sliceLedgeYtype[loopLayer]) 387 | 388 | elif sliceLedgeYtype[loopLayer][0] in ['r','w','b']: 389 | if loopLayer == 0: 390 | tempYss.append(ssLY) 391 | tempYssType.append('ss') 392 | 393 | if ssLY <= sliceLedgeY[loopLayer]: 394 | tempYss.append(sliceLedgeY[loopLayer]) 395 | tempYssType.append(sliceLedgeYtype[loopLayer]) 396 | 397 | #print(tempYss) 398 | #print(tempYssType) 399 | maxEdgeBottom = max(tempYss) 400 | maxEdgeBottomIDX = tempYss.index(maxEdgeBottom) 401 | maxEdgeBottomType = tempYssType[maxEdgeBottomIDX] 402 | 403 | nsliceLedgeY[0] = maxEdgeBottom 404 | nsliceLedgeYtype[0] = maxEdgeBottomType 405 | 406 | if loopSlice == 1: 407 | ss_csv.append([ss_Y_pred[loopSlice-1][0], maxEdgeBottom]) 408 | 409 | # add slip surface to slice edges - right 410 | nsliceRedgeY = [0] 411 | nsliceRedgeYtype = [0] 412 | 413 | sliceRedgeYtype = sliceN[loopSlice] 414 | sliceRedgeYtype = sliceRedgeYtype[3][1] 415 | 416 | tempYss = [] 417 | tempYssType = [] 418 | for loopLayer in range(len(sliceRedgeYtype)): 419 | if sliceRedgeYtype[loopLayer][0] in ['t','m','g']: 420 | nsliceRedgeY.append(sliceRedgeY[loopLayer]) 421 | nsliceRedgeYtype.append(sliceRedgeYtype[loopLayer]) 422 | 423 | elif sliceRedgeYtype[loopLayer][0] in ['r','w','b']: 424 | if loopLayer == 0: 425 | tempYss.append(ssRY) 426 | tempYssType.append('ss') 427 | 428 | if ssLY <= sliceRedgeY[loopLayer]: 429 | tempYss.append(sliceRedgeY[loopLayer]) 430 | tempYssType.append(sliceRedgeYtype[loopLayer]) 431 | 432 | #print(tempYss) 433 | #print(tempYssType) 434 | maxEdgeBottom = max(tempYss) 435 | maxEdgeBottomIDX = tempYss.index(maxEdgeBottom) 436 | maxEdgeBottomType = tempYssType[maxEdgeBottomIDX] 437 | 438 | nsliceRedgeY[0] = maxEdgeBottom 439 | nsliceRedgeYtype[0] = maxEdgeBottomType 440 | 441 | ss_csv.append([ss_Y_pred[loopSlice][0], maxEdgeBottom]) 442 | 443 | newSliceN[loopSlice] = [ss_Y_pred[loopSlice-1][0], [nsliceLedgeY, nsliceLedgeYtype], ss_Y_pred[loopSlice][0], [nsliceRedgeY, nsliceRedgeYtype]] 444 | 445 | if not np.isnan(firstLeft): 446 | 447 | sliceLedge = sliceN[firstLeft] 448 | sliceLedgeX = sliceLedge[0] 449 | sliceLedgeY = sliceLedge[1][0] 450 | sliceLedgeYtype = sliceLedge[1][1] 451 | sliceRedge = sliceN[firstLeft] 452 | sliceRedgeX = sliceRedge[2] 453 | sliceRedgeY = sliceRedge[3][0] 454 | sliceRedgeYtype = sliceRedge[3][1] 455 | 456 | # add slip surface to slice edges - left 457 | nsliceLedgeY = [0] 458 | nsliceLedgeYtype = [0] 459 | 460 | tt_sliceLedgeY_idx = sliceRedgeYtype.index('tt') 461 | 462 | if SSTypeList == 2: # circular grid search 463 | # extract inputPara 464 | pt0X = inputPara[0] 465 | pt0Y = inputPara[1] 466 | R = inputPara[2] 467 | 468 | tempPtXSS1 = pt0X + np.sqrt(R**2 - (sliceLedgeY[tt_sliceLedgeY_idx] - pt0Y)**2) 469 | tempPtXSS2 = pt0X - np.sqrt(R**2 - (sliceLedgeY[tt_sliceLedgeY_idx] - pt0Y)**2) 470 | 471 | if tempPtXSS1 > sliceLedgeX and tempPtXSS1 < sliceRedgeX: 472 | ss_csv.append([tempPtXSS1, sliceLedgeY[tt_sliceLedgeY_idx]]) 473 | nsliceLedgeY[0] = sliceLedgeY[tt_sliceLedgeY_idx] 474 | nsliceLedgeYtype[0] = 'tt' 475 | 476 | elif tempPtXSS2 > sliceLedgeX and tempPtXSS2 < sliceRedgeX: 477 | ss_csv.append([tempPtXSS2, sliceLedgeY[tt_sliceLedgeY_idx]]) 478 | nsliceLedgeY[0] = sliceLedgeY[tt_sliceLedgeY_idx] 479 | nsliceLedgeYtype[0] = 'tt' 480 | 481 | elif SSTypeList == 1: # user defined 482 | DEMNameList = inputPara[0] 483 | interpolType = inputPara[1] 484 | 485 | tempPtYSS = interpolation2D(interpolType, (sliceLedgeX+sliceRedgeX)/2, DEMNameList, stdMax, exportOption=0) 486 | 487 | ss_csv.append([(sliceLedgeX+sliceRedgeX)/2, tempPtYSS]) 488 | nsliceLedgeY[0] = tempPtYSS 489 | nsliceLedgeYtype[0] = 'tt' 490 | 491 | # add slip surface to slice edges - right 492 | edgeRinfo = newSliceN[firstLeft+1] 493 | edgeRinfo = edgeRinfo[1] 494 | 495 | newSliceN[firstLeft] = [sliceLedgeX, [nsliceLedgeY, nsliceLedgeYtype], sliceRedgeX, edgeRinfo] 496 | 497 | if not np.isnan(lastRight): 498 | 499 | sliceLedge = sliceN[lastRight] 500 | sliceLedgeX = sliceLedge[0] 501 | sliceLedgeY = sliceLedge[1][0] 502 | sliceLedgeYtype = sliceLedge[1][1] 503 | sliceRedge = sliceN[lastRight] 504 | sliceRedgeX = sliceRedge[2] 505 | sliceRedgeY = sliceRedge[3][0] 506 | sliceRedgeYtype = sliceRedge[3][1] 507 | 508 | # add slip surface to slice edges - left 509 | edgeLinfo = newSliceN[lastRight-1] 510 | edgeLinfo = edgeLinfo[3] 511 | 512 | # add slip surface to slice edges - right 513 | nsliceRedgeY = [0] 514 | nsliceRedgeYtype = [0] 515 | 516 | tt_sliceRedgeYtype_idx = sliceRedgeYtype.index('tt') 517 | 518 | if SSTypeList == 2: # circular grid search 519 | # extract inputPara 520 | pt0X = inputPara[0] 521 | pt0Y = inputPara[1] 522 | R = inputPara[2] 523 | 524 | tempPtXSS1 = pt0X + np.sqrt(R**2 - (sliceRedgeY[tt_sliceRedgeYtype_idx] - pt0Y)**2) 525 | tempPtXSS2 = pt0X - np.sqrt(R**2 - (sliceRedgeY[tt_sliceRedgeYtype_idx] - pt0Y)**2) 526 | 527 | if tempPtXSS1 > sliceLedgeX and tempPtXSS1 < sliceRedgeX: 528 | ss_csv.append([tempPtXSS1, sliceRedgeY[tt_sliceRedgeYtype_idx]]) 529 | nsliceRedgeY[0] = sliceRedgeY[tt_sliceRedgeYtype_idx] 530 | nsliceRedgeYtype[0] = 'tt' 531 | 532 | elif tempPtXSS2 > sliceLedgeX and tempPtXSS2 < sliceRedgeX: 533 | ss_csv.append([tempPtXSS2, sliceRedgeY[tt_sliceRedgeYtype_idx]]) 534 | nsliceRedgeY[0] = sliceRedgeY[tt_sliceRedgeYtype_idx] 535 | nsliceRedgeYtype[0] = 'tt' 536 | 537 | elif SSTypeList == 1: # user defined 538 | DEMNameList = inputPara[0] 539 | interpolType = inputPara[1] 540 | 541 | tempPtYSS = interpolation2D(interpolType, (sliceLedgeX+sliceRedgeX)/2, DEMNameList, stdMax, exportOption=0) 542 | 543 | ss_csv.append([(sliceLedgeX+sliceRedgeX)/2, tempPtYSS]) 544 | nsliceRedgeY[0] = tempPtYSS 545 | nsliceRedgeYtype[0] = 'tt' 546 | 547 | newSliceN[lastRight] = [sliceLedgeX, edgeLinfo, sliceRedgeX, [nsliceRedgeY, nsliceRedgeYtype]] 548 | 549 | #print(ss_csv) 550 | if len(newSliceN.keys()) == 0: 551 | return None 552 | else: 553 | exportList2CSV('interpolated_ss_type'+str(SSTypeList)+'.csv', ss_csv) 554 | return newSliceN, ss_csv 555 | 556 | # find center of rotation and radius of user-defined slip surface 557 | def findpt0nR_2D(ss_csv): 558 | import numpy as np 559 | 560 | # starting and ending index 561 | startID = 0 562 | endID = 0 563 | for loopID in range(len(ss_csv)): 564 | if np.isnan(ss_csv[loopID][1]): 565 | if startID != 0 and endID == 0 and not(np.isnan(ss_csv[loopID-1][1])): 566 | endID = loopID-1 567 | break 568 | else: 569 | continue 570 | else: 571 | if startID == 0: 572 | startID = loopID 573 | else: 574 | continue 575 | 576 | #print(ss_csv[startID]) 577 | #print(ss_csv[startID+3]) 578 | #print(ss_csv[endID]) 579 | 580 | P1x = ss_csv[startID][0] 581 | P1y = ss_csv[startID][1] 582 | P2x = ss_csv[startID+3][0] 583 | P2y = ss_csv[startID+3][1] 584 | P3x = ss_csv[endID][0] 585 | P3y = ss_csv[endID][1] 586 | DistSq1 = P1x**2 + P1y**2 587 | DistSq2 = P2x**2 + P2y**2 588 | DistSq3 = P3x**2 + P3y**2 589 | 590 | M11 = np.array([[P1x, P1y, 1],[P2x, P2y, 1],[P3x, P3y, 1]]) 591 | M12 = np.array([[DistSq1, P1y, 1],[DistSq2, P2y, 1],[DistSq3, P3y, 1]]) 592 | M13 = np.array([[DistSq1, P1x, 1],[DistSq2, P2x, 1],[DistSq3, P3x, 1]]) 593 | M14 = np.array([[DistSq1, P1x, P1y],[DistSq2, P2x, P2y],[DistSq3, P3x, P3y]]) 594 | 595 | pt0X = 0.5*np.linalg.det(M12)/np.linalg.det(M11) 596 | pt0Y = -0.5*np.linalg.det(M13)/np.linalg.det(M11) 597 | 598 | R = np.sqrt(pt0X**2 + pt0Y**2 + (np.linalg.det(M14)/np.linalg.det(M11))) 599 | 600 | return [round(pt0X,3), round(pt0Y,3), round(R,3)] 601 | 602 | '''calculate area using shoelace theorem''' 603 | def area_np(x, y): 604 | import numpy as np 605 | x = np.asanyarray(x) 606 | y = np.asanyarray(y) 607 | n = len(x) 608 | shift_up = np.arange(-n+1, 1) 609 | shift_down = np.arange(-1, n-1) 610 | return abs((x * (y.take(shift_up) - y.take(shift_down))).sum() / 2.0) 611 | 612 | '''2D LEM Slope Analysis - compute R, f, x and e for moment arm for moment equilibrium ''' 613 | ''' 614 | Input - X,Y coordinate of each slices, central point of rotation 615 | Output - moment arm of R, f, x and e for corresponding Sm, N, W and k*W 616 | 617 | ## Input file column legend of inputSlice 618 | 0(A) - slice number 619 | 1(B) - central coordinate X 620 | 2(C) - central coordinate Y at top 621 | 3(D) - central coordinate Y at base 622 | 4(E) - slice horizontal width 623 | 5(F) - slice base angle from horizontal (alpha) 624 | 625 | ## output file column legend 626 | 0(A) - slice number 627 | 1(B) - radius (R) 628 | 2(C) - perpendicular offset from center of rotation(f) 629 | 3(D) - horizontal distance from slice to the center of rotation (x) 630 | 4(E) - vertical distance from C.G. of slice to the center of rotation (e) 631 | ''' 632 | def computeRfxe_2D(inputSlice, cenPt0): 633 | # import functions python libraries 634 | #import numpy as np 635 | import math 636 | 637 | # compute horizontal moment arm (x) 638 | xi = abs(inputSlice[1] - cenPt0[0]) 639 | 640 | # compute vertical moment arm for horizontal seismic (e) 641 | ei = abs(cenPt0[1] - 0.5*(inputSlice[2]+inputSlice[3])) 642 | 643 | # compute moment arm of Ri and fi 644 | RY = abs(cenPt0[1] - inputSlice[3]) 645 | RR = math.sqrt(xi**2 + RY**2) 646 | 647 | deltaRangleY = round(90 - (abs(inputSlice[5]) + abs(math.degrees(math.atan(RY/xi)))),2) 648 | 649 | if deltaRangleY == 0: 650 | Ri = RR 651 | fi = 0 652 | elif deltaRangleY != 0: 653 | Ri = RR*math.cos(math.radians(deltaRangleY)) 654 | fi = RR*math.sin(math.radians(deltaRangleY)) 655 | 656 | return [Ri, fi, xi, ei] 657 | 658 | # GW level, pwp 659 | def GW_2D(inputFile, baseZ, water_unitWeight): 660 | import math 661 | 662 | dictKeys = inputFile.keys() 663 | 664 | output = {} 665 | for loopSlice in dictKeys: 666 | 667 | # check presence of GW level 668 | checkGW_left = 0 669 | if 'gw' in inputFile[loopSlice][1][1]: 670 | gwLindex = inputFile[loopSlice][1][1] 671 | gwLindex = gwLindex.index('gw') 672 | gwyL = inputFile[loopSlice][1][0][gwLindex] 673 | xL = inputFile[loopSlice][0] 674 | ytL = inputFile[loopSlice][1][0][-1] 675 | ybL = inputFile[loopSlice][1][0][0] 676 | checkGW_left = 1 677 | 678 | checkGW_right = 0 679 | if 'gw' in inputFile[loopSlice][3][1]: 680 | gwRindex = inputFile[loopSlice][3][1] 681 | gwRindex = gwRindex.index('gw') 682 | gwyR = inputFile[loopSlice][3][0][gwLindex] 683 | xR = inputFile[loopSlice][2] 684 | ytR = inputFile[loopSlice][3][0][-1] 685 | ybR = inputFile[loopSlice][3][0][0] 686 | checkGW_right = 1 687 | 688 | if checkGW_left == 0 and checkGW_right == 0: 689 | continue 690 | elif checkGW_left != 0 and checkGW_right == 0: 691 | gwyR = baseZ 692 | xR = inputFile[loopSlice][2] 693 | ytR = inputFile[loopSlice][3][0][-1] 694 | ybR = inputFile[loopSlice][3][0][0] 695 | elif checkGW_left == 0 and checkGW_right != 0: 696 | gwyL = baseZ 697 | xL = inputFile[loopSlice][0] 698 | ytL = inputFile[loopSlice][1][0][-1] 699 | ybL = inputFile[loopSlice][1][0][0] 700 | 701 | # calculate angle of GW inclination 702 | GWangle = abs(math.atan((gwyR-gwyL)/(xR-xL))) 703 | 704 | # define l 705 | lb_l = gwyL - ybL 706 | lb_r = gwyR - ybR 707 | lt_l = max([gwyL - ytL, 0]) 708 | lt_r = max([gwyR - ytR, 0]) 709 | # for top, take only positive hw 710 | 711 | # calculate hw for left, right, base, top 712 | hw_l = lb_l*(math.cos(GWangle))**2 713 | hw_r = lb_r*(math.cos(GWangle))**2 714 | hw_b = (hw_l+hw_r)/2 715 | hw_t = 0.5*(lt_l*((math.cos(GWangle))**2)+lt_r*((math.cos(GWangle))**2)) 716 | 717 | # calculate net hw for side and base 718 | hw_b_net = hw_b - hw_t 719 | if hw_b_net < 0: 720 | hw_s_net = 0 721 | else: 722 | hw_s_net = abs(hw_l-hw_r) 723 | 724 | output[loopSlice] = [hw_l*water_unitWeight, hw_r*water_unitWeight, hw_t*water_unitWeight, hw_b*water_unitWeight, hw_s_net*water_unitWeight, hw_b_net*water_unitWeight] 725 | 726 | return output 727 | 728 | # main function - slope stability base shear parameters with class input 729 | ## Input file column legend 730 | ''' 731 | 1 = Mohr-Coulomb - [phi', c'] 732 | 2 = undrained - depth - [shear_max, shear_min, Su_top, diff_Su] 733 | 3 = undrained - datum - [shear_max, shear_min, Su_datum, diff_Su, z_datum] 734 | 4 = power curve - [P_atm, a, b] 735 | 5 = shear-normal user defined function - [fileName] 736 | unsaturated - [phi_b, aev, us_max] 737 | ''' 738 | def shearModel2cphi(materialClass, materialName, Z, Ztop, eff_normal_stress, matricSuction): 739 | #import math 740 | import making_list_with_floats as makelist 741 | import numpy as np 742 | 743 | # materialClass takes input 744 | # class[name] = [modelType, inputPara] 745 | 746 | material = materialClass[materialName] 747 | modelType = material[0] 748 | inputPara = material[1][0] 749 | unsaturatedPara = material[1][1] 750 | 751 | calcPhiC=[] 752 | #userShearNormal_mc=[] 753 | 754 | # Mohr-Coulomb Model 755 | if modelType in [1,10]: 756 | calcPhiC.append([inputPara[0], inputPara[1]]) 757 | 758 | # undrained - depth 759 | elif modelType in [2,20]: 760 | calcShear = inputPara[2] + inputPara[3]*(Ztop - Z) 761 | 762 | if calcShear < inputPara[1]: # lower than min shear 763 | calcShear = inputPara[1] 764 | if calcShear > inputPara[0]: # higher than max shear 765 | calcShear = inputPara[0] 766 | 767 | calcPhiC.append([0, calcShear]) 768 | 769 | # undrained - datum 770 | elif modelType in [3,30]: 771 | calcShear = inputPara[2] + inputPara[3]*abs(inputPara[4] - Z) 772 | 773 | if calcShear < inputPara[1]: # lower than min shear 774 | calcShear = inputPara[1] 775 | if calcShear > inputPara[0]: # higher than max shear 776 | calcShear = inputPara[0] 777 | 778 | calcPhiC.append([0, calcShear]) 779 | 780 | # power curve 781 | elif modelType in [4,40]: 782 | calcShear = inputPara[0]*inputPara[1]*(eff_normal_stress/inputPara[0])**inputPara[2] 783 | 784 | calcPhiC.append([0, calcShear]) 785 | 786 | # user defined shear-normal force 787 | elif modelType in [5,50]: 788 | 789 | userShearNormal = makelist.csv2list(inputPara[0]) 790 | 791 | for loopSN in range(len(userShearNormal)-1): 792 | if inputPara[1] <= userShearNormal[loopSN+1][0] and inputPara[1] >= userShearNormal[loopSN][0]: 793 | 794 | gradient = (userShearNormal[loopSN+1][1] - userShearNormal[loopSN][1])/(userShearNormal[loopSN+1][0] - userShearNormal[loopSN][0]) 795 | intercept = userShearNormal[loopSN][1] - gradient*userShearNormal[loopSN][0] 796 | #userShearNormal_mc.append([gradient, intercept]) 797 | 798 | calcShear = gradient*eff_normal_stress + intercept 799 | break 800 | 801 | elif inputPara[1] >= userShearNormal[len(userShearNormal)][0]: 802 | #print('out of range of nonlinear curve') 803 | calcShear = userShearNormal[len(userShearNormal)][1] 804 | break 805 | 806 | else: 807 | continue 808 | 809 | calcPhiC.append([0, calcShear]) 810 | 811 | # adding unsaturated strength 812 | if round(modelType/10) in [1,2,3,4,5]: 813 | if matricSuction >= unsaturatedPara[1]: 814 | unsatShearStrength = min([matricSuction, unsaturatedPara[2]])*np.tan(np.radians(unsaturatedPara[0])) 815 | calcPhiC[1] += unsatShearStrength 816 | 817 | return calcPhiC 818 | 819 | ''' main function - 2D slope stability support forces calculations from class of support type ''' 820 | ''' 821 | 0 = User Defined Support - [type, F(0), d1, d2, d] 822 | 1 = End Anchored - [type, T] 823 | 2 = GeoTextile - [type, A(%), phi, a, T, anchorage_setting] 824 | 3 = Grouted Tieback - [type, T, P, B] 825 | 4 = Grouted Tieback with Friction - [type, T, P, phi, a, D] 826 | 5 = Micro Pile - [type, T] 827 | 6 = Soil Nail - [type, T, P, B] 828 | ''' 829 | ''' 830 | def support_analysis(supportClass, supportName, Ana2D3D=2, Li=None, Lo=None, spacing2D=1, eff_normal_stress=None): 831 | 832 | import math 833 | import making_list_with_floats as makelist 834 | 835 | # converting the input csv file into a list 836 | supportInput = supportClass[supportName] 837 | 838 | F_applied=[] 839 | 840 | # for 3D analysis, set S to 1 841 | if Ana2D3D==3: 842 | Spacing=1 843 | elif Ana2D3D==2: 844 | Spacing=spacing2D 845 | 846 | # End Anchored - 1 = End Anchored - [type, T] 847 | if supportInput[0] == 1: 848 | F=supportInput[1]/Spacing 849 | F_applied.append(F) 850 | 851 | # GeoTextile - #2 = GeoTextile - [type, A(%), phi, a, T, anchorage_setting] 852 | # For GeoTextile Anchorage, 0 = not applicable, 1 = None, 2 = slope face, 3 = embedded end, 4 = both ends 853 | elif supportInput[0] == 2: 854 | # F=[F1:Pullout, F2:Tensile Failure, F3:Stripping] 855 | F=[2*Lo*supportInput[1]*(supportInput[3] + eff_normal_stress*math.tan(math.radians(supportInput[2])))/100, supportInput[4]*Lo/100, 2*Li*supportInput[1]*(supportInput[3] + eff_normal_stress*math.tan(math.radians(supportInput[2])))/100] 856 | 857 | if supportInput[5] == 1: 858 | F_applied.append(min(F)) 859 | elif supportInput[5]== 2: 860 | F_applied.append(min(F[1],F[2])) 861 | elif supportInput[5] == 3: 862 | F_applied.append(min(F[2],F[3])) 863 | elif supportInput[5] == 4: 864 | F_applied.append(F[2]) 865 | 866 | # Grouted Tieback - [type, T, P, B] 867 | elif supportInput[0] == 3: 868 | # F=[F1:Pullout, F2:Tensile Failure, F3:Stripping] 869 | F=[supportInput[3]*Lo/Spacing, supportInput[1]/Spacing, (supportInput[2]+supportInput[3]*Li)/Spacing] 870 | F_applied.append(min(F)) 871 | 872 | # Grouted Tieback with Friction - [type, T, P, phi, a, D] 873 | elif supportInput[0] == 4: 874 | # F=[F1:Pullout, F2:Tensile Failure, F3:Stripping] 875 | strengthModel = supportInput[4] + eff_normal_stress*np.tan(np.radians(supportInput[3])) 876 | 877 | F=[math.pi*supportInput[5]*Lo*strengthModel/Spacing, supportInput[1]/Spacing, (supportInput[2] + math.pi*supportInput[5]*Li*strengthModel)/Spacing] 878 | F_applied.append(min(F)) 879 | 880 | # Micro Pile - [type, T] 881 | elif supportInput[0] == 5: 882 | F=supportInput[1]/Spacing 883 | F_applied.append(F) 884 | 885 | # Soil Nail - [type, T, P, B] 886 | elif supportInput[0] == 6: 887 | F=[supportInput[3]*Lo/Spacing, supportInput[1]/Spacing, (supportInput[2]+supportInput[3]*Li)/Spacing] 888 | F_applied.append(min(F)) 889 | 890 | # User Defined Support - [type, T, F(0), d1, d2] - 6,10,11,12,13 891 | elif supportInput[0] == 0: 892 | 893 | if Li < supportInput[d1]: 894 | slope1 = (supportInput[1]-supportInput[2])/supportInput[3] 895 | F = slope1*Li + supportInput[2] 896 | F_applied.append(F) 897 | 898 | elif Li >= supportInput[3] and Li <= (supportInput[3]+supportInput[4]): 899 | F=supportInput[1] 900 | F_applied.append(F) 901 | 902 | elif Li > (supportInput[3]+supportInput[4]): 903 | slope2=(0-supportInput[1])/((Lo+Li)-supportInput[3]-supportInput[4]) 904 | F=slope2*(Li-supportInput[3]-supportInput[4])+supportInput[1] 905 | F_applied.append(F) 906 | 907 | return F_applied[0] 908 | ''' 909 | 910 | # find geometric data (area, base, width) for each slice 911 | def createInputfile4Analysis_2D_slices(newSliceN, L2R_or_R2L, seismicK, pt0, sliceNumberMax, materialClass, canvasRange, water_unitWeight, tensionCrackAngle=None): 912 | # import python libraries 913 | import numpy as np 914 | #import scipy 915 | #import matplotlib.pyplot as plt 916 | 917 | analysisInputFile = [[2,0,1]] 918 | analysisInputFile.append([2, 0, 1, len(newSliceN), L2R_or_R2L, pt0[0], pt0[1], seismicK, 0, 0, 0]) 919 | 920 | sliceKeyList = newSliceN.keys() 921 | 922 | # width, base length, inclination (base, top), side left length, side right length 923 | sliceInfo_bAlalphaBeta = {} 924 | sliceInfo_W = {} # weight 925 | for sliceN in sliceKeyList: 926 | tempList = [] 927 | 928 | # slice width (b) and base length (l) 929 | b = abs(newSliceN[sliceN][0] - newSliceN[sliceN][2]) 930 | l = np.sqrt((newSliceN[sliceN][1][0][0] - newSliceN[sliceN][3][0][0])**2 + (newSliceN[sliceN][0] - newSliceN[sliceN][2])**2) 931 | tempList.append(b) 932 | tempList.append(l) 933 | 934 | # base angle and top angle (alpha and beta) 935 | alpha = abs((newSliceN[sliceN][1][0][0] - newSliceN[sliceN][3][0][0])/(newSliceN[sliceN][0] - newSliceN[sliceN][2])) 936 | beta = abs((newSliceN[sliceN][1][0][-1] - newSliceN[sliceN][3][0][-1])/(newSliceN[sliceN][0] - newSliceN[sliceN][2])) 937 | tempList.append(alpha) 938 | tempList.append(beta) 939 | 940 | # side left length, side right length 941 | sideL = abs((newSliceN[sliceN][1][0][0] - newSliceN[sliceN][1][0][-1])) 942 | sideR = abs((newSliceN[sliceN][3][0][0] - newSliceN[sliceN][3][0][-1])) 943 | tempList.append(sideL) 944 | tempList.append(sideR) 945 | 946 | # individual areas and their unit weights 947 | tempArea = [] 948 | tempUnitWeight = [] 949 | if sliceN == min(sliceKeyList): 950 | numDiffAreasL = 0 951 | numDiffAreasR = len(newSliceN[sliceN][3][1])-2 952 | 953 | for loopArea in range(numDiffAreasR): 954 | xList = [newSliceN[sliceN][0], newSliceN[sliceN][2], newSliceN[sliceN][2]] 955 | yList = [newSliceN[sliceN][1][0][0], newSliceN[sliceN][3][0][loopArea], newSliceN[sliceN][3][0][loopArea+1]] 956 | 957 | tempType=[newSliceN[sliceN][1][1][0], newSliceN[sliceN][3][1][loopArea], newSliceN[sliceN][3][1][loopArea+1]] 958 | tempArea.append(area_np(xList, yList)) 959 | 960 | if 'gw' in tempType: 961 | for loopAtype in range(loopArea+1, len(newSliceN[sliceN][3][1])): 962 | if newSliceN[sliceN][3][1][loopAtype][0] in ['m']: 963 | tempUnitWeight.append(materialClass[newSliceN[sliceN][3][1][loopAtype]][3]) 964 | break 965 | else: 966 | continue 967 | #elif tempType[0][0] in ['r','w']: 968 | # tempAreaType.append(tempType[1]) 969 | else: 970 | tempUnitWeight.append(materialClass[newSliceN[sliceN][3][1][loopAtype]][2]) 971 | elif sliceN == max(sliceKeyList): 972 | numDiffAreasL = len(newSliceN[sliceN][1][1])-2 973 | numDiffAreasR = 0 974 | 975 | for loopArea in range(numDiffAreasL): 976 | xList = [newSliceN[sliceN][2], newSliceN[sliceN][2], newSliceN[sliceN][0]] 977 | yList = [newSliceN[sliceN][1][0][loopArea], newSliceN[sliceN][1][0][loopArea+1], newSliceN[sliceN][3][0][0]] 978 | 979 | tempType=[newSliceN[sliceN][1][1][loopArea], newSliceN[sliceN][1][1][loopArea+1], newSliceN[sliceN][3][1][0]] 980 | tempArea.append(area_np(xList, yList)) 981 | 982 | if 'gw' in tempType: 983 | for loopAtype in range(loopArea+1, len(newSliceN[sliceN][1][1])): 984 | if newSliceN[sliceN][1][1][loopAtype][0] in ['m']: 985 | tempUnitWeight.append(materialClass[newSliceN[sliceN][1][1][loopAtype]][3]) 986 | break 987 | else: 988 | continue 989 | #elif tempType[0][0] in ['r','w']: 990 | # tempAreaType.append(tempType[1]) 991 | else: 992 | tempUnitWeight.append(materialClass[newSliceN[sliceN][1][1][loopAtype]][2]) 993 | else: 994 | numDiffAreasL = len(newSliceN[sliceN][1][1])-2 995 | numDiffAreasR = len(newSliceN[sliceN][3][1])-2 996 | 997 | for loopArea in range(min([numDiffAreasL, numDiffAreasR])): 998 | xList = [newSliceN[sliceN][0], newSliceN[sliceN][0], newSliceN[sliceN][2], newSliceN[sliceN][2]] 999 | yList = [newSliceN[sliceN][1][0][loopArea], newSliceN[sliceN][1][0][loopArea+1], newSliceN[sliceN][3][0][loopArea+1], newSliceN[sliceN][3][0][loopArea]] 1000 | 1001 | tempType=[newSliceN[sliceN][1][1][loopArea], newSliceN[sliceN][1][1][loopArea+1], newSliceN[sliceN][3][1][loopArea+1], newSliceN[sliceN][3][1][loopArea]] 1002 | tempArea.append(area_np(xList, yList)) 1003 | 1004 | if 'gw' in tempType: 1005 | for loopAtype in range(loopArea+1, len(newSliceN[sliceN][1][1])): 1006 | if newSliceN[sliceN][1][1][loopAtype][0] in ['m']: 1007 | tempUnitWeight.append(materialClass[newSliceN[sliceN][1][1][loopAtype]][3]) 1008 | else: 1009 | continue 1010 | #elif tempType[0][0] in ['r','w']: 1011 | # tempAreaType.append(tempType[0]) 1012 | else: 1013 | for loopAtype in range(loopArea+1, len(newSliceN[sliceN][1][1])): 1014 | if newSliceN[sliceN][1][1][loopAtype][0] in ['m']: 1015 | tempUnitWeight.append(materialClass[newSliceN[sliceN][1][1][loopAtype]][2]) 1016 | else: 1017 | continue 1018 | 1019 | tempW = 0 1020 | for loopW in range(len(tempArea)): 1021 | tempW += tempArea[loopW]*tempUnitWeight[loopW] 1022 | 1023 | sliceInfo_bAlalphaBeta[sliceN] = tempList 1024 | sliceInfo_W[sliceN] = tempW 1025 | 1026 | # R, f, x, e - moment arms 1027 | # make input file 1028 | ''' 1029 | 0(A) - slice number 1030 | 1(B) - central coordinate X 1031 | 2(C) - central coordinate Y at top 1032 | 3(D) - central coordinate Y at base 1033 | 4(E) - slice horizontal width 1034 | 5(F) - slice base angle from horizontal (alpha) 1035 | ''' 1036 | sliceInfo_Rfxe = {} 1037 | for sliceN in sliceKeyList: 1038 | inputSlice = [sliceN, 0.5*(newSliceN[sliceN][0]+newSliceN[sliceN][2]), 0.5*(newSliceN[sliceN][1][0][-1]+newSliceN[sliceN][3][0][-1]), 0.5*(newSliceN[sliceN][1][0][0]+newSliceN[sliceN][3][0][0]), sliceInfo_bAlalphaBeta[sliceN][0], sliceInfo_bAlalphaBeta[sliceN][2]] 1039 | sliceInfo_Rfxe[sliceN] = computeRfxe_2D(inputSlice, pt0) 1040 | 1041 | # pore-water pressure 1042 | # output - [hw_l, hw_r, hw_t, hw_b, hw_s_net, hw_b_net] 1043 | sliceInfo_GW = GW_2D(newSliceN, canvasRange[2], water_unitWeight) 1044 | 1045 | # external load - for future 1046 | #sliceInfo_load = {} 1047 | 1048 | # support - for future 1049 | #sliceInfo_supportT = {} 1050 | 1051 | # shear strength parameters 1052 | sliceInfo_shear = {} 1053 | for sliceN in sliceKeyList: 1054 | 1055 | # name of the material type 1056 | # left side 1057 | if newSliceN[sliceN][1][1][0][0] in ['r','w']: 1058 | materialNameL = newSliceN[sliceN][1][1][0] 1059 | 1060 | elif newSliceN[sliceN][1][1][0][0] in ['b','s'] and len(newSliceN[sliceN][1][1]) != 1: 1061 | if newSliceN[sliceN][1][1][1] not in ['gw']: 1062 | materialNameL = newSliceN[sliceN][1][1][1] 1063 | else: 1064 | materialNameL = newSliceN[sliceN][1][1][2] 1065 | 1066 | elif newSliceN[sliceN][1][1][0][0] in ['b','s'] and len(newSliceN[sliceN][1][1]) == 1: 1067 | materialNameL = None 1068 | 1069 | # right side 1070 | if newSliceN[sliceN][3][1][0][0] in ['r','w']: 1071 | materialNameR = newSliceN[sliceN][1][1][0] 1072 | 1073 | elif newSliceN[sliceN][3][1][0][0] in ['b','s'] and len(newSliceN[sliceN][3][1]) != 1: 1074 | if newSliceN[sliceN][3][1][1] not in ['gw']: 1075 | materialNameR = newSliceN[sliceN][3][1][1] 1076 | else: 1077 | materialNameR = newSliceN[sliceN][3][1][2] 1078 | 1079 | elif newSliceN[sliceN][3][1][0][0] in ['b','s'] and len(newSliceN[sliceN][3][1]) == 1: 1080 | materialNameR = None 1081 | 1082 | if materialNameR != materialNameL and materialNameL == None: 1083 | materialName = materialNameR 1084 | elif materialNameR != materialNameL and materialNameR == None: 1085 | materialName = materialNameL 1086 | elif materialNameR == materialNameL and materialNameL != None and materialNameR != None: 1087 | materialName = materialNameL 1088 | else: 1089 | materialName = newSliceN[sliceN+1][1][1][-2] 1090 | 1091 | # inputs 1092 | if sliceInfo_GW[sliceN][-1] < 0: 1093 | matricSuction = abs(sliceInfo_GW[sliceN][-1]) 1094 | else: 1095 | matricSuction = 0 1096 | 1097 | # width, base length, inclination (base, top), side left length, side right length 1098 | eff_normal_stress = (sliceInfo_W[sliceN]/sliceInfo_bAlalphaBeta[sliceN][1]) - max(sliceInfo_GW[sliceN][-1], 0) 1099 | 1100 | Z = 0.5*(newSliceN[sliceN][1][0][0]+newSliceN[sliceN][3][0][0]) 1101 | 1102 | if materialName in newSliceN[sliceN][1][1][1]: 1103 | materialYLIDX = newSliceN[sliceN][1][1][1].index(materialName) 1104 | else: 1105 | materialYLIDX = -1 1106 | 1107 | if materialName in newSliceN[sliceN][3][1][1]: 1108 | materialYRIDX = newSliceN[sliceN][3][1][1].index(materialName) 1109 | else: 1110 | materialYRIDX = -1 1111 | 1112 | if materialYLIDX != None and materialYRIDX == None: 1113 | Ztop = 0.5*(newSliceN[sliceN][1][0][materialYLIDX]+newSliceN[sliceN][3][0][0]) 1114 | elif materialYLIDX == None and materialYRIDX != None: 1115 | Ztop = 0.5*(newSliceN[sliceN][1][0][0]+newSliceN[sliceN][3][0][materialYRIDX]) 1116 | elif materialYLIDX != None and materialYRIDX != None: 1117 | Ztop = 0.5*(newSliceN[sliceN][1][0][materialYLIDX]+newSliceN[sliceN][3][0][materialYRIDX]) 1118 | 1119 | sliceInfo_shear[sliceN] = shearModel2cphi(materialClass, materialName, Z, Ztop, eff_normal_stress, matricSuction)[0] 1120 | 1121 | # L and d factors for corrected Janbu 1122 | point1 = [newSliceN[min(sliceKeyList)][0], newSliceN[min(sliceKeyList)][1][0][0]] 1123 | point2 = [newSliceN[max(sliceKeyList)][0], newSliceN[max(sliceKeyList)][3][0][0]] 1124 | L_factor = np.sqrt((point1[1]-point2[1])**2 + (point1[0]-point2[0])**2) 1125 | L_factor_gradient = (point1[1]-point2[1])/(point1[0]-point2[0]) 1126 | L_factor_intercept = point1[1] - point1[0]*L_factor_gradient 1127 | 1128 | dList = [] 1129 | for sliceN in sliceKeyList: 1130 | point3 = [0.5*(newSliceN[sliceN][0]+newSliceN[sliceN][2]), 0.5*(newSliceN[sliceN][1][0][0]+newSliceN[sliceN][3][0][0])] 1131 | 1132 | tempX = (L_factor_intercept-point3[1]-(point3[0]/L_factor_gradient))/(-L_factor_gradient-(1/L_factor_gradient)) 1133 | tempY = L_factor_gradient*tempX + L_factor_intercept 1134 | 1135 | tempDist = np.sqrt((point3[1]-tempY)**2 + (point3[0]-tempX)**2) 1136 | dList.append(tempDist) 1137 | d_factor = max(dList) 1138 | 1139 | analysisInputFile[1].append(L_factor) 1140 | analysisInputFile[1].append(d_factor) 1141 | 1142 | # compile into a new csv file for 2D analysis 1143 | newSliceID = 1 1144 | for sliceN in sliceKeyList: 1145 | compileList = [newSliceID] 1146 | 1147 | compileList.append(sliceInfo_bAlalphaBeta[sliceN][0]) # width 1148 | compileList.append(sliceInfo_bAlalphaBeta[sliceN][1]) # base length 1149 | compileList.append(sliceInfo_bAlalphaBeta[sliceN][2]) # base angle incline 1150 | compileList.append(sliceInfo_bAlalphaBeta[sliceN][3]) # top angle incline 1151 | 1152 | compileList.append(sliceInfo_Rfxe[sliceN][0]) # R 1153 | compileList.append(sliceInfo_Rfxe[sliceN][1]) # f 1154 | compileList.append(sliceInfo_Rfxe[sliceN][2]) # x 1155 | compileList.append(sliceInfo_Rfxe[sliceN][3]) # e 1156 | 1157 | compileList.append(sliceInfo_W[sliceN]) # W 1158 | compileList.append(sliceInfo_GW[sliceN][3]*sliceInfo_bAlalphaBeta[sliceN][0]) # U_t 1159 | compileList.append(max([sliceInfo_GW[sliceN][4],0])*sliceInfo_bAlalphaBeta[sliceN][1]) # U_b 1160 | compileList.append(sliceInfo_GW[sliceN][0]*sliceInfo_bAlalphaBeta[sliceN][4]) # U_l 1161 | compileList.append(sliceInfo_GW[sliceN][1]*sliceInfo_bAlalphaBeta[sliceN][5]) # U_r 1162 | 1163 | compileList.append(0) # L 1164 | compileList.append(0) # omega 1165 | compileList.append(0) # L-d 1166 | 1167 | compileList.append(0) # T 1168 | compileList.append(0) # i 1169 | 1170 | if sliceInfo_shear[sliceN][0] == 0 and sliceInfo_shear[sliceN][1] != 0: 1171 | analysisInputFile[1][10] = 2 1172 | compileList.append(sliceInfo_shear[sliceN][1]) # Sm 1173 | compileList.append(sliceInfo_shear[sliceN][0]) # phi' 1174 | compileList.append(sliceInfo_shear[sliceN][1]) # c' 1175 | 1176 | elif sliceInfo_shear[sliceN][0] != 0: 1177 | analysisInputFile[1][10] = 1 1178 | compileList.append(0) # Sm 1179 | compileList.append(sliceInfo_shear[sliceN][0]) # phi' 1180 | compileList.append(sliceInfo_shear[sliceN][1]) # c' 1181 | 1182 | if tensionCrackAngle==None: 1183 | compileList.append(1) 1184 | elif tensionCrackAngle!=None: 1185 | if sliceInfo_bAlalphaBeta[sliceN][2] >= tensionCrackAngle: 1186 | compileList.append(0) 1187 | else: 1188 | compileList.append(1) 1189 | 1190 | analysisInputFile.append(compileList) 1191 | 1192 | exportList2CSV('2DanalysisInputFile.csv', analysisInputFile) 1193 | 1194 | return analysisInputFile 1195 | 1196 | 1197 | # one main function to run 2D backend 1198 | def overall_2D_backend(DEMNameList, DEMTypeList, DEMInterpolTypeList, materialClass, water_unitWeight, canvasRange, sliceNumberMax, SSTypeList, SSinputPara, L2R_or_R2L, seismicK): 1199 | 1200 | slicepoints = DEM_2D_slices(DEMNameList, DEMTypeList, DEMInterpolTypeList, canvasRange, sliceNumberMax) 1201 | slicepointsv2, ss_csv = SS_2D_slices(SSTypeList, SSinputPara, canvasRange, sliceNumberMax, slicepoints) 1202 | pt0 = findpt0nR_2D(ss_csv) 1203 | #print(pt0) 1204 | analysisInputFile = createInputfile4Analysis_2D_slices(slicepointsv2, L2R_or_R2L, seismicK, pt0, sliceNumberMax, materialClass, canvasRange, water_unitWeight, tensionCrackAngle=None) 1205 | 1206 | return slicepointsv2, ss_csv, pt0, analysisInputFile 1207 | 1208 | 1209 | '''2D analysis''' 1210 | # Analysis_2D_Ordinary_V4_06_09_2018.py 1211 | def ordinary_method(filename): 1212 | import math 1213 | 1214 | # converting the input csv file into a list 1215 | analysisInput = csv2list(filename) 1216 | 1217 | # total number of slip surfaces 1218 | totalSlipSurface = int(analysisInput[0][2]) 1219 | 1220 | # create an empty list for FS of all slip surfaces 1221 | FS= [] 1222 | 1223 | # cut inputfile into separate lists 1224 | for surface_num in range(totalSlipSurface): 1225 | if surface_num == 0: 1226 | startingRowN=1 1227 | else: 1228 | startingRowN = endingRowN+1 1229 | endingRowN = startingRowN + int(analysisInput[startingRowN][3]) 1230 | 1231 | analysisInfo= analysisInput[startingRowN] 1232 | sliceInfo= analysisInput[startingRowN+1:endingRowN+1] 1233 | 1234 | # create variables used in ordinary method equation 1235 | numerator=0 #numerator of the equation 1236 | sum_Wx=0 1237 | sum_Pf=0 1238 | sum_kWe=0 1239 | sum_Aa=analysisInfo[8]*analysisInfo[9] 1240 | sum_Ld=0 1241 | 1242 | # add values from each slice to the total 1243 | for slice in sliceInfo: 1244 | # water forces 1245 | u=slice[11]-slice[10] 1246 | l=slice[2]*slice[22] 1247 | P=(slice[9] + slice[10])*math.cos(math.radians(slice[3])) - analysisInfo[7]*slice[9]*math.sin(math.radians(slice[3])) 1248 | numerator+=(slice[20]*l+(P-u)*math.tan(math.radians(slice[21])))*slice[5] 1249 | sum_Wx+=(slice[9])*slice[7] 1250 | sum_Pf+=slice[6]*P 1251 | sum_kWe+=analysisInfo[7]*slice[9]*slice[8] 1252 | sum_Ld+=slice[14]*slice[16] 1253 | 1254 | # add the FS of each slip surface to the list 1255 | FS.append(numerator/(sum_Wx-sum_Pf+sum_kWe+sum_Aa+sum_Ld)) 1256 | 1257 | return FS 1258 | 1259 | # Analysis_2D_Modified_Bishop_Method_V6.py 1260 | def modified_bishop(filename,tol=0.0001,iterationNMax=100): 1261 | import math 1262 | 1263 | # converting the input csv file into a list 1264 | analysisInput= csv2list(filename) 1265 | 1266 | # total number of slip surfaces 1267 | totalSlipSurface= int(analysisInput[0][2]) 1268 | 1269 | # using ordinary method as a first guess 1270 | FSguess = ordinary_method(filename) 1271 | 1272 | # create an empty list for FS of all slip surfaces 1273 | FS=[] 1274 | 1275 | # cut inputfile into separate lists 1276 | for surface_num in range(totalSlipSurface): 1277 | iterationN=0 1278 | if surface_num == 0: 1279 | startingRowN=1 1280 | else: 1281 | startingRowN= endingRowN+1 1282 | endingRowN=startingRowN + int(analysisInput[startingRowN][3]) 1283 | 1284 | analysisInfo=analysisInput[startingRowN] 1285 | sliceInfo= analysisInput[startingRowN+1:endingRowN+1] 1286 | 1287 | # set initial difference bigger than the tolerance 1288 | difference = tol+1 1289 | 1290 | while difference>tol: 1291 | 1292 | # create variables used in ordinary method equation 1293 | numerator=0 1294 | sum_Wx=0 1295 | sum_Pf=0 1296 | sum_kWe=0 1297 | sum_Aa=analysisInfo[8]*analysisInfo[9] 1298 | sum_Ld=0 1299 | sum_T=0 1300 | 1301 | # add values from each slice to the total 1302 | for slice in sliceInfo: 1303 | # water forces 1304 | u=slice[11]-slice[10] 1305 | l=slice[1]/math.cos(math.radians(slice[3])) 1306 | m_alpha=math.cos(math.radians(slice[3]))+(math.sin(math.radians(slice[3]))*math.tan(math.radians(slice[21])))/FSguess[surface_num] 1307 | P=(slice[9]-(slice[20]*l*math.sin(math.radians(slice[3])))/FSguess[surface_num]+(u*l*math.tan(math.radians(slice[21]))*math.sin(math.radians(slice[3])))/FSguess[surface_num])/m_alpha 1308 | numerator+=(slice[20]*l*slice[5]+(P-u)*slice[5]*math.tan(math.radians(slice[21]))) 1309 | sum_Wx+=slice[9]*slice[7] 1310 | sum_Pf+=slice[6]*P 1311 | sum_kWe+=analysisInfo[7]*slice[9]*slice[8] 1312 | sum_Ld+=slice[14]*slice[16] 1313 | sum_T+=slice[17] 1314 | 1315 | F=numerator/(sum_Ld+sum_Pf+sum_Wx+sum_Aa+sum_kWe) 1316 | # find the difference between the guess and the result 1317 | difference=abs(FSguess[surface_num]-F) 1318 | if difference <= tol: 1319 | FS.append(F) 1320 | iterationN+=1 1321 | # stop the loop when number of iterations is over the limit 1322 | elif iterationN >=iterationNMax: 1323 | if 'NONE' in FS: 1324 | FS.append('NONE') 1325 | break 1326 | else: 1327 | FS.append('NONE') 1328 | print ('too many iterations (iterationNN) - check code or increase maximum iteration number') 1329 | break 1330 | else: 1331 | FSguess[surface_num]=F 1332 | iterationN+=1 1333 | return FS 1334 | 1335 | #main function - 2D slope stability analysis using Janbu's Simplified Method 1336 | def janbu_simplified(filename,tol,iterationNMax,f0_used): 1337 | import math 1338 | import statistics 1339 | 1340 | # converting the input csv file into a list 1341 | analysisInput= csv2list(filename) 1342 | 1343 | # total number of slip surfaces 1344 | totalSlipSurface= int(analysisInput[0][2]) 1345 | 1346 | # using ordinary method as a first guess 1347 | FSguess=ordinary_method(filename) 1348 | 1349 | # create an empty list for FS of all slip surfaces 1350 | FS=[] 1351 | 1352 | # cut inputfile into separate lists 1353 | for surface_num in range(totalSlipSurface): 1354 | iterationN=0 1355 | if surface_num == 0: 1356 | startingRowN=1 1357 | else: 1358 | startingRowN= endingRowN+1 1359 | endingRowN=startingRowN + int(analysisInput[startingRowN][3]) 1360 | 1361 | analysisInfo=analysisInput[startingRowN] 1362 | sliceInfo= analysisInput[startingRowN+1:endingRowN+1] 1363 | 1364 | # set initial difference bigger than the tolerance 1365 | difference = tol+1 1366 | 1367 | # put all cohesion factor and friction angles into lists and find the most common element 1368 | c_list=[] 1369 | phi_list=[] 1370 | for slice in sliceInfo: 1371 | c_list.append(slice[20]) 1372 | phi_list.append(slice[21]) 1373 | 1374 | # using the most common element in the lists, find the according b1 values 1375 | if statistics.mode(c_list) != 0 and statistics.mode(phi_list) !=0: 1376 | b1=0.5 1377 | elif statistics.mode(c_list) ==0 and statistics.mode(phi_list) !=0: 1378 | b1=0.31 1379 | elif statistics.mode(c_list) !=0 and statistics.mode(phi_list) ==0: 1380 | b1=0.69 1381 | 1382 | # if we don't want correction, set f0 to 1 1383 | if f0_used== True: 1384 | f0=1+b1*(analysisInfo[12]/analysisInfo[11]-1.4*(analysisInfo[12]/analysisInfo[11])**2) 1385 | else: 1386 | f0=1 1387 | 1388 | while difference>tol: 1389 | numerator=0 1390 | sum_Psina=0 1391 | sum_kW=0 1392 | sum_A=analysisInfo[8] 1393 | sum_Lcosw=0 1394 | for slice in sliceInfo: 1395 | u=slice[11]-slice[10] 1396 | l=slice[1]/math.cos(math.radians(slice[3])) 1397 | m_alpha=math.cos(math.radians(slice[3]))+(math.sin(math.radians(slice[3]))*math.tan(math.radians(slice[21])))/FSguess[surface_num] 1398 | P=(slice[9]-(slice[20]*l*math.sin(math.radians(slice[3])))/FSguess[surface_num]+(u*l*math.tan(math.radians(slice[21]))*math.sin(math.radians(slice[3])))/FSguess[surface_num])/m_alpha 1399 | numerator += slice[20]*l*math.cos(math.radians(slice[3]))+(P-u)*math.tan(math.radians(slice[21]))*math.cos(math.radians(slice[3])) 1400 | sum_Psina += P*math.sin(math.radians(slice[3])) 1401 | sum_kW += analysisInfo[7]*slice[9] 1402 | sum_Lcosw += slice[14]*math.cos(math.radians(slice[15])) 1403 | 1404 | F_0=numerator/(sum_Psina+sum_kW+sum_A+sum_Lcosw) 1405 | F=F_0*f0 1406 | 1407 | # find the difference between the guess and the result 1408 | difference=abs(FSguess[surface_num]-F) 1409 | if difference <= tol: 1410 | FS.append(F) 1411 | iterationN+=1 1412 | # stop the loop when number of iterations is over the limit 1413 | elif iterationN >=iterationNMax: 1414 | if 'NONE' in FS: 1415 | FS.append('NONE') 1416 | break 1417 | else: 1418 | FS.append('NONE') 1419 | print ('too many iterations (iterationNN) - check code or increase maximum iteration number') 1420 | break 1421 | else: 1422 | FSguess[surface_num]=F 1423 | iterationN+=1 1424 | 1425 | # tell the user whether the result was modified using the correction factor 1426 | ''' 1427 | if f0_used==True: 1428 | message='correction factor was used' 1429 | else: 1430 | message='correction factor was not used' 1431 | print(message) 1432 | ''' 1433 | return FS 1434 | 1435 | # Analysis_2D_Spencer_v2_06_05_2018.py 1436 | def changeIntersliceTheta_Spencer(thetaInter, FS_moment_f, FS_force_f, tolaranceFS): 1437 | # create total number of change criteria based on decimal points 1438 | if tolaranceFS >= 1: 1439 | decimalPoint = 1 1440 | elif tolaranceFS < 0.0001: 1441 | dpListed = list(str(tolaranceFS)) 1442 | idx = dpListed.index('-') 1443 | dPstring = ''.join(dpListed[idx+1:]) 1444 | decimalPoint = int(dPstring) 1445 | else: 1446 | decimalPoint = len(list(str(tolaranceFS)))-2 1447 | 1448 | if decimalPoint >= 5: 1449 | decimalPoint = 5 1450 | tolaranceFS = 0.00001 1451 | 1452 | dFSLimList = [1] 1453 | for loop1 in range(decimalPoint): 1454 | if loop1 == decimalPoint-1: 1455 | dFSLimList.append(tolaranceFS) 1456 | elif tolaranceFS >= 0.0001 and loop1 == decimalPoint-2: 1457 | dFSLimList.append(tolaranceFS*5) 1458 | else: 1459 | dFSLimList.append(0.1*float('1E-'+str(loop1))) 1460 | 1461 | # change the interslice force angle 1462 | completeValueChangeSet = [10, 5, 1, 0.1, 0.01] 1463 | valueChangeList = completeValueChangeSet[-(decimalPoint):] 1464 | 1465 | # changing thetaInter higher or lower value 1466 | if FS_moment_f>FS_force_f: 1467 | UorD = 1 1468 | else: 1469 | UorD = -1 1470 | 1471 | absDiffFS = abs(FS_moment_f - FS_force_f) 1472 | for loop2 in range(decimalPoint): 1473 | if absDiffFS <= tolaranceFS: 1474 | valueChange = valueChangeList[-1] 1475 | break 1476 | elif absDiffFS <= dFSLimList[loop2] and absDiffFS > dFSLimList[loop2+1]: 1477 | valueChange = valueChangeList[loop2] 1478 | break 1479 | 1480 | thetaInter += valueChange*UorD 1481 | 1482 | return thetaInter 1483 | 1484 | '''main function - Spencer Method 2D LEM slope stability analysis''' 1485 | def analysis2DSpencer(inputFileName, tolaranceFS=0.0005, iterationNMax=200): 1486 | # import function from Math Library 1487 | #import numpy as np 1488 | import math 1489 | 1490 | # take the inputfile and convert it into list 1491 | analysisInput = csv2list(inputFileName) 1492 | 1493 | # initial trial of FS 1494 | FS_initials = ordinary_method(inputFileName) 1495 | 1496 | totalSlipSurface = int(analysisInput[0][2]) # total number of slip surfaces 1497 | 1498 | # cut into separate files 1499 | results2DLEMSpencer = [] 1500 | for loopSlip in range(totalSlipSurface): 1501 | # starting and ending row numbers 1502 | if loopSlip == 0: 1503 | startingRowN = 1 1504 | else: 1505 | startingRowN = endingRowN+1 1506 | endingRowN = startingRowN + int(analysisInput[startingRowN][3]) 1507 | 1508 | analysisInfo = analysisInput[startingRowN] 1509 | sliceInfo = analysisInput[startingRowN+1:endingRowN+1] 1510 | 1511 | # trial interslice angle (theta) 1512 | thetaInter = 0 1513 | iterationNN = 1 1514 | iteration1 = True 1515 | 1516 | while iteration1: 1517 | 1518 | FS_force_i = FS_initials[loopSlip] # inital trial value of FS for force equilibrium 1519 | FS_moment_i = FS_initials[loopSlip] # inital trial value of FS for moment equilibrium 1520 | iterationN = 1 1521 | dE_list = [] 1522 | iteration2 = True 1523 | 1524 | while iteration2: 1525 | 1526 | # FS for force calculated 1527 | FS_force = 0 1528 | FS_f_nom = 0 1529 | FS_f_de = analysisInfo[8] # A 1530 | 1531 | # FS for moment calculated 1532 | FS_moment = 0 1533 | FS_m_nom = 0 1534 | FS_m_de = analysisInfo[8]*analysisInfo[9] # A*a 1535 | 1536 | # iterate trough slice 1537 | for loopSlice in range(len(sliceInfo)): 1538 | # net pore-water pressure 1539 | u_net_base = sliceInfo[loopSlice][11] - sliceInfo[loopSlice][10] 1540 | u_net_side = abs(sliceInfo[loopSlice][12] - sliceInfo[loopSlice][13]) 1541 | 1542 | # interslice assumption for first analysis 1543 | if iterationN == 1: 1544 | dX_f = math.tan(math.radians(thetaInter))*u_net_side 1545 | dX_m = math.tan(math.radians(thetaInter))*u_net_side # change in vertical interslice force (dX = X_L-X_R) 1546 | # using FS from previous calculation dX is calculated 1547 | else: 1548 | dX_f = math.tan(math.radians(thetaInter))*dE_list[loopSlice][0] 1549 | dX_m = math.tan(math.radians(thetaInter))*dE_list[loopSlice][1] 1550 | 1551 | # actual resisting base length = base length * tension crack coefficient 1552 | b_len_r = sliceInfo[loopSlice][2]*sliceInfo[loopSlice][22] 1553 | 1554 | if analysisInfo[10] == 1: 1555 | # calculate normal force (P) for force equilibrium 1556 | ma_force = math.cos(math.radians(sliceInfo[loopSlice][3])) + math.sin(math.radians(sliceInfo[loopSlice][3]))*math.tan(math.radians(sliceInfo[loopSlice][21]))/FS_force_i 1557 | P_force = (sliceInfo[loopSlice][9] + sliceInfo[loopSlice][10] - dX_f - (sliceInfo[loopSlice][20])*b_len_r*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_force_i + u_net_base*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_force_i)/ma_force 1558 | 1559 | # calculate normal force (P) for moment equilibrium 1560 | ma_moment = math.cos(math.radians(sliceInfo[loopSlice][3])) + math.sin(math.radians(sliceInfo[loopSlice][3]))*math.tan(math.radians(sliceInfo[loopSlice][21]))/FS_moment_i 1561 | P_moment = (sliceInfo[loopSlice][9] + sliceInfo[loopSlice][10] - dX_m - (sliceInfo[loopSlice][20])*b_len_r*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_moment_i + u_net_base*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_moment_i)/ma_moment 1562 | 1563 | # calculate shear strength 1564 | shear_strength_f = (sliceInfo[loopSlice][21]*b_len_r + (P_force - u_net_base)*math.tan(math.radians(sliceInfo[loopSlice][21]))) 1565 | shear_strength_m = (sliceInfo[loopSlice][21]*b_len_r + (P_moment - u_net_base)*math.tan(math.radians(sliceInfo[loopSlice][21]))) 1566 | 1567 | elif analysisInfo[10] != 1: 1568 | # calculate normal force (P) for force equilibrium 1569 | P_force = (sliceInfo[loopSlice][9] + sliceInfo[loopSlice][10] - dX_f - sliceInfo[loopSlice][19]*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_force_i)/math.cos(math.radians(sliceInfo[loopSlice][3])) 1570 | 1571 | # calculate normal force (P) for moment equilibrium 1572 | P_moment = (sliceInfo[loopSlice][9] + sliceInfo[loopSlice][10] - dX_m - sliceInfo[loopSlice][19]*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_moment_i)/math.cos(math.radians(sliceInfo[loopSlice][3])) 1573 | 1574 | # calculate shear strength 1575 | shear_strength_f = sliceInfo[loopSlice][19] 1576 | shear_strength_m = sliceInfo[loopSlice][19] 1577 | 1578 | # calcualte FS for force 1579 | FS_f_nom += math.cos(math.radians(sliceInfo[loopSlice][3]))*shear_strength_f 1580 | FS_f_de += P_force*math.sin(math.radians(sliceInfo[loopSlice][3])) + analysisInfo[7]*(sliceInfo[loopSlice][9]+sliceInfo[loopSlice][10]) - sliceInfo[loopSlice][14]*math.cos(math.radians(sliceInfo[loopSlice][15])) 1581 | 1582 | # calcualte FS for moment 1583 | FS_m_nom += sliceInfo[loopSlice][5]*shear_strength_m 1584 | FS_m_de += (sliceInfo[loopSlice][9]+sliceInfo[loopSlice][10])*sliceInfo[loopSlice][7] - P_moment*sliceInfo[loopSlice][6] + analysisInfo[5]*sliceInfo[loopSlice][9]*sliceInfo[loopSlice][8] + sliceInfo[loopSlice][14]*sliceInfo[loopSlice][16] 1585 | 1586 | # calculate dE for next iteration 1587 | # dE = change in horizontal interslice force (dE = E_L-E_R) 1588 | dE_f = u_net_side + P_force*math.sin(math.radians(sliceInfo[loopSlice][3])) - (math.cos(math.radians(sliceInfo[loopSlice][3]))*shear_strength_f/FS_force_i) + analysisInfo[7]*sliceInfo[loopSlice][9] 1589 | dE_m = u_net_side + P_moment*math.sin(math.radians(sliceInfo[loopSlice][3])) - (math.cos(math.radians(sliceInfo[loopSlice][3]))*shear_strength_m/FS_moment_i) + analysisInfo[7]*sliceInfo[loopSlice][9] 1590 | 1591 | if iterationN == 1: 1592 | dE_list.append([dE_f, dE_m]) 1593 | else: 1594 | dE_list[loopSlice] = [dE_f, dE_m] 1595 | 1596 | # calculated FS 1597 | FS_force = FS_f_nom/FS_f_de 1598 | FS_moment = FS_m_nom/FS_m_de 1599 | 1600 | if iterationN >= iterationNMax: 1601 | print('too many iterations - check code or increase maximum iteration number') 1602 | iteration2 = False 1603 | elif abs(FS_force_i - FS_force) > tolaranceFS or abs(FS_moment_i - FS_moment) > tolaranceFS: 1604 | FS_force_i = FS_force 1605 | FS_moment_i = FS_moment 1606 | FS_force = 0 1607 | FS_moment = 0 1608 | iterationN += 1 1609 | else: 1610 | FS_force_i = FS_force 1611 | FS_moment_i = FS_moment 1612 | iteration2 = False 1613 | 1614 | FS_force_f = FS_force_i 1615 | FS_moment_f = FS_moment_i 1616 | 1617 | if iterationN >= iterationNMax or iterationNN >= iterationNMax: 1618 | print('too many iterations - check code or increase maximum iteration number') 1619 | iteration1 = False 1620 | FS_final = 'None' 1621 | elif abs(FS_moment_f - FS_force_f) > tolaranceFS: 1622 | iterationNN += 1 1623 | thetaInter = changeIntersliceTheta_Spencer(thetaInter, FS_moment_f, FS_force_f, tolaranceFS) 1624 | else: 1625 | FS_final = FS_force_f 1626 | iteration1 = False 1627 | 1628 | results2DLEMSpencer.append([analysisInfo[0:3], [FS_final, thetaInter]]) 1629 | 1630 | return results2DLEMSpencer 1631 | 1632 | # Analysis_2D_Morgenstern_Price_v1_06_03_2018.py 1633 | 1634 | '''change the interslice angle Lambda based on the difference of FS''' 1635 | def changeIntersliceLambda_MP(scaleLambda, FS_moment_f, FS_force_f, tolaranceFS): 1636 | # create total number of change criteria based on decimal points 1637 | if tolaranceFS >= 1: 1638 | decimalPoint = 1 1639 | elif tolaranceFS < 0.0001: 1640 | dpListed = list(str(tolaranceFS)) 1641 | idx = dpListed.index('-') 1642 | dPstring = ''.join(dpListed[idx+1:]) 1643 | decimalPoint = int(dPstring) 1644 | else: 1645 | decimalPoint = len(list(str(tolaranceFS)))-2 1646 | 1647 | if decimalPoint >= 5: 1648 | decimalPoint = 5 1649 | tolaranceFS = 0.00001 1650 | 1651 | dFSLimList = [0.5] 1652 | for loop1 in range(decimalPoint): 1653 | if loop1 == decimalPoint-1: 1654 | dFSLimList.append(tolaranceFS) 1655 | #elif tolaranceFS >= 0.0001 and loop1 == decimalPoint-2: 1656 | # dFSLimList.append(tolaranceFS*5) 1657 | else: 1658 | dFSLimList.append(0.1*float('1E-'+str(loop1))) 1659 | 1660 | # change the interslice force angle 1661 | completeValueChangeSet = [0.5, 0.1, 0.05, 0.01, 0.001] 1662 | valueChangeList = completeValueChangeSet[-(decimalPoint):] 1663 | 1664 | # changing Lambda higher or lower value 1665 | if FS_moment_f > FS_force_f: 1666 | UorD = 1 1667 | else: 1668 | UorD = -1 1669 | 1670 | absDiffFS = abs(FS_moment_f - FS_force_f) 1671 | for loop2 in range(decimalPoint): 1672 | if absDiffFS <= tolaranceFS: 1673 | valueChange = valueChangeList[-1] 1674 | break 1675 | elif absDiffFS <= dFSLimList[loop2] and absDiffFS > dFSLimList[loop2+1]: 1676 | valueChange = valueChangeList[loop2] 1677 | break 1678 | else: 1679 | valueChange = valueChangeList[-1] 1680 | break 1681 | 1682 | scaleLambda += valueChange*UorD 1683 | 1684 | return scaleLambda 1685 | 1686 | '''the interslice function''' 1687 | def intersliceFx_MorgensternPrice(sliceInfo, FxType, inputFx): 1688 | # import modules 1689 | import math 1690 | 1691 | # designate x in F(x) interslice function to each slice 1692 | interSliceFx = [] 1693 | 1694 | sumX = sum(listAtColNum(sliceInfo,1)) 1695 | x = 0 1696 | 1697 | # when Fxtype = 4: parameters from the input to create linear line equations 1698 | if FxType == 4: 1699 | Fxline = [] 1700 | for loopInFx in range(len(inputFx)-1): 1701 | start_x = inputFx[loopInFx][0] 1702 | end_x = inputFx[loopInFx+1][0] 1703 | gradient = (inputFx[loopInFx+1][1]-inputFx[loopInFx][1])/(inputFx[loopInFx+1][0]-inputFx[loopInFx][0]) 1704 | intercept = inputFx[loopInFx][1] - gradient*inputFx[loopInFx][0] 1705 | Fxline.append([start_x, end_x, gradient, intercept]) 1706 | 1707 | for loopX in range(len(sliceInfo)): 1708 | # x position of each slice 1709 | x += 0.5*sliceInfo[loopX][1]/sumX # normalized to vary between 0 and 1 1710 | 1711 | # interslice function 1712 | if FxType == 1: # constant 1713 | Fx = 1.0 1714 | 1715 | elif FxType == 2: # half-sine 1716 | Fx = round(math.sin((math.pi)*x),3) 1717 | 1718 | elif FxType == 3: # clipped sine 1719 | # parameters from the input 1720 | startFx = inputFx[0] 1721 | endFx = inputFx[1] 1722 | 1723 | # find phase of sine curve 1724 | start_x_angle = math.asin(startFx) 1725 | end_x_angle = math.asin(endFx) 1726 | if start_x_angle > end_x_angle: 1727 | phase_angle = (math.pi - end_x_angle) - start_x_angle 1728 | else: 1729 | phase_angle = end_x_angle - start_x_angle 1730 | 1731 | Fx = round(math.sin(phase_angle*x + start_x_angle),3) 1732 | 1733 | elif FxType == 4: # general - user-defined 1734 | for loopRow in range(len(Fxline)): 1735 | if x >= Fxline[loopRow][0] and x <= Fxline[loopRow][1]: 1736 | Fx = x*Fxline[loopRow][2] + Fxline[loopRow][3] 1737 | break 1738 | 1739 | interSliceFx.append([sliceInfo[loopX][0], x, Fx]) 1740 | 1741 | return interSliceFx 1742 | 1743 | '''main function - Spencer Method 2D LEM slope stability analysis''' 1744 | def analysis2DMorgensternPrice(inputFileName, tolaranceFS, FxType, inputFx, iterationNMax): 1745 | # import function from Math Library 1746 | #import numpy as np 1747 | import math 1748 | 1749 | # take the inputfile and convert it into list 1750 | analysisInput = csv2list(inputFileName) 1751 | 1752 | # initial trial of FS 1753 | FS_initials = ordinary_method(inputFileName) 1754 | 1755 | totalSlipSurface = int(analysisInput[0][2]) # total number of slip surfaces 1756 | 1757 | # cut into separate files 1758 | results2DMP = [] 1759 | for loopSlip in range(totalSlipSurface): 1760 | # starting and ending row numbers 1761 | if loopSlip == 0: 1762 | startingRowN = 1 1763 | else: 1764 | startingRowN = endingRowN+1 1765 | endingRowN = startingRowN + int(analysisInput[startingRowN][3]) 1766 | 1767 | analysisInfo = analysisInput[startingRowN] 1768 | sliceInfo = analysisInput[startingRowN+1:endingRowN+1] 1769 | 1770 | # trial interslice angle (theta) 1771 | scaleLambda = 0.5 1772 | intersliceFxList = intersliceFx_MorgensternPrice(sliceInfo, FxType, inputFx) 1773 | iterationNN = 1 1774 | iteration1 = True 1775 | 1776 | while iteration1: 1777 | 1778 | FS_force_i = FS_initials[loopSlip] # inital trial value of FS for force equilibrium 1779 | FS_moment_i = FS_initials[loopSlip] # inital trial value of FS for moment equilibrium 1780 | iterationN = 1 1781 | dE_list = [] 1782 | iteration2 = True 1783 | 1784 | while iteration2: 1785 | 1786 | # FS for force calculated 1787 | FS_force = 0 1788 | FS_f_nom = 0 1789 | FS_f_de = analysisInfo[8] # A 1790 | 1791 | # FS for moment calculated 1792 | FS_moment = 0 1793 | FS_m_nom = 0 1794 | FS_m_de = analysisInfo[8]*analysisInfo[9] # A*a 1795 | 1796 | # iterate trough slice 1797 | for loopSlice in range(len(sliceInfo)): 1798 | # net pore-water pressure 1799 | u_net_base = sliceInfo[loopSlice][11] - sliceInfo[loopSlice][10] 1800 | u_net_side = abs(sliceInfo[loopSlice][12] - sliceInfo[loopSlice][13]) 1801 | 1802 | # interslice assumption for first analysis 1803 | if iterationN == 1: 1804 | dX_f = scaleLambda*intersliceFxList[loopSlice][2]*u_net_side 1805 | dX_m = scaleLambda*intersliceFxList[loopSlice][2]*u_net_side # change in vertical interslice force (dX = X_L-X_R) 1806 | # using FS from previous calculation dX is calculated 1807 | else: 1808 | dX_f = scaleLambda*intersliceFxList[loopSlice][2]*dE_list[loopSlice][0] 1809 | dX_m = scaleLambda*intersliceFxList[loopSlice][2]*dE_list[loopSlice][1] 1810 | 1811 | # actual resisting base length 1812 | b_len_r = sliceInfo[loopSlice][2]*sliceInfo[loopSlice][22] 1813 | 1814 | if analysisInfo[10] == 1: 1815 | # calculate normal force (P) for force equilibrium 1816 | ma_force = math.cos(math.radians(sliceInfo[loopSlice][3])) + math.sin(math.radians(sliceInfo[loopSlice][3]))*math.tan(math.radians(sliceInfo[loopSlice][21]))/FS_force_i 1817 | P_force = (sliceInfo[loopSlice][9] + sliceInfo[loopSlice][10] - dX_f - (sliceInfo[loopSlice][20])*b_len_r*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_force_i + u_net_base*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_force_i)/ma_force 1818 | 1819 | # calculate normal force (P) for moment equilibrium 1820 | ma_moment = math.cos(math.radians(sliceInfo[loopSlice][3])) + math.sin(math.radians(sliceInfo[loopSlice][3]))*math.tan(math.radians(sliceInfo[loopSlice][21]))/FS_moment_i 1821 | P_moment = (sliceInfo[loopSlice][9] + sliceInfo[loopSlice][10] - dX_m - (sliceInfo[loopSlice][20])*b_len_r*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_moment_i + u_net_base*math.tan(math.radians(sliceInfo[loopSlice][21]))*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_moment_i)/ma_moment 1822 | 1823 | # calculate shear strength 1824 | shear_strength_f = (sliceInfo[loopSlice][21]*b_len_r + (P_force - u_net_base)*math.tan(math.radians(sliceInfo[loopSlice][21]))) 1825 | shear_strength_m = (sliceInfo[loopSlice][21]*b_len_r + (P_moment - u_net_base)*math.tan(math.radians(sliceInfo[loopSlice][21]))) 1826 | 1827 | elif analysisInfo[10] != 1: 1828 | # calculate normal force (P) for force equilibrium 1829 | P_force = (sliceInfo[loopSlice][9] + sliceInfo[loopSlice][10] - dX_f - sliceInfo[loopSlice][19]*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_force_i)/math.cos(math.radians(sliceInfo[loopSlice][3])) 1830 | 1831 | # calculate normal force (P) for moment equilibrium 1832 | P_moment = (sliceInfo[loopSlice][9] + sliceInfo[loopSlice][10] - dX_m - sliceInfo[loopSlice][19]*math.sin(math.radians(sliceInfo[loopSlice][3]))/FS_moment_i)/math.cos(math.radians(sliceInfo[loopSlice][3])) 1833 | 1834 | # calculate shear strength 1835 | shear_strength_f = sliceInfo[loopSlice][19] 1836 | shear_strength_m = sliceInfo[loopSlice][19] 1837 | 1838 | # calcualte FS for force 1839 | FS_f_nom += math.cos(math.radians(sliceInfo[loopSlice][3]))*shear_strength_f 1840 | FS_f_de += P_force*math.sin(math.radians(sliceInfo[loopSlice][3])) + analysisInfo[7]*(sliceInfo[loopSlice][9]+sliceInfo[loopSlice][10]) - sliceInfo[loopSlice][14]*math.cos(math.radians(sliceInfo[loopSlice][15])) 1841 | 1842 | # calcualte FS for moment 1843 | FS_m_nom += sliceInfo[loopSlice][5]*shear_strength_m 1844 | FS_m_de += (sliceInfo[loopSlice][9]+sliceInfo[loopSlice][10])*sliceInfo[loopSlice][7] - P_moment*sliceInfo[loopSlice][6] + analysisInfo[5]*sliceInfo[loopSlice][9]*sliceInfo[loopSlice][8] + sliceInfo[loopSlice][14]*sliceInfo[loopSlice][16] 1845 | 1846 | # calculate dE for next iteration 1847 | # dE = change in horizontal interslice force (dE = E_L-E_R) 1848 | dE_f = u_net_side + P_force*math.sin(math.radians(sliceInfo[loopSlice][3])) - (math.cos(math.radians(sliceInfo[loopSlice][3]))*shear_strength_f/FS_force_i) + analysisInfo[7]*sliceInfo[loopSlice][9] 1849 | dE_m = u_net_side + P_moment*math.sin(math.radians(sliceInfo[loopSlice][3])) - (math.cos(math.radians(sliceInfo[loopSlice][3]))*shear_strength_m/FS_moment_i) + analysisInfo[7]*sliceInfo[loopSlice][9] 1850 | 1851 | if iterationN == 1: 1852 | dE_list.append([dE_f, dE_m]) 1853 | else: 1854 | dE_list[loopSlice] = [dE_f, dE_m] 1855 | 1856 | # calculated FS 1857 | FS_force = FS_f_nom/FS_f_de 1858 | FS_moment = FS_m_nom/FS_m_de 1859 | 1860 | if iterationN >= iterationNMax: 1861 | #print('too many iterations - check code or increase maximum iteration number') 1862 | iteration2 = False 1863 | elif abs(FS_force_i-FS_force) > tolaranceFS or abs(FS_moment_i-FS_moment) > tolaranceFS: 1864 | FS_force_i = FS_force 1865 | FS_moment_i = FS_moment 1866 | FS_force = 0 1867 | FS_moment = 0 1868 | iterationN += 1 1869 | else: 1870 | FS_force_i = FS_force 1871 | FS_moment_i = FS_moment 1872 | iteration2 = False 1873 | 1874 | FS_force_f = FS_force_i 1875 | FS_moment_f = FS_moment_i 1876 | 1877 | #print(scaleLambda) 1878 | #print(FS_force_f) 1879 | #print(FS_moment_f) 1880 | #print(iterationNN) 1881 | 1882 | if iterationNN >= iterationNMax: 1883 | print('too many iterations (iterationNN) - check code or increase maximum iteration number') 1884 | iteration1 = False 1885 | FS_final = 0.5*(FS_force_f+FS_moment_f) 1886 | 1887 | elif abs(FS_moment_f-FS_force_f) > tolaranceFS: 1888 | ''' 1889 | if iterationNN == 1: 1890 | absDiffFS_p, scaleLambda = changeIntersliceLambda_MP(0.1, scaleLambda, FS_moment_f, FS_force_f, tolaranceFS) 1891 | else: 1892 | absDiffFS_p, scaleLambda = changeIntersliceLambda_MP(absDiffFS_p, scaleLambda, FS_moment_f, FS_force_f, tolaranceFS) 1893 | ''' 1894 | iterationNN += 1 1895 | scaleLambda = changeIntersliceLambda_MP(scaleLambda, FS_moment_f, FS_force_f, tolaranceFS) 1896 | 1897 | else: 1898 | FS_final = FS_force_f 1899 | iteration1 = False 1900 | 1901 | results2DMP.append([analysisInfo[0:3], [FS_final, scaleLambda, FxType]]) 1902 | #print(iterationNN) 1903 | 1904 | return results2DMP 1905 | 1906 | # for input method: ordinary=1, modified bishop=2, simplified Janbu=3, corected Janbu=4, spencer=5, morgenstern price=6 1907 | def selectMethod(inputFileName,method,tolaranceFS,iterationNMax,FxType,inputFx): 1908 | if method == 1: 1909 | return ordinary_method(inputFileName) 1910 | elif method == 2: 1911 | return modified_bishop(inputFileName,tolaranceFS,iterationNMax) 1912 | elif method == 3: 1913 | return janbu_simplified(inputFileName,tolaranceFS,iterationNMax,False) 1914 | elif method == 4: 1915 | return janbu_simplified(inputFileName,tolaranceFS,iterationNMax,True) 1916 | elif method == 5: 1917 | return analysis2DSpencer(inputFileName, tolaranceFS, iterationNMax) 1918 | elif method == 6: 1919 | return analysis2DMorgensternPrice(inputFileName, tolaranceFS, FxType, inputFx, iterationNMax) 1920 | else: 1921 | return 'Invalid Input Method' 1922 | 1923 | # everything combined 1924 | def process2DDEM(DEMNameList, DEMTypeList, DEMInterpolTypeList, materialClass, water_unitWeight, canvasRange, sliceNumberMax, SSTypeList, SSinputPara, L2R_or_R2L, seismicK, method, inputFileName='2DanalysisInputFile.csv',tolaranceFS=0.001,iterationNMax=100,FxType=0,inputFx=0): 1925 | 1926 | slicepointsv2, ss_csv, pt0, analysisInputFile = overall_2D_backend(DEMNameList, DEMTypeList, DEMInterpolTypeList, materialClass, water_unitWeight, canvasRange, sliceNumberMax, SSTypeList, SSinputPara, L2R_or_R2L, seismicK) 1927 | FS2D = selectMethod(inputFileName,method,tolaranceFS,iterationNMax,FxType,inputFx) 1928 | 1929 | return FS2D 1930 | 1931 | ''' 1932 | #naming convension of DEMTypeList 1933 | 'gw' = groundwater - phreatic layer (uw = 0 at the layer) 1934 | 'mx' = top surface boundary of material x (x is integer) 1935 | 'wx' = weak layer x - does not apply material properties below the weak layer x (x is integer) 1936 | 'rr' = rock layer - base of the slice goes along the surface of rock boundary 1937 | 'tt' = slope face - above this layer there is no material 1938 | ''' 1939 | ## Input file column legend 1940 | ''' 1941 | [modelType, inputPara, unit weight, saturated unit weight] 1942 | 1 = Mohr-Coulomb - [phi', c'] 1943 | 2 = undrained - depth - [shear_max, shear_min, Su_top, diff_Su] 1944 | 3 = undrained - datum - [shear_max, shear_min, Su_datum, diff_Su, z_datum] 1945 | 4 = power curve - [P_atm, a, b] 1946 | 5 = shear-normal user defined function - [fileName] 1947 | unsaturated - [phi_b, aev, us_max] 1948 | 1949 | Interpolation methods used: 1950 | 1. scipy interpolation interp1d 1951 | > linear - a1 1952 | 1953 | 2. kriging ordinary 1954 | > linear - b1 1955 | > power - b2 1956 | > gaussian - b3 1957 | > spherical - b4 1958 | > exponentail - b5 1959 | > hole-effect - b6 1960 | 3. kriging universal 1961 | > linear - c1 1962 | > power - c2 1963 | > gaussian - c3 1964 | > spherical - c4 1965 | > exponentail - c5 1966 | > hole-effect - c6 1967 | 1968 | 1969 | ''' 1970 | '''Output Check''' 1971 | import time 1972 | time_start = time.clock() 1973 | 1974 | DEMNameList = ['gwLevel2D.csv','bedrockLayer2D.csv','weakLayer2D.csv','groundSurface2D.csv','groundSurface2D.csv'] 1975 | DEMTypeList = ['gw','rr','w1','m1','tt'] 1976 | materialClass = {'rr':[1,[[45,10000],[0,0,0]],150,150,1],'w1':[1,[[10,0],[0,0,0]],120,120,2],'m1':[1,[[20,600],[0,0,0]],120,120,3]} 1977 | water_unitWeight = 62.4 1978 | 1979 | DEMInterpolTypeList = ['b1', 'b1', 'b1', 'b1', 'b1'] 1980 | canvasRange = [0, 155, 0, 80] # min X, max X, min Y, max Y 1981 | sliceNumberMax = 100 1982 | 1983 | SSTypeList = 2 1984 | SSinputPara = [60, 90, 80] 1985 | L2R_or_R2L = 1 1986 | seismicK = 0 1987 | 1988 | # for input method: ordinary=1, modified bishop=2, simplified Janbu=3, corected Janbu=4, spencer=5, morgenstern price=6 1989 | method = 3 1990 | 1991 | #selectMethod(inputFileName,method,tolaranceFS,iterationNMax,FxType,inputFx) 1992 | print(process2DDEM(DEMNameList, DEMTypeList, DEMInterpolTypeList, materialClass, water_unitWeight, canvasRange, sliceNumberMax, SSTypeList, SSinputPara, L2R_or_R2L, seismicK, method, inputFileName='2DanalysisInputFile.csv',tolaranceFS=0.001,iterationNMax=100,FxType=0,inputFx=0)) 1993 | 1994 | time_elapsed = (time.clock() - time_start) 1995 | print(time_elapsed) # tells us the computation time in seconds -------------------------------------------------------------------------------- /Analysis_3D_Combined_V2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 3D LEM Slope Analysis: 3 | 1. Hungr Bishop 4 | 2. Hungr Janbu 5 | 3. Hungr Janbu corrected 6 | 4. Cheng and Yip Bishop 7 | 5. Cheng and Yip Janbu 8 | 6. Cheng and Yip Spencer 9 | ''' 10 | 11 | ''' 12 | # file input 13 | 0(A) columnId 14 | 1(B),2(C) Coordinates X and Y 15 | 3(D) Base Normal Stress (psf) 16 | 4(E) Base Effective Normal Stress (psf) 17 | 5(F) Pore Pressure (psf) 18 | 6(G) Excess Pore Pressure (psf) 19 | 7(H) Initial Pore Pressure (psf) 20 | 8(I) Shear Strength (psf) 21 | 9(J) Shear Stress (psf) 22 | 10(K) Base Shear Force (lbs) 23 | 11(L) Base Normal Force (lbs) 24 | 12(M) Base Cohesion (psf) 25 | 13(N) Base Friction Angle (deg) 26 | 14(O) Column Weight (lbs) 27 | 15(P) Column Volume (ft3) 28 | 16(Q) Column Weight/Area (lbs/ft2) 29 | 17(R) Dip of Column Base (deg) 30 | 18(S) Dip Direction of Column Base (deg) 31 | 19(T) Matric Suction (psf) 32 | 20(U) Column Center Z Top (ft) 33 | 21(V) Column Center Z Bottom (ft) 34 | 35 | # may be added later 36 | 22(W),23(X),24(Y),25(Z) = area of side 1,2,3,4 37 | 26(AA) = shear model type 38 | 27(AB) = material name ID 39 | 28(AC) = tensile strength - support 40 | 29(AD) = tension crack coefficient 41 | 30(AE) = Ru coefficient 42 | 31(AF) = Dip of Column Top (deg) 43 | 32(AG) = Dip Direction of Column Top (deg) 44 | ''' 45 | 46 | # making_list_with_floats.py 47 | 48 | def csv2txtlistSlide3(fileName): 49 | import csv 50 | with open(fileName, 'r') as f: 51 | reader = csv.reader(f) 52 | csvListTxt = list(reader) 53 | 54 | csvList = [] 55 | tempList = [] 56 | for idR in range(len(csvListTxt)): 57 | csvListTxt[idR] = [x for x in csvListTxt[idR] if x != ''] 58 | 59 | for i in range(len(csvListTxt[idR])): 60 | if csvListTxt[idR][i] == '': 61 | continue 62 | 63 | elif i==0 and (idR==0 or idR%22 ==0): 64 | indList = list(csvListTxt[idR][i]) 65 | blankInx = indList.index(' ') 66 | columnID = ''.join(csvListTxt[idR][i][(blankInx+1):]) 67 | tempList.append(int(columnID)) 68 | 69 | elif i!=0 and csvListTxt[idR][i].find(',') == -1: 70 | tempList.append(float(csvListTxt[idR][i])) 71 | 72 | elif i!=0 and csvListTxt[idR][i].find(',') != -1: 73 | commaIdx = csvListTxt[idR][i].index(',') 74 | tempList.append(float(csvListTxt[idR][i][0:commaIdx])) 75 | tempList.append(float(csvListTxt[idR][i][(commaIdx+2):])) 76 | 77 | if idR!=0 and len(tempList)==22: 78 | csvList.append(tempList) 79 | tempList = [] 80 | 81 | return csvList 82 | 83 | def csv2list(fileName): 84 | import csv 85 | with open(fileName, 'r') as f: 86 | reader = csv.reader(f) 87 | csvListTxt = list(reader) 88 | 89 | csvListNum = [] 90 | for idR in range(len(csvListTxt)): 91 | csvListTxt[idR] = [x for x in csvListTxt[idR] if x != ''] 92 | tempList = [float(i) for i in csvListTxt[idR]] 93 | csvListNum.append(tempList) 94 | 95 | return csvListNum 96 | 97 | def making_float_list(startNum, endNum, spacing): 98 | result = [] 99 | length = 1 + abs(startNum - endNum)/abs(spacing) 100 | for i in range(int(length)): 101 | x = startNum + spacing*i 102 | result.append(float(x)) 103 | return result 104 | 105 | def concatenate_lists(parentList, addingList): 106 | result = parentList[:] 107 | for i in range(len(addingList)): 108 | result.append(float(addingList[i])) 109 | return result 110 | 111 | def listAtColNum(listName,colNum): 112 | result = [] 113 | for i in range(len(listName)): 114 | result.append(float(listName[i][colNum])) 115 | return result 116 | 117 | def listAtColNumTxt(listName,colNum): 118 | result = [] 119 | for i in range(len(listName)): 120 | result.append(listName[i][colNum]) 121 | return result 122 | 123 | def arrayAtColNum(arrayName,colNum): 124 | import numpy as np 125 | result = [] 126 | for i in range(len(arrayName)): 127 | result.append(float(arrayName[i][colNum])) 128 | result = np.array(result) 129 | return result 130 | 131 | # csv_file = filename of csv exported from list 132 | # csv_column = column titles 133 | # data_list = list data 134 | def exportList2CSV(csv_file,data_list,csv_columns=None): 135 | # export files 136 | import csv 137 | 138 | with open(csv_file, 'w',newline='') as csvfile: 139 | writer = csv.writer(csvfile, delimiter=',') 140 | if csv_columns != None: 141 | writer.writerow(csv_columns) 142 | for data in data_list: 143 | writer.writerow(data) 144 | 145 | # pts = [(x1, y1, z1), (x2, y2, z2), (x3, y3, z3)] 146 | def angleBtw3Pts(pts): 147 | import numpy as np 148 | 149 | ptA, ptB, ptC = pts[0], pts[1], pts[2] 150 | x1, y1, z1 = float(ptA[0]), float(ptA[1]), float(ptA[2]) 151 | x2, y2, z2 = float(ptB[0]), float(ptB[1]), float(ptB[2]) 152 | x3, y3, z3 = float(ptC[0]), float(ptC[1]), float(ptC[2]) 153 | 154 | # pts is the central point 155 | vector1 = np.array([[x2-x1], [y2-y1], [z2-z1]]) 156 | vector2 = np.array([[x3-x1], [y3-y1], [z3-z1]]) 157 | 158 | mag1 = np.linalg.norm(vector1) 159 | mag2 = np.linalg.norm(vector2) 160 | 161 | dotProduct = (vector1[0]*vector2[0]) + (vector1[1]*vector2[1]) + (vector1[2]*vector2[2]) 162 | 163 | angle = np.degrees(np.arccos(dotProduct/(mag1*mag2))) 164 | 165 | return angle 166 | 167 | # main function - slope stability base shear parameters with class input 168 | ## Input file column legend 169 | ''' 170 | 1 = Mohr-Coulomb - [phi', c'] 171 | 2 = undrained - depth - [shear_max, shear_min, Su_top, diff_Su] 172 | 3 = undrained - datum - [shear_max, shear_min, Su_datum, diff_Su, z_datum] 173 | 4 = power curve - [P_atm, a, b] 174 | 5 = shear-normal user defined function - [fileName] 175 | unsaturated - [phi_b, aev, us_max] 176 | ''' 177 | def shearModel2cphi(materialClass, materialName, Z, Ztop, eff_normal_stress, matricSuction): 178 | #import math 179 | #import making_list_with_floats as makelist 180 | import numpy as np 181 | 182 | # materialClass takes input 183 | # class[name] = [modelType, inputPara] 184 | 185 | material = materialClass[materialName] 186 | modelType = material[0] 187 | inputPara = material[1] 188 | 189 | calcPhiC=[] 190 | #userShearNormal_mc=[] 191 | 192 | # Mohr-Coulomb Model 193 | if modelType in [1,10]: 194 | calcPhiC.append([inputPara[0], inputPara[1]]) 195 | 196 | # undrained - depth 197 | elif modelType in [2,20]: 198 | calcShear = inputPara[2] + inputPara[3]*(Ztop - Z) 199 | 200 | if calcShear < inputPara[1]: # lower than min shear 201 | calcShear = inputPara[1] 202 | if calcShear > inputPara[0]: # higher than max shear 203 | calcShear = inputPara[0] 204 | 205 | calcPhiC.append([0, calcShear]) 206 | 207 | # undrained - datum 208 | elif modelType in [3,30]: 209 | calcShear = inputPara[2] + inputPara[3]*abs(inputPara[4] - Z) 210 | 211 | if calcShear < inputPara[1]: # lower than min shear 212 | calcShear = inputPara[1] 213 | if calcShear > inputPara[0]: # higher than max shear 214 | calcShear = inputPara[0] 215 | 216 | calcPhiC.append([0, calcShear]) 217 | 218 | # power curve 219 | elif modelType in [4,40]: 220 | calcShear = inputPara[0]*inputPara[1]*(eff_normal_stress/inputPara[0])**inputPara[2] 221 | 222 | calcPhiC.append([0, calcShear]) 223 | 224 | # user defined shear-normal force 225 | elif modelType in [5,50]: 226 | 227 | userShearNormal = csv2list(inputPara[0]) 228 | 229 | for loopSN in range(len(userShearNormal)-1): 230 | if inputPara[1] <= userShearNormal[loopSN+1][0] and inputPara[1] >= userShearNormal[loopSN][0]: 231 | 232 | gradient = (userShearNormal[loopSN+1][1] - userShearNormal[loopSN][1])/(userShearNormal[loopSN+1][0] - userShearNormal[loopSN][0]) 233 | intercept = userShearNormal[loopSN][1] - gradient*userShearNormal[loopSN][0] 234 | #userShearNormal_mc.append([gradient, intercept]) 235 | 236 | calcShear = gradient*eff_normal_stress + intercept 237 | break 238 | 239 | elif inputPara[1] >= userShearNormal[len(userShearNormal)][0]: 240 | #print('out of range of nonlinear curve') 241 | calcShear = userShearNormal[len(userShearNormal)][1] 242 | break 243 | 244 | else: 245 | continue 246 | 247 | calcPhiC.append([0, calcShear]) 248 | 249 | # adding unsaturated strength 250 | if round(modelType/10) in [1,2,3,4,5]: 251 | if matricSuction >= inputPara[1]: 252 | unsatShearStrength = min([matricSuction, inputPara[2]])*np.tan(np.radians(inputPara[0])) 253 | calcPhiC[1] += unsatShearStrength 254 | 255 | return calcPhiC 256 | 257 | 258 | # return list of soil columns that is at the exterior 259 | def colIDExternal(analysisInput): 260 | import numpy as np 261 | 262 | idxList = np.arange(len(analysisInput)-1).tolist() 263 | idList = listAtColNum(analysisInput,0) # soil column ID number 264 | idList = [int(idx) for idx in idList] 265 | xList = sorted(np.unique(listAtColNum(analysisInput,1))) # unique list of x coordinates 266 | yList = sorted(np.unique(listAtColNum(analysisInput,2))) # unique list of y coordinates 267 | 268 | # sort soil columns into rows with same X coordinates 269 | XsortedIDList = [] 270 | XsortedIDXList = [] 271 | for xCoord in xList: 272 | tempX = [] 273 | tempIDX = [] 274 | for loopColID in idxList: 275 | if analysisInput[loopColID][1] == xCoord: 276 | tempX.append(idList[loopColID]) 277 | tempIDX.append(loopColID) 278 | idxList.remove(loopColID) 279 | 280 | XsortedIDList.append(tempX) 281 | XsortedIDXList.append(tempIDX) 282 | 283 | # take the exteriors from each row of soil columns 284 | extXsortedIDList = [] 285 | extXsortedIDXList = [] 286 | exposedSidesDict = {} 287 | 288 | for loopExt in range(len(XsortedIDList)): 289 | 290 | # first soil column of each column 291 | extXsortedIDList.append(XsortedIDList[loopExt][0]) 292 | extXsortedIDXList.append(XsortedIDXList[loopExt][0]) 293 | 294 | sideCheck1 = [[False]*4][0] 295 | sideCheck1[0] = True # side 1 is automatically open 296 | 297 | # side 2 298 | if yList[-1] == analysisInput[XsortedIDXList[loopExt][0]][2] or (XsortedIDList[loopExt][0]+1) not in idList: 299 | sideCheck1[1] = True # right most soil column - side 2 open 300 | 301 | # side 4 302 | if yList[0] == analysisInput[XsortedIDXList[loopExt][0]][2] or (XsortedIDList[loopExt][0]-1) not in idList: 303 | sideCheck1[3] = True # left most soil column - side 4 open 304 | 305 | exposedSidesDict[XsortedIDXList[loopExt][0]] = sideCheck1 306 | 307 | # last soil column of each column 308 | extXsortedIDList.append(XsortedIDList[loopExt][-1]) 309 | extXsortedIDXList.append(XsortedIDXList[loopExt][-1]) 310 | 311 | sideCheck2 = [[False]*4][0] 312 | sideCheck2[2] = True # side 3 is automatically open 313 | 314 | # side 2 315 | if yList[-1] == analysisInput[XsortedIDXList[loopExt][-1]][2] or (XsortedIDList[loopExt][-1]+1) not in idList: 316 | sideCheck2[1] = True # right most soil column - side 2 open 317 | 318 | # side 4 319 | if yList[0] == analysisInput[XsortedIDXList[loopExt][-1]][2] or (XsortedIDList[loopExt][-1]-1) not in idList: 320 | sideCheck2[3] = True # left most soil column - side 4 open 321 | 322 | exposedSidesDict[XsortedIDXList[loopExt][-1]] = sideCheck2 323 | 324 | return XsortedIDList, XsortedIDXList, extXsortedIDList, extXsortedIDXList, exposedSidesDict 325 | 326 | 327 | # Analysis_3D_HungrBishop1989_v4_06_28_2018.py 328 | def analysis3DHungrBishop1989(fileName, seismicK, centerPt0, materialClass, materialNameList, iterationNMax=200, tolFS=0.0005, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=None): 329 | # import libraries 330 | import numpy as np 331 | from scipy.stats import mode 332 | 333 | # take the inputfile and convert it into list 334 | analysisInput = csv2list(fileName) 335 | #print(analysisInput[0]) 336 | 337 | # seismic coefficient 338 | seismicKx = seismicK[0] 339 | seismicKy = seismicK[1] 340 | seismicKxy = np.sqrt(seismicKx**2 + seismicKy**2) 341 | 342 | ''' direction of column dip direction ''' 343 | if avDipDirectionB_user == None: 344 | dipDirectionList = listAtColNum(analysisInput, 18) 345 | avDipDirectionB, countN = mode(np.array(dipDirectionList),axis=None) 346 | 347 | if countN >= occuranceFactor*len(analysisInput): 348 | avDipDirectionB = round(float(avDipDirectionB),1) 349 | tolDirection = 0 350 | else: 351 | avDipDirectionB = round(float(np.mean(dipDirectionList)),1) 352 | if tolDirection_user == None: 353 | tolDirection = 10 354 | else: 355 | tolDirection = tolDirection_user 356 | else: 357 | avDipDirectionB = avDipDirectionB_user 358 | tolDirection = 0 359 | 360 | #print(avDipDirectionB) 361 | 362 | directionOfSlidingBList = making_float_list(avDipDirectionB-tolDirection, avDipDirectionB+tolDirection, spacingDirection) 363 | #directionOfSlidingPList = making_float_list(avDipDirectionP-tolDirection, avDipDirectionP+tolDirection, spacingDirection) 364 | 365 | #changeFS = 0.01 366 | 367 | ''' FS computation ''' 368 | FS_results = [] 369 | 370 | for dirLoop in range(len(directionOfSlidingBList)): 371 | 372 | iterationN = 1 373 | FSm_i = 3 #inital guess of FS 374 | 375 | # iterate through to find global 3D FS 376 | iterationFS = True 377 | while iterationFS: 378 | 379 | # calculating the FS 380 | FSmNu = 0 381 | #FSmDe = 0 382 | FSmDeWx = 0 383 | FSmDeNf = 0 384 | FSmDekWe = 0 385 | FSmDeEd = 0 386 | 387 | for loopCol in range(len(analysisInput)): 388 | #print(analysisInput[loopCol]) 389 | #print('columnID=%i'%loopCol) 390 | 391 | # base inclination 392 | # inclination of base relative to the positive x (right) and positive y (up) direction 393 | dipRad = np.radians(analysisInput[loopCol][17]) 394 | 395 | if analysisInput[loopCol][17] == 0: 396 | dipDirectionRad = np.radians(directionOfSlidingBList[dirLoop]) 397 | else: 398 | dipDirectionRad = np.radians(analysisInput[loopCol][18]) 399 | 400 | baseAngleXraw = np.arctan(np.sin(dipDirectionRad)*np.tan(dipRad)) 401 | baseAngleYraw = np.arctan(np.cos(dipDirectionRad)*np.tan(dipRad)) 402 | baseAngleX = abs(baseAngleXraw) 403 | baseAngleY = abs(baseAngleYraw) 404 | cosBaseAngleGamma = ((np.tan(baseAngleX))**2 + (np.tan(baseAngleY))**2 + 1)**(-0.5) 405 | #baseAngleX = abs(baseAngleXraw) 406 | #baseAngleY = abs(baseAngleYraw) 407 | 408 | # direction of sliding base inclination 409 | if analysisInput[loopCol][17] == 0: 410 | thetaDiff = 0 411 | else: 412 | thetaDiff = abs(directionOfSlidingBList[dirLoop]-analysisInput[loopCol][18]) 413 | 414 | dipSlidingDirectionRaw = np.arctan(np.tan(dipRad)*np.cos(np.radians(thetaDiff))) 415 | dipSlidingDirection = abs(dipSlidingDirectionRaw) 416 | 417 | # lever arm for moment analysis 418 | # find Ri and fi, which are distance of moment arm for shear strength and normal force 419 | RX = abs(centerPt0[0] - analysisInput[loopCol][1]) 420 | RY = abs(centerPt0[1] - analysisInput[loopCol][2]) 421 | RZ = abs(centerPt0[2] - analysisInput[loopCol][21]) 422 | #RmidZ = abs(centerPt0[2] - 0.5*(analysisInput[loopCol][20] + analysisInput[loopCol][21])) 423 | 424 | angleBearing = angleBtw3Pts([(centerPt0[0], centerPt0[1], 0), (analysisInput[loopCol][1], analysisInput[loopCol][2], 0), (centerPt0[0], 100+centerPt0[1], 0)])%180 425 | angleXi = np.radians(abs(angleBearing[0] - (directionOfSlidingBList[dirLoop]%180))) 426 | if angleXi < 0.5*np.pi: 427 | xi = np.sqrt(RX**2 + RY**2)*np.sin(angleXi) # horizontal distance of column weight from centerPt0 428 | else: 429 | xi = np.sqrt(RX**2 + RY**2)*np.cos(angleXi%(0.5*np.pi)) # horizontal distance of column weight from centerPt0 430 | 431 | # compute moment arm of Ri and fi 432 | #RiThetaXY = abs(np.degrees(np.atan(RZ/xi))) 433 | RR = np.sqrt(RX**2 + RY**2 + RZ**2) 434 | #RR = np.sqrt((RX**2 + RY**2 + RZ**2) - RY**2) 435 | deltaRangleXY = round(90 - (np.degrees(dipSlidingDirection) + abs(np.degrees(np.arctan(RZ/xi)))),2) 436 | 437 | Ri = RR*np.cos(np.radians(deltaRangleXY)) 438 | fi = RR*np.sin(np.radians(deltaRangleXY)) 439 | 440 | # base A 441 | baseA = (analysisInput[loopCol][14]/analysisInput[loopCol][16])#/np.cos(dipRad) 442 | 443 | Wi = analysisInput[loopCol][14] # soil column weight 444 | ui = analysisInput[loopCol][5] # pore-water pressure force 445 | matricSuction = analysisInput[loopCol][19] 446 | Ei = 0 # applied line load 447 | E_d = 0 # moment arm of applied line load 448 | 449 | # Shear strength - initial 450 | ci = analysisInput[loopCol][12] # base cohesion - Mohr Coloumb failure 451 | phiRad = np.radians(analysisInput[loopCol][13]) # base friction angle - Mohr Coloumb failure 452 | 453 | # Normal 454 | m_alpha = cosBaseAngleGamma + np.sin(dipSlidingDirection)*np.tan(phiRad)/FSm_i 455 | Ni = (Wi - (ci - ui*np.tan(phiRad))*(baseA*np.sin(dipSlidingDirection)/FSm_i))/m_alpha 456 | 457 | # change of phi and c with the new Ni 458 | if analysisInput[loopCol][26] in [4,5]: 459 | newShear = shearModel2cphi(materialClass, analysisInput[loopCol][27], 0, 0, (Ni/baseA - ui), matricSuction) 460 | 461 | ci = newShear[0][1] 462 | phiRad = np.radians(newShear[0][0]) 463 | 464 | # Moment equilibrium 465 | FSmNu += (ci*baseA + (Ni - ui*baseA)*np.tan(phiRad))*Ri 466 | FSmDeWx += Wi*xi 467 | FSmDeNf += Ni*fi*(cosBaseAngleGamma/np.cos(dipSlidingDirection)) 468 | FSmDekWe += seismicKxy*Wi*RZ 469 | FSmDeEd += Ei*E_d 470 | #FSmDe += Wi*xi - Ni*fi*(cosBaseAngleGamma/np.cos(dipSlidingDirection)) + seismicKxy*Wi*RmidZ + Ei*E_d 471 | 472 | # computed FS 473 | FS_c = FSmNu/(FSmDeWx - FSmDeNf + FSmDekWe + FSmDeEd) 474 | 475 | # compare computed and inital guess FS 476 | if iterationN >= iterationNMax: 477 | #print('too many iterations (iterationNN) - check code or increase maximum iteration number') 478 | iterationFS = False 479 | FSm_f = np.nan #'non-converging' 480 | FS_results.append([iterationN, directionOfSlidingBList[dirLoop], FSm_i, FS_c, FSm_f]) 481 | 482 | elif abs(FS_c-FSm_i) <= tolFS: 483 | 484 | ''' find decimal points of FS tolarance allowed ''' 485 | if tolFS >= 1: 486 | decimalPoint = 1 487 | elif tolFS < 0.0001: 488 | dpListed = list(str(tolFS)) 489 | idx = dpListed.index('-') 490 | dPstring = ''.join(dpListed[idx+1:]) 491 | decimalPoint = int(dPstring) 492 | else: 493 | decimalPoint = len(list(str(tolFS)))-2 494 | 495 | FSm_f = round(FS_c,decimalPoint+2) 496 | FS_results.append([iterationN, directionOfSlidingBList[dirLoop], FSm_i, FS_c, FSm_f]) 497 | iterationN = 0 498 | iterationFS = False 499 | else: 500 | FSm_f = np.nan #'non-converging' 501 | #FS_results.append([iterationN, directionOfSlidingBList[dirLoop], FSm_i, FS_c, FSm_f]) 502 | iterationN += 1 503 | FSm_i = FS_c 504 | #FSm_i -= changeFS 505 | 506 | 507 | if len(FS_results) > 1: 508 | FS_final_list = listAtColNum(FS_results,4) 509 | 510 | FS_final_list_min = min(FS_final_list) 511 | FS_final_list_min_IDX = FS_final_list.index(FS_final_list_min) 512 | FS_final_info = FS_results[FS_final_list_min_IDX] 513 | 514 | return FS_final_info #, FS_results#[-1] 515 | else: 516 | return FS_results 517 | 518 | # Analysis_3D_HungrJanbu1989_v4_06_28_2018.py 519 | def analysis3DHungrJanbu1989(fileName, seismicK, materialClass, materialNameList, correctFS=None, iterationNMax=200, tolFS=0.0005, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=None, sideResistance=True): 520 | # import libraries 521 | import numpy as np 522 | from scipy.stats import mode 523 | 524 | # take the inputfile and convert it into list 525 | analysisInput = csv2list(fileName) 526 | #print(analysisInput[0]) 527 | 528 | # seismic coefficient 529 | seismicKx = seismicK[0] 530 | seismicKy = seismicK[1] 531 | seismicKxy = np.sqrt(seismicKx**2 + seismicKy**2) 532 | 533 | if sideResistance == True: 534 | XsortedIDList, XsortedIDXList, extXsortedIDList, extXsortedIDXList, exposedSidesDict = colIDExternal(analysisInput) 535 | 536 | ''' direction of column dip direction ''' 537 | #directionOfSlidingBList, directionOfSlidingPList = findGenSldiingDirection3D(analysisInput, occuranceFactor, tolDirection, spacingDirection) 538 | if avDipDirectionB_user == None: 539 | dipDirectionList = listAtColNum(analysisInput, 18) 540 | avDipDirectionB, countN = mode(np.array(dipDirectionList),axis=None) 541 | 542 | if countN >= occuranceFactor*len(analysisInput): 543 | avDipDirectionB = round(float(avDipDirectionB),1) 544 | tolDirection = 0 545 | else: 546 | avDipDirectionB = round(float(np.mean(dipDirectionList)),1) 547 | if tolDirection_user == None: 548 | tolDirection = 10 549 | else: 550 | tolDirection = tolDirection_user 551 | else: 552 | avDipDirectionB = avDipDirectionB_user 553 | if tolDirection_user == None: 554 | tolDirection = 0 555 | else: 556 | tolDirection = tolDirection_user 557 | 558 | # find sliding direction based on dip and dip direction - polar direction 559 | #print(avDipDirectionB) 560 | avDipDirectionP = 0 561 | if avDipDirectionB < 0: 562 | avDipDirectionB = avDipDirectionB + 360 563 | 564 | if avDipDirectionB > 360: 565 | avDipDirectionB = avDipDirectionB%360 566 | 567 | if avDipDirectionB >= 0 and avDipDirectionB < 270: 568 | avDipDirectionP = 90-avDipDirectionB 569 | elif avDipDirectionB >= 270 and avDipDirectionB <= 360: 570 | avDipDirectionP = 450-avDipDirectionB 571 | 572 | #avDipDirectionP = (450-avDipDirectionB)%360 573 | 574 | # store information of sliding direction 575 | if avDipDirectionB_user != None: 576 | directionOfSlidingBList = [avDipDirectionB] 577 | directionOfSlidingPList = [avDipDirectionP] 578 | else: 579 | directionOfSlidingBList = making_float_list(avDipDirectionB-tolDirection, avDipDirectionB+tolDirection, spacingDirection) 580 | directionOfSlidingPList = making_float_list(avDipDirectionP-tolDirection, avDipDirectionP+tolDirection, spacingDirection) 581 | 582 | ''' FS computation ''' 583 | FS_results = [] 584 | 585 | for dirLoop in range(len(directionOfSlidingBList)): 586 | 587 | ''' Janbu Correction Factor ''' 588 | if correctFS == None: 589 | # factor b1 590 | sumPhiList = round(sum( listAtColNum(analysisInput,13)),2) 591 | sumCList = round(sum( listAtColNum(analysisInput,12)),2) 592 | if sumPhiList > 0 and sumCList > 0: 593 | b1 = 0.50 594 | elif sumPhiList > 0 and sumCList == 0: 595 | b1 = 0.31 596 | elif sumPhiList == 0 and sumCList > 0: 597 | b1 = 0.69 598 | 599 | # d and L factor 600 | 601 | Lx = abs(max( listAtColNum(analysisInput,1)) - min( listAtColNum(analysisInput,1)))/2 602 | Ly = abs(max( listAtColNum(analysisInput,2)) - min( listAtColNum(analysisInput,2)))/2 603 | 604 | L = 2*(Lx*Ly)/np.sqrt((Lx*np.sin(directionOfSlidingPList[dirLoop]))**2 + (Ly*np.cos(directionOfSlidingPList[dirLoop]))**2 ) 605 | 606 | dZList = [] 607 | for loopCol in range(len(analysisInput)): 608 | #baseDip = analysisInput[loopCol][17] 609 | 610 | dipRad = np.radians(analysisInput[loopCol][31]) 611 | if analysisInput[loopCol][31] == 0: 612 | thetaDiff = 0 613 | else: 614 | thetaDiff = abs(directionOfSlidingBList[dirLoop]-analysisInput[loopCol][32]) 615 | apparantDip = abs(np.arctan(np.tan(dipRad)*np.cos(np.radians(thetaDiff)))) 616 | 617 | dZ = abs(analysisInput[loopCol][21] - analysisInput[loopCol][20]) 618 | dZList.append(dZ*np.cos(np.radians(apparantDip))) 619 | d = max(dZList) 620 | 621 | ''' 622 | point1 = [newSliceN[min(sliceKeyList)][0], newSliceN[min(sliceKeyList)][1][0][0]] 623 | point2 = [newSliceN[max(sliceKeyList)][0], newSliceN[max(sliceKeyList)][3][0][0]] 624 | L_factor = np.sqrt((point1[1]-point2[1])**2 + (point1[0]-point2[0])**2) 625 | L_factor_gradient = (point1[1]-point2[1])/(point1[0]-point2[0]) 626 | L_factor_intercept = point1[1] - point1[0]*L_factor_gradient 627 | 628 | dList = [] 629 | for sliceN in sliceKeyList: 630 | point3 = [0.5*(newSliceN[sliceN][0]+newSliceN[sliceN][2]), 0.5*(newSliceN[sliceN][1][0][0]+newSliceN[sliceN][3][0][0])] 631 | 632 | tempX = (L_factor_intercept-point3[1]-(point3[0]/L_factor_gradient))/(-L_factor_gradient-(1/L_factor_gradient)) 633 | tempY = L_factor_gradient*tempX + L_factor_intercept 634 | 635 | tempDist = np.sqrt((point3[1]-tempY)**2 + (point3[0]-tempX)**2) 636 | dList.append(tempDist) 637 | d_factor = max(dList) 638 | ''' 639 | ''' 640 | Lx = abs(max( listAtColNum(analysisInput,1)) - min( listAtColNum(analysisInput,1))) 641 | Ly = abs(max( listAtColNum(analysisInput,2)) - min( listAtColNum(analysisInput,2))) 642 | Lxy = np.sqrt(Lx**2 + Ly**2) 643 | Llist = [Lx, Ly, Lxy] 644 | Lmin = min(Llist) 645 | Lindex = Llist.index(Lmin) 646 | Lz = abs(max( listAtColNum(analysisInput,20)) - min( listAtColNum(analysisInput,20))) 647 | LangleRad = np.arctan(Lz/Lmin) 648 | LangleDeg = np.degrees(np.arctan(Lz/Lmin)) 649 | L = np.sqrt(Lmin**2 + Lz**2) 650 | 651 | ZbottomList = listAtColNum(analysisInput,21) 652 | dZstart = min(ZbottomList) 653 | if Lindex == 0: 654 | dstart = min( listAtColNum(analysisInput,1)) 655 | dIDX = 1 656 | elif Lindex == 1: 657 | dstart = min( listAtColNum(analysisInput,2)) 658 | dIDX = 2 659 | elif Lindex == 2: 660 | dstartx = min( listAtColNum(analysisInput,1)) 661 | dstarty = min( listAtColNum(analysisInput,2)) 662 | dIDX = 3 663 | 664 | dList = [] 665 | for loopZBot in range(len(ZbottomList)): 666 | if dIDX in [1,2]: 667 | dLen = max(abs(analysisInput[loopZBot][dIDX] - dstart), 0.0001) 668 | elif dIDX == 3: 669 | dLen = max(np.sqrt((analysisInput[loopZBot][1] - dstartx)**2 + (analysisInput[loopZBot][2] - dstarty)**2), 0.0001) 670 | 671 | 672 | dZ = analysisInput[loopZBot][20] - dZstart 673 | dangleRad = LangleRad - np.arctan(dZ/dLen) 674 | 675 | dList.append(abs(dLen*np.sin(dangleRad))) 676 | d = max(dList) 677 | ''' 678 | correctionFactor = 1 + b1*((d/L) - 1.4*((d/L)**2)) 679 | #print('correction factor = %f'%correctionFactor) 680 | else: 681 | correctionFactor = correctFS 682 | 683 | iterationN = 1 684 | FS_i = 1 #inital guess of FS 685 | sumW = 0 686 | sumV = 0 687 | 688 | # iterate through to find global 3D FS 689 | iterationFS = True 690 | while iterationFS: 691 | 692 | FSNu = 0 693 | Qs = 0 694 | #FSDe = 0 695 | FSDeNcosa = 0 696 | FSDekW = 0 697 | FSDeE = 0 698 | 699 | for loopCol in range(len(analysisInput)): 700 | #print(analysisInput[loopCol]) 701 | #print('columnID=%i'%loopCol) 702 | 703 | # base inclination 704 | # inclination of base relative to the positive x (right) and positive y (up) direction 705 | dipRad = np.radians(analysisInput[loopCol][17]) 706 | 707 | if analysisInput[loopCol][17] == 0: 708 | dipDirectionRad = np.radians(directionOfSlidingBList[dirLoop]) 709 | else: 710 | dipDirectionRad = np.radians(analysisInput[loopCol][18]) 711 | 712 | #baseAngleX = np.radians(round(np.degrees(np.arctan(np.sin(dipDirectionRad)*np.tan(dipRad))),2)) 713 | #baseAngleY = np.radians(round(np.degrees(np.arctan(np.cos(dipDirectionRad)*np.tan(dipRad))),2)) 714 | baseAngleX = np.arctan(np.sin(dipDirectionRad)*np.tan(dipRad)) 715 | baseAngleY = np.arctan(np.cos(dipDirectionRad)*np.tan(dipRad)) 716 | baseAngleX = abs(baseAngleX) 717 | baseAngleY = abs(baseAngleY) 718 | cosBaseAngleGamma = np.cos(dipRad) #((np.tan(baseAngleX))**2 + (np.tan(baseAngleY))**2 + 1)**(-0.5) 719 | 720 | # direction of sliding base inclination 721 | if analysisInput[loopCol][17] == 0: 722 | thetaDiff = 0 723 | else: 724 | thetaDiff = abs(directionOfSlidingBList[dirLoop]-analysisInput[loopCol][18]) 725 | 726 | #print('thetaDiff=%f'%thetaDiff) 727 | dipSlidingDirection = abs(np.arctan(np.tan(dipRad)*np.cos(np.radians(thetaDiff)))) 728 | #print(thetaDiff) 729 | #print(dipSlidingDirection*180/np.pi) 730 | 731 | # base A 732 | baseA = (analysisInput[loopCol][14]/analysisInput[loopCol][16]) #/np.cos(dipRad) 733 | 734 | Wi = analysisInput[loopCol][14] # soil column weight 735 | sumW += Wi 736 | sumV += analysisInput[loopCol][15] 737 | ui = analysisInput[loopCol][5] # pore-water pressure 738 | matricSuction = analysisInput[loopCol][19] 739 | Ei = 0 # applied line load 740 | 741 | # Shear strength - initial 742 | ci = analysisInput[loopCol][12] # base cohesion - Mohr Coloumb failure 743 | phiRad = np.radians(analysisInput[loopCol][13]) # base friction angle - Mohr Coloumb failure 744 | 745 | # Normal 746 | m_alpha = cosBaseAngleGamma + np.sin(dipSlidingDirection)*np.tan(phiRad)/FS_i 747 | Ni = (Wi - (ci*baseA - ui*baseA*np.tan(phiRad))*(np.sin(dipSlidingDirection)/FS_i))/m_alpha 748 | 749 | # change of phi and c with the new Ni 750 | if analysisInput[loopCol][26] in [4,5]: 751 | newShear = shearModel2cphi(materialClass, materialNameList[analysisInput[loopCol][27]-1], 0, 0, (Ni/baseA - ui), matricSuction) 752 | 753 | ci = newShear[0][1] 754 | phiRad = np.radians(newShear[0][0]) 755 | 756 | # side resistance 757 | if sideResistance == True: 758 | sideA = 0 759 | if analysisInput[loopCol][0] in extXsortedIDXList: 760 | K0 = 1-np.sin(phiRad) 761 | Ka = (1-np.sin(phiRad))/(1+np.sin(phiRad)) 762 | K_tau = 0.5*(K0+Ka) 763 | c_im = K_tau*((Ni/baseA)-ui)*np.tan(phiRad) 764 | 765 | sideAreaExposed = exposedSidesDict[analysisInput[loopCol][0]] 766 | 767 | if (315 <= directionOfSlidingBList[dirLoop] <= 360) and (45 > directionOfSlidingBList[dirLoop] >= 0): 768 | if sideAreaExposed[1]: 769 | sideA += analysisInput[loopCol][23] 770 | if sideAreaExposed[3]: 771 | sideA += analysisInput[loopCol][25] 772 | 773 | elif 45 <= directionOfSlidingBList[dirLoop] < 135: 774 | if sideAreaExposed[0]: 775 | sideA += analysisInput[loopCol][22] 776 | if sideAreaExposed[2]: 777 | sideA += analysisInput[loopCol][24] 778 | 779 | elif 135 <= directionOfSlidingBList[dirLoop] < 225: 780 | if sideAreaExposed[1]: 781 | sideA += analysisInput[loopCol][23] 782 | if sideAreaExposed[3]: 783 | sideA += analysisInput[loopCol][25] 784 | 785 | elif 225 <= directionOfSlidingBList[dirLoop] < 315: 786 | if sideAreaExposed[0]: 787 | sideA += analysisInput[loopCol][22] 788 | if sideAreaExposed[2]: 789 | sideA += analysisInput[loopCol][24] 790 | 791 | Qs += c_im*sideA 792 | 793 | # force equilibrium 794 | FSNu += (ci*baseA + (Ni - ui*baseA)*np.tan(phiRad))*np.cos(dipSlidingDirection) 795 | #FSDe += Ni*cosBaseAngleGamma*np.tan(dipSlidingDirection) + seismicKxy*Wi + Ei 796 | FSDeNcosa += Ni*cosBaseAngleGamma*np.tan(dipSlidingDirection) 797 | FSDekW += seismicKxy*Wi 798 | FSDeE += Ei 799 | 800 | # computed FS 801 | FS_c = (Qs+FSNu)/(FSDeNcosa + FSDekW + FSDeE) 802 | 803 | # compare computed and inital guess FS 804 | if iterationN >= iterationNMax: 805 | #print('too many iterations (iterationNN) - check code or increase maximum iteration number') 806 | iterationFS = False 807 | FS_f = np.nan #'non-converging' 808 | FS_results.append([iterationN, directionOfSlidingBList[dirLoop], FS_i, FS_c, correctionFactor, FS_f]) 809 | elif abs(FS_c-FS_i) <= tolFS: 810 | 811 | ''' find decimal points of FS tolarance allowed ''' 812 | if tolFS >= 1: 813 | decimalPoint = 1 814 | elif tolFS < 0.0001: 815 | dpListed = list(str(tolFS)) 816 | idx = dpListed.index('-') 817 | dPstring = ''.join(dpListed[idx+1:]) 818 | decimalPoint = int(dPstring) 819 | else: 820 | decimalPoint = len(list(str(tolFS)))-2 821 | 822 | FS_f = round(FS_c*correctionFactor, decimalPoint+2) 823 | FS_results.append([iterationN, directionOfSlidingBList[dirLoop], FS_i, FS_c, correctionFactor, FS_f]) 824 | iterationN = 0 825 | iterationFS = False 826 | else: 827 | FS_f = np.nan #'non-converging' 828 | #FS_results.append([iterationN, directionOfSlidingBList[dirLoop], FS_i, FS_c, correctionFactor, FS_f]) 829 | iterationN += 1 830 | FS_i = FS_c 831 | #FS_i -= changeFS 832 | 833 | #print(sumW) 834 | #print(sumV) 835 | if len(FS_results) > 1: 836 | FS_final_list = listAtColNum(FS_results,5) 837 | 838 | FS_final_list_min = min(FS_final_list) 839 | FS_final_list_min_IDX = FS_final_list.index(FS_final_list_min) 840 | FS_final_info = FS_results[FS_final_list_min_IDX] 841 | 842 | return FS_final_info #, FS_results # None # FS_results[-1] 843 | else: 844 | return FS_results 845 | 846 | 847 | '''change the interslice angle Lambda based on the difference of FS''' 848 | 849 | def changeLambda3D(scaleLambdaXList, scaleLambdaYList, FS_List, tolaranceFS): 850 | from numpy import mean, nan 851 | from numpy.random import choice 852 | 853 | # create total number of change criteria based on decimal points 854 | if tolaranceFS >= 1: 855 | decimalPoint = 1 856 | elif tolaranceFS <= 0.0001: 857 | decimalPoint = 4 858 | tolaranceFS = 0.0001 859 | else: 860 | decimalPoint = len(list(str(tolaranceFS)))-2 861 | 862 | dFSLimList = [1] 863 | for loop1 in range(decimalPoint): 864 | if loop1 == decimalPoint-1: 865 | dFSLimList.append(tolaranceFS) 866 | #elif tolaranceFS >= 0.0001 and loop1 == decimalPoint-2: 867 | # dFSLimList.append(tolaranceFS*5) 868 | else: 869 | dFSLimList.append(0.1*float('1E-'+str(loop1))) 870 | 871 | # change the interslice force angle 872 | completeValueChangeSet = [1, 0.5, 0.1, 0.05] # [2, 1, 0.5, 0.1] # 873 | valueChangeList = completeValueChangeSet[:(decimalPoint)] 874 | 875 | # error condition 876 | if nan in FS_List[-1]: 877 | ''' 878 | randomNum = choice(range(100)) 879 | if (randomNum%2) == 0: # even number 880 | scaleLambdaXList.append(scaleLambdaXList[-1]) 881 | scaleLambdaYList.append(scaleLambdaYList[-1] + 0.1) 882 | else: # odd number 883 | scaleLambdaXList.append(scaleLambdaXList[-1] + 0.1) 884 | scaleLambdaYList.append(scaleLambdaYList[-1]) 885 | ''' 886 | if scaleLambdaXList[-1] >= scaleLambdaYList[-1]: 887 | scaleLambdaXList.append(scaleLambdaXList[-1]) 888 | scaleLambdaYList.append(scaleLambdaYList[-1] + 0.1) 889 | elif scaleLambdaXList[-1] < scaleLambdaYList[-1]: 890 | scaleLambdaXList.append(scaleLambdaXList[-1] + 0.1) 891 | scaleLambdaYList.append(scaleLambdaYList[-1]) 892 | 893 | return scaleLambdaXList, scaleLambdaYList 894 | 895 | # dFS - [FSmx_f, FSmy_f, FSx_f, FSy_f] 896 | dFS_m = abs(FS_List[-1][0] - FS_List[-1][1]) 897 | dFS_f = abs(FS_List[-1][2] - FS_List[-1][3]) 898 | 899 | if dFS_m > tolaranceFS and dFS_f > tolaranceFS: 900 | dFS_fm = (max(FS_List[-1][0:2]) - max(FS_List[-1][2:])) 901 | elif dFS_m <= tolaranceFS and dFS_f > tolaranceFS: 902 | dFS_fm = (mean(FS_List[-1][0:2]) - max(FS_List[-1][2:])) 903 | elif dFS_m > tolaranceFS and dFS_f <= tolaranceFS: 904 | dFS_fm = (max(FS_List[-1][0:2]) - mean(FS_List[-1][2:])) 905 | else: 906 | dFS_fm = (mean(FS_List[-1][0:2]) - mean(FS_List[-1][2:])) 907 | 908 | # changing Lambda higher or lower value 909 | absDiffFS = abs(dFS_fm) 910 | print(absDiffFS) 911 | 912 | for loop2 in range(decimalPoint): 913 | if absDiffFS <= tolaranceFS: 914 | valueChange = valueChangeList[-1] 915 | break 916 | elif absDiffFS <= dFSLimList[loop2] and absDiffFS > dFSLimList[loop2+1]: 917 | valueChange = valueChangeList[loop2] 918 | break 919 | else: 920 | valueChange = valueChangeList[-1] 921 | break 922 | 923 | # initial condition - no intercolumn force computed 924 | if len(scaleLambdaXList) == 1 and len(scaleLambdaYList) == 1: 925 | scaleLambdaXList.append(scaleLambdaXList[-1] + valueChange) 926 | scaleLambdaYList.append(scaleLambdaYList[-1]) 927 | 928 | # not initial condition 929 | else: 930 | if nan in FS_List[-2]: 931 | if scaleLambdaXList[-1] >= scaleLambdaYList[-1]: 932 | scaleLambdaXList.append(scaleLambdaXList[-1]) 933 | scaleLambdaYList.append(scaleLambdaYList[-1] + valueChange) 934 | elif scaleLambdaXList[-1] < scaleLambdaYList[-1]: 935 | scaleLambdaXList.append(scaleLambdaXList[-1] + valueChange) 936 | scaleLambdaYList.append(scaleLambdaYList[-1]) 937 | return scaleLambdaXList, scaleLambdaYList 938 | 939 | else: 940 | dFS_mO = abs(FS_List[-2][0] - FS_List[-2][1]) 941 | dFS_fO = abs(FS_List[-2][2] - FS_List[-2][3]) 942 | 943 | if dFS_mO > tolaranceFS and dFS_fO > tolaranceFS: 944 | dFS_fmO = (max(FS_List[-2][0:2]) - max(FS_List[-2][2:])) 945 | elif dFS_mO <= tolaranceFS and dFS_fO > tolaranceFS: 946 | dFS_fmO = (mean(FS_List[-2][0:2]) - max(FS_List[-2][2:])) 947 | elif dFS_mO > tolaranceFS and dFS_fO <= tolaranceFS: 948 | dFS_fmO = (max(FS_List[-2][0:2]) - mean(FS_List[-2][2:])) 949 | else: 950 | dFS_fmO = (mean(FS_List[-2][0:2]) - mean(FS_List[-2][2:])) 951 | 952 | absDiffFS_old = abs(dFS_fmO) 953 | print(absDiffFS_old) 954 | 955 | dlambX = scaleLambdaXList[-2] - scaleLambdaXList[-1] 956 | dlambY = scaleLambdaYList[-2] - scaleLambdaYList[-1] 957 | 958 | # deviation of FS due to lambda 959 | deviationCheck1 = ((dFS_mO <= tolaranceFS) and (dFS_m > tolaranceFS)) or ((dFS_fO <= tolaranceFS) and (dFS_f > tolaranceFS)) 960 | deviationCheck2 = ((dFS_m > 0.3) or (dFS_f > 0.3)) 961 | if deviationCheck1 or deviationCheck2: 962 | ''' 963 | if abs(scaleLambdaXList[-1]) >= abs(scaleLambdaYList[-1]): 964 | scaleLambdaXList.append(scaleLambdaXList[-1]) 965 | scaleLambdaYList.append(scaleLambdaXList[-1]) 966 | elif abs(scaleLambdaXList[-1]) < abs(scaleLambdaYList[-1]): 967 | scaleLambdaXList.append(scaleLambdaYList[-1]) 968 | scaleLambdaYList.append(scaleLambdaYList[-1]) 969 | ''' 970 | scaleLambdaXList.append(max([scaleLambdaYList[-1],scaleLambdaXList[-1]])) 971 | scaleLambdaYList.append(max([scaleLambdaYList[-1],scaleLambdaXList[-1]])) 972 | 973 | elif dlambX == 0 and dlambY != 0: 974 | # if changing lambdaY improves dFS change lambdaY, if not change lambdaX 975 | if absDiffFS_old < absDiffFS: 976 | scaleLambdaXList.append(scaleLambdaXList[-1]) 977 | scaleLambdaYList.append(scaleLambdaYList[-1] + valueChange) 978 | else: 979 | scaleLambdaXList.append(scaleLambdaXList[-1] + valueChange) 980 | scaleLambdaYList.append(scaleLambdaYList[-1]) 981 | 982 | # not initial condition 983 | elif dlambX != 0 and dlambY == 0: 984 | # if changing lambdaX improves dFS change lambdaX, if not change lambdaY 985 | if absDiffFS_old < absDiffFS: 986 | scaleLambdaXList.append(scaleLambdaXList[-1] + valueChange) 987 | scaleLambdaYList.append(scaleLambdaYList[-1]) 988 | else: 989 | scaleLambdaXList.append(scaleLambdaXList[-1]) 990 | scaleLambdaYList.append(scaleLambdaYList[-1] + valueChange) 991 | 992 | return scaleLambdaXList, scaleLambdaYList 993 | 994 | ''' 995 | method - 3D analysis method used: 996 | 1 = morgenstern-price -> half-sine function 997 | 2 = spencer 998 | 3 = bishop 999 | 4 = janbu 1000 | ''' 1001 | # intial values of sliding direction 1002 | def analysis3DChengnYip2007_initialSlidingDir(avDipDirectionB_user, occuranceFactor, analysisInput, spacingDirection, tolDirection_user): 1003 | import numpy as np 1004 | from scipy.stats import mode 1005 | 1006 | # find sliding direction based on dip and dip direction - bearing direction 1007 | if avDipDirectionB_user == None: 1008 | dipDirectionList = listAtColNum(analysisInput, 18) 1009 | avDipDirectionB, countN = mode(np.array(dipDirectionList),axis=None) 1010 | 1011 | if countN >= occuranceFactor*len(analysisInput): 1012 | avDipDirectionB = round(float(avDipDirectionB)*2)/2 #round to nearest 0.5 1013 | tolDirection = 0 1014 | else: 1015 | avDipDirectionB = round(float(np.mean(dipDirectionList))*2)/2 #round to nearest 0.5 1016 | if tolDirection_user == None: 1017 | tolDirection = 5 1018 | else: 1019 | tolDirection = tolDirection_user 1020 | else: 1021 | avDipDirectionB = avDipDirectionB_user 1022 | if tolDirection_user == None: 1023 | tolDirection = 0 1024 | else: 1025 | tolDirection = tolDirection_user 1026 | 1027 | # find sliding direction based on dip and dip direction - polar direction 1028 | #print(avDipDirectionB) 1029 | avDipDirectionP = 0 1030 | if avDipDirectionB < 0: 1031 | avDipDirectionB = avDipDirectionB + 360 1032 | 1033 | if avDipDirectionB > 360: 1034 | avDipDirectionB = avDipDirectionB%360 1035 | 1036 | if avDipDirectionB >= 0 and avDipDirectionB < 270: 1037 | avDipDirectionP = 90-avDipDirectionB 1038 | elif avDipDirectionB >= 270 and avDipDirectionB <= 360: 1039 | avDipDirectionP = 450-avDipDirectionB 1040 | 1041 | #avDipDirectionP = (450-avDipDirectionB)%360 1042 | 1043 | # store information of sliding direction 1044 | if avDipDirectionB_user != None: 1045 | directionOfSlidingBList = [avDipDirectionB] 1046 | directionOfSlidingPList = [avDipDirectionP] 1047 | else: 1048 | directionOfSlidingBList = making_float_list(avDipDirectionB-tolDirection, avDipDirectionB+tolDirection, spacingDirection) 1049 | directionOfSlidingPList = making_float_list(avDipDirectionP-tolDirection, avDipDirectionP+tolDirection, spacingDirection) 1050 | 1051 | # find shearing direction, i.e. opposite direction of sliding direction 1052 | #directionOfShearBList = [] 1053 | directionOfShearPList = [] 1054 | for dirSlBLoop in range(len(directionOfSlidingBList)): 1055 | shearDB = (directionOfSlidingBList[dirSlBLoop] + 180)%360 1056 | 1057 | if shearDB >= 0 and shearDB < 270: 1058 | shearDP = 90-shearDB 1059 | elif shearDB >= 270 and shearDB <= 360: 1060 | shearDP = 450-shearDB 1061 | 1062 | #directionOfShearBList.append(shearDB) 1063 | directionOfShearPList.append(shearDP) 1064 | 1065 | return directionOfSlidingBList, directionOfSlidingPList, directionOfShearPList #,directionOfShearBList 1066 | 1067 | # function to calculate corrected Janbu FS factors 1068 | def analysis3DChengnYip2007_correctFSfactor(correctFS, analysisInput, slidingDiP, slidingDiB): 1069 | import numpy as np 1070 | 1071 | if correctFS == None: 1072 | # factor b1 1073 | sumPhiList = round(sum( listAtColNum(analysisInput,13)),2) 1074 | sumCList = round(sum( listAtColNum(analysisInput,12)),2) 1075 | if sumPhiList > 0 and sumCList > 0: 1076 | b1 = 0.5 1077 | elif sumPhiList > 0 and sumCList == 0: 1078 | b1 = 0.31 1079 | elif sumPhiList == 0 and sumCList > 0: 1080 | b1 = 0.69 1081 | 1082 | # d and L factor 1083 | #xxx = listAtColNum(analysisInput,1) 1084 | #yyy = listAtColNum(analysisInput,2) 1085 | #print([xxx, yyy]) 1086 | 1087 | Lx = abs(max( listAtColNum(analysisInput,1)) - min( listAtColNum(analysisInput,1)))/2 1088 | Ly = abs(max( listAtColNum(analysisInput,2)) - min( listAtColNum(analysisInput,2)))/2 1089 | 1090 | L = 2*(Lx*Ly)/np.sqrt((Ly*np.cos(slidingDiP))**2 + (Lx*np.sin(slidingDiP))**2 ) 1091 | 1092 | dZList = [] 1093 | for loopCol in range(len(analysisInput)): 1094 | #baseDip = analysisInput[loopCol][17] 1095 | 1096 | dipRad = np.radians(analysisInput[loopCol][31]) 1097 | if analysisInput[loopCol][31] == 0: 1098 | thetaDiff = 0 1099 | else: 1100 | thetaDiff = abs(slidingDiB-analysisInput[loopCol][32]) 1101 | apparantDip = abs(np.arctan(np.tan(dipRad)*np.cos(np.radians(thetaDiff)))) 1102 | 1103 | dZ = abs(analysisInput[loopCol][21] - analysisInput[loopCol][20]) 1104 | dZList.append(dZ*np.cos(np.radians(apparantDip))) 1105 | d = max(dZList) 1106 | 1107 | #print(Lx, Ly, slidingDiP, L, d) 1108 | 1109 | ''' 1110 | Lx = abs(max( listAtColNum(analysisInput,1)) - min( listAtColNum(analysisInput,1))) 1111 | Ly = abs(max( listAtColNum(analysisInput,2)) - min( listAtColNum(analysisInput,2))) 1112 | Lxy = np.sqrt(Lx**2 + Ly**2) 1113 | Llist = [Lx, Ly, Lxy] 1114 | Lmin = min(Llist) 1115 | Lindex = Llist.index(Lmin) 1116 | Lz = abs(max( listAtColNum(analysisInput,20)) - min( listAtColNum(analysisInput,21))) 1117 | LangleRad = np.arctan(Lz/Lmin) 1118 | LangleDeg = np.degrees(np.arctan(Lz/Lmin)) 1119 | L = np.sqrt(Lmin**2 + Lz**2) 1120 | 1121 | print([Lx, Ly, Lxy, Lmin, Lz, LangleRad, LangleDeg, L]) 1122 | print(b1) 1123 | 1124 | ZbottomList = listAtColNum(analysisInput,21) 1125 | dZstart = min(ZbottomList) 1126 | if Lindex == 0: 1127 | dstart = min( listAtColNum(analysisInput,1)) 1128 | dIDX = 1 1129 | elif Lindex == 1: 1130 | dstart = min( listAtColNum(analysisInput,2)) 1131 | dIDX = 2 1132 | elif Lindex == 2: 1133 | dstartx = min( listAtColNum(analysisInput,1)) 1134 | dstarty = min( listAtColNum(analysisInput,2)) 1135 | dIDX = 3 1136 | 1137 | dList = [] 1138 | for loopZBot in range(len(ZbottomList)): 1139 | if dIDX in [1,2]: 1140 | dLen = max(abs(analysisInput[loopZBot][dIDX] - dstart), 0.0001) 1141 | elif dIDX == 3: 1142 | dLen = max(np.sqrt((analysisInput[loopZBot][1] - dstartx)**2 + (analysisInput[loopZBot][2] - dstarty)**2), 0.0001) 1143 | 1144 | dZ = analysisInput[loopZBot][20] - dZstart 1145 | dangleRad = LangleRad - np.arctan(dZ/dLen) 1146 | 1147 | dList.append(abs(dLen*np.sin(dangleRad))) 1148 | d = max(dList) 1149 | correctionFactor = 1 + b1*((d/L) - 1.4*((d/L)**2)) 1150 | ''' 1151 | correctionFactor = 1 + b1*((d/L) - 1.4*((d/L)**2)) 1152 | #print('correction factor = %f'%correctionFactor) 1153 | else: 1154 | correctionFactor = correctFS 1155 | 1156 | return correctionFactor 1157 | 1158 | def analysis3DChengnYip2007(fileName, seismicK, centerPt0, method, materialClass, lambdaIteration=None, iterationNMax=100, tolFS=0.001, correctFS=None, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=None): 1159 | # import libraries 1160 | import numpy as np 1161 | 1162 | # take the inputfile and convert it into list 1163 | analysisInput = csv2list(fileName) 1164 | #print(analysisInput[0]) 1165 | 1166 | # seismic coefficient 1167 | seismicKx = seismicK[0] 1168 | seismicKy = seismicK[1] 1169 | 1170 | ''' direction of column dip direction ''' 1171 | directionOfSlidingBList, directionOfSlidingPList, directionOfShearPList = analysis3DChengnYip2007_initialSlidingDir(avDipDirectionB_user, occuranceFactor, analysisInput, spacingDirection, tolDirection_user) 1172 | 1173 | #changeFS = 0.005 1174 | #changeFS = 0.01 1175 | changeLambda = 0.1 1176 | 1177 | FS_results = [] 1178 | loopFS = int(0) 1179 | 1180 | iterationN_a = 0 1181 | iterationN_FS = 0 1182 | 1183 | FSg_cur = np.nan 1184 | FSg_IDX = np.nan 1185 | 1186 | # iterate through sliding direction 1187 | for loopSDir in range(len(directionOfSlidingBList)): 1188 | #print(directionOfSlidingBList[loopSDir]) 1189 | shearDirectionRadP = np.radians(directionOfShearPList[loopSDir]) 1190 | slidingDirection = directionOfSlidingBList[loopSDir] 1191 | slidingDirectionP = directionOfSlidingPList[loopSDir] 1192 | 1193 | # intercolumn function 1194 | if method == 4: # simplified Janbu method 1195 | Fxy = 0 # intercoloum function 1196 | lambdaXY = 0 # horizontal direction intercoloum force scaling factor 1197 | scaleLambdaXList = [0] # making_float_list(-1, 3, 0.05) 1198 | scaleLambdaYList = [0] # making_float_list(-1, 3, 0.05) 1199 | correctionFactor = analysis3DChengnYip2007_correctFSfactor(correctFS, analysisInput, slidingDirectionP, slidingDirection) 1200 | elif method == 3: # simplified bishop method 1201 | Fxy = 0 # intercoloum function 1202 | lambdaXY = 0 # horizontal direction intercoloum force scaling factor 1203 | scaleLambdaXList = [0] # making_float_list(-1, 3, 0.05) 1204 | scaleLambdaYList = [0] # making_float_list(-1, 3, 0.05) 1205 | elif method == 2: # spencer method 1206 | Fxy = 1 # intercoloum function 1207 | lambdaXY = 0 # horizontal direction intercoloum force scaling factor 1208 | if lambdaIteration == None: 1209 | scaleLambdaXList = [0] #[-1] 1210 | scaleLambdaYList = [0] #[-1] 1211 | elif lambdaIteration != None: 1212 | scaleLambdaXList = [lambdaIteration] 1213 | scaleLambdaYList = [lambdaIteration] 1214 | elif method == 1: # Morgenstern-Price method 1215 | lambdaXY = 0 # horizontal direction intercoloum force scaling factor 1216 | if lambdaIteration == None: 1217 | scaleLambdaXList = [0] #[-1] 1218 | scaleLambdaYList = [0] #[-1] 1219 | elif lambdaIteration != None: 1220 | scaleLambdaXList = [lambdaIteration] 1221 | scaleLambdaYList = [lambdaIteration] 1222 | 1223 | angleDatas = [] # store information of base angles for a given direction of sliding 1224 | fVectorDatas = [] # store information of unit vector of shear, i.e. [f1, f2, f3], for a given direction of sliding 1225 | gVectorDatas = [] # store information of unit vector of normal, i.e. [g1, g2, g3], for a given direction of sliding 1226 | dExDatas = [] 1227 | dEyDatas = [] 1228 | QDatas = [] 1229 | 1230 | FS_results_Temp = [] 1231 | tempFSforceList = [] 1232 | tempFSmomentList = [] 1233 | 1234 | # iterate through intercolumn scaling factors for x 1235 | iterationLambda = True 1236 | while iterationLambda: 1237 | 1238 | #final computed of FS 1239 | FSx_f = 0 1240 | FSy_f = 0 1241 | FSmx_f = 0 1242 | FSmy_f = 0 1243 | 1244 | #inital trial of FS 1245 | FSx_i = 1 1246 | FSy_i = 1 1247 | FSmx_i = 1 1248 | FSmy_i = 1 1249 | 1250 | # iterate through to find global 3D FS 1251 | iterationFS = True 1252 | counts = 0 1253 | while iterationFS: 1254 | 1255 | # calculating the FS 1256 | 1257 | FSxNu = 0 1258 | #FSxDe = 0 1259 | FSxDeAg1 = 0 1260 | FSxDeQx = 0 1261 | FSxDekxW = 0 1262 | FSxDeDHx = 0 1263 | 1264 | FSyNu = 0 1265 | #FSyDe = 0 1266 | FSyDeAg2 = 0 1267 | FSyDeQy = 0 1268 | FSyDekyW = 0 1269 | FSyDeDHy = 0 1270 | 1271 | FSmxNu = 0 1272 | #FSmxDe = 0 1273 | FSmxDeWRY = 0 1274 | FSmxDeKyWRZ = 0 1275 | FSmxDeNig2RZ = 0 1276 | FSmxDeNig3RY = 0 1277 | FSmxDeQmx = 0 1278 | 1279 | FSmyNu = 0 1280 | #FSmyDe = 0 1281 | FSmyDeWRx = 0 1282 | FSmyDeKxWRZ = 0 1283 | FSmyDeNig2RZ = 0 1284 | FSmyDeNig3RX = 0 1285 | FSmyDeQmy = 0 1286 | 1287 | for loopCol in range(len(analysisInput)): 1288 | #print(analysisInput[loopCol]) 1289 | 1290 | if iterationN_FS == 0: 1291 | # base inclination 1292 | # inclination of base relative to the positive x (right) and positive y (up) direction 1293 | dipRad = np.radians(analysisInput[loopCol][17]) 1294 | if analysisInput[loopCol][17] == 0: 1295 | dipDirectionRad = np.radians(directionOfSlidingBList[loopSDir]) 1296 | else: 1297 | dipDirectionRad = np.radians(analysisInput[loopCol][18]) 1298 | baseAngleX = abs(np.arctan(np.sin(dipDirectionRad)*np.tan(dipRad))) 1299 | baseAngleY = abs(np.arctan(np.cos(dipDirectionRad)*np.tan(dipRad))) 1300 | 1301 | angleDatas.append([shearDirectionRadP, loopCol, baseAngleX, baseAngleY]) 1302 | 1303 | if analysisInput[loopCol][17] == 0: 1304 | thetaDiff_f = abs(slidingDirection-directionOfSlidingBList[loopSDir]) 1305 | else: 1306 | thetaDiff_f = abs(slidingDirection-analysisInput[loopCol][18]) 1307 | baseAngleSliding_f = abs(np.arctan(np.tan(dipRad)*np.cos(np.radians(thetaDiff_f)))) 1308 | 1309 | f1 = -np.cos(baseAngleSliding_f)*np.sin(np.radians(slidingDirection)) 1310 | f2 = -np.cos(baseAngleSliding_f)*np.cos(np.radians(slidingDirection)) 1311 | f3 = np.sin(baseAngleSliding_f) 1312 | 1313 | fVectorDatas.append([f1,f2,f3]) 1314 | 1315 | # unit vectors for normal force (N) 1316 | 1317 | J = np.sqrt((np.tan(baseAngleX))**2 + (np.tan(baseAngleY))**2 + 1) 1318 | g1 = np.tan(baseAngleX)/J 1319 | g2 = np.tan(baseAngleY)/J 1320 | g3 = 1/J 1321 | #g_check = g1**2 + g2**2 + g3**2 1322 | #print([loopCol, g1, g2, g3, g_check]) 1323 | ''' 1324 | dipRad_g = 0.5*np.pi - dipRad 1325 | g1 = -np.cos(dipRad_g)*np.cos(np.radians(dipDirectionRad)) 1326 | g2 = -np.cos(dipRad_g)*np.sin(np.radians(dipDirectionRad)) 1327 | g3 = np.sin(dipRad_g) 1328 | ''' 1329 | gVectorDatas.append([g1,g2,g3]) 1330 | 1331 | # intercolumn force 1332 | dEx = 0 1333 | dEy = 0 1334 | dExDatas.append(dEx) 1335 | dEyDatas.append(dEy) 1336 | 1337 | # externally applied forces and moments 1338 | Qxi = 0 1339 | Qyi = 0 1340 | Qzi = 0 1341 | Qmx = 0 1342 | Qmy = 0 1343 | Qmz = 0 1344 | Qmz_local = 0 1345 | QDatas.append([Qxi, Qyi, Qzi, Qmx, Qmy, Qmz, Qmz_local]) 1346 | 1347 | else: 1348 | baseAngleX = angleDatas[loopCol][2] 1349 | baseAngleY = angleDatas[loopCol][3] 1350 | #baseAngleTheta = angleDatas[loopCol][4] 1351 | #baseAngleSliding = angleDatas[loopCol][5] 1352 | 1353 | f1 = fVectorDatas[loopCol][0] 1354 | f2 = fVectorDatas[loopCol][1] 1355 | f3 = fVectorDatas[loopCol][2] 1356 | 1357 | g1 = gVectorDatas[loopCol][0] 1358 | g2 = gVectorDatas[loopCol][1] 1359 | g3 = gVectorDatas[loopCol][2] 1360 | 1361 | if method in [3,4]: 1362 | dEx = 0 1363 | dEy = 0 1364 | elif method in [1,2]: 1365 | dEx = dExDatas[loopCol] 1366 | dEy = dEyDatas[loopCol] 1367 | 1368 | Qxi = QDatas[loopCol][0] 1369 | Qyi = QDatas[loopCol][1] 1370 | Qzi = QDatas[loopCol][2] 1371 | Qmx = QDatas[loopCol][3] 1372 | Qmy = QDatas[loopCol][4] 1373 | Qmz = QDatas[loopCol][5] 1374 | Qmz_local = QDatas[loopCol][6] 1375 | 1376 | 1377 | # base area 1378 | baseA = (analysisInput[loopCol][14]/analysisInput[loopCol][16])#/np.cos(dipRad) 1379 | #columnWidth = np.sqrt(baseArea) 1380 | 1381 | # forces 1382 | Ui = baseA*analysisInput[loopCol][5] 1383 | matricSuction = analysisInput[loopCol][19] 1384 | Wi = analysisInput[loopCol][14] 1385 | 1386 | # inital strength 1387 | Ci = baseA*analysisInput[loopCol][12] 1388 | phiRad = np.radians(analysisInput[loopCol][13]) 1389 | 1390 | # intercolumn forces 1391 | lambdaX = scaleLambdaXList[-1] 1392 | lambdaY = scaleLambdaYList[-1] 1393 | dHx = Fxy*lambdaX*dEx 1394 | dHy = Fxy*lambdaY*dEy 1395 | #dXx = Fxy*lambdaXY*dEx 1396 | #dXy = Fxy*lambdaXY*dEy 1397 | #print([dEx, dEy, dHx, dHy, dXx, dXy]) 1398 | 1399 | # Shear Force coefficients based on vertical equilibrium (\Sum(Fv) = 0) 1400 | Ai = (lambdaX*dEx + lambdaY*dEy + Wi + Qzi)/g3 1401 | Bi = -f3/g3 1402 | 1403 | # new normal force 1404 | Si_mx = (Ci + (Ai - Ui)*np.tan(phiRad))/(FSmx_i-(Bi*np.tan(phiRad))) 1405 | Si_my = (Ci + (Ai - Ui)*np.tan(phiRad))/(FSmy_i-(Bi*np.tan(phiRad))) 1406 | 1407 | Ni_mx = Ai + Bi*Si_mx 1408 | Ni_my = Ai + Bi*Si_my 1409 | 1410 | # change of phi and c with the new Ni 1411 | if analysisInput[loopCol][26] in [4,5]: 1412 | Ni = 0.5*(Ni_my+Ni_mx) 1413 | newShear = shearModel2cphi(materialClass, analysisInput[loopCol][27], 0, 0, (Ni/baseA - Ui/baseA), matricSuction) 1414 | 1415 | Ci = baseA*newShear[0][1] 1416 | phiRad = np.radians(newShear[0][0]) 1417 | 1418 | ''' 1419 | print('columnID=%i'%loopCol) 1420 | print('Ai = %f'%Ai) 1421 | print('Bi = %f'%Bi) 1422 | ''' 1423 | # Janbu's method - force equilibrium method 1424 | if method in [1,2,4]: 1425 | 1426 | # Force equilibrium - X direction 1427 | Axi = (Ci + (Ai - Ui)*np.tan(phiRad))/(1-(Bi*np.tan(phiRad)/FSx_i)) 1428 | FSxNu += Axi*(f1-(Bi*g1)) 1429 | #FSxDe += Ai*g1 - Qxi + seismicKx*Wi - dHx + dEx 1430 | FSxDeAg1 += Ai*g1 1431 | FSxDeQx += Qxi 1432 | FSxDekxW += seismicKx*Wi 1433 | FSxDeDHx += dHx 1434 | #print([Axi, Axi*(f1-Bi*g1), Ai*g1 - Qxi + seismicKx*Wi - dHx + dEx]) 1435 | 1436 | # Force equilibrium - Y direction 1437 | Ayi = (Ci + (Ai - Ui)*np.tan(phiRad))/(1-(Bi*np.tan(phiRad)/FSy_i)) 1438 | FSyNu += Ayi*(f2-(Bi*g2)) 1439 | #FSyDe += Ai*g2 - Qyi + seismicKy*Wi - dHy + dEy 1440 | FSyDeAg2 += Ai*g2 1441 | FSyDeQy += Qyi 1442 | FSyDekyW += seismicKy*Wi 1443 | FSyDeDHy += dHy 1444 | #print([Ayi, Ayi*(f2-Bi*g2), Ai*g2 - Qyi + seismicKy*Wi - dHy + dEy]) 1445 | 1446 | 1447 | if method in [1,2,3]: 1448 | # lever arm for moment analysis 1449 | RX = abs(centerPt0[0] - analysisInput[loopCol][1]) 1450 | RY = abs(centerPt0[1] - analysisInput[loopCol][2]) 1451 | #RZ = abs(centerPt0[2] - 0.5*(analysisInput[loopCol][20] + analysisInput[loopCol][21])) 1452 | RZ = abs(centerPt0[2] - analysisInput[loopCol][21]) 1453 | 1454 | Si_mx = (Ci + (Ai - Ui)*np.tan(phiRad))/(FSmx_i-(Bi*np.tan(phiRad))) 1455 | Si_my = (Ci + (Ai - Ui)*np.tan(phiRad))/(FSmy_i-(Bi*np.tan(phiRad))) 1456 | 1457 | Ni_mx = Ai + Bi*Si_mx 1458 | Ni_my = Ai + Bi*Si_my 1459 | 1460 | # Moment equilibrium - XX 1461 | Kmxi = (Ci + (Ai - Ui)*np.tan(phiRad))/(1-(Bi*np.tan(phiRad)/FSmx_i)) 1462 | FSmxNu += Kmxi*(f2*RZ+f3*RY) 1463 | #FSmxDe += Wi*(RY + seismicKy*RZ) + Ni_mx*(g2*RZ - g3*RY) + Qmx 1464 | FSmxDeWRY += Wi*RY 1465 | FSmxDeKyWRZ += Wi*seismicKy*RZ 1466 | FSmxDeNig2RZ += Ni_mx*g2*RZ 1467 | FSmxDeNig3RY += Ni_mx*g3*RY 1468 | FSmxDeQmx += Qmx 1469 | 1470 | # Moment equilibrium - YY 1471 | Kmyi = (Ci + (Ai - Ui)*np.tan(phiRad))/(1-(Bi*np.tan(phiRad)/FSmy_i)) 1472 | FSmyNu += Kmyi*(f1*RZ+f3*RX) 1473 | #FSmyDe += Wi*(RX + seismicKx*RZ) + Ni_my*(g2*RZ - g3*RX) + Qmy 1474 | FSmyDeWRx += Wi*RX 1475 | FSmyDeKxWRZ += Wi*seismicKx*RZ 1476 | FSmyDeNig2RZ += Ni_my*g2*RZ 1477 | FSmyDeNig3RX += Ni_my*g3*RX 1478 | FSmyDeQmy += Qmy 1479 | 1480 | ''' 1481 | # Force equilibrium - X direction 1482 | Kxi = (Ci + (((Wi + Qzi)/g3) - Ui)*np.tan(phiRad))/(1 + (f3*np.tan(phiRad))/(g3*FSmx_i)) 1483 | FSmxNu += Kxi*(f2*RZ + f3*RY) 1484 | FSmxDe += (Wi + Qzi)*RY + Ni_mx*(g2*RZ - g3*RY) 1485 | #print([Axi, Axi*(f1+(f3*g1)/g3), (g1/g3)*(Wi + Qzi)]) 1486 | 1487 | # Force equilibrium - Y direction 1488 | Kyi = (Ci + (((Wi + Qzi)/g3) - Ui)*np.tan(phiRad))/(1 + (f3*np.tan(phiRad))/(g3*FSmy_i)) 1489 | FSmyNu += Kyi*(f1*RZ + f3*RX) 1490 | FSmyDe += (Wi + Qzi)*RX + Ni_my*(g1*RZ - g3*RX) 1491 | #print([Ayi, Ayi*(f1+(f3*g2)/g3), (g2/g3)*(Wi + Qzi)]) 1492 | ''' 1493 | ''' 1494 | print(iterationN) 1495 | print(iterationN_FS) 1496 | print(slidingDirection_i) 1497 | ''' 1498 | 1499 | # calculate 3D FS for each equilibrium 1500 | if method in [1,2,4]: 1501 | FSx = FSxNu/(FSxDeAg1 - FSxDeQx + FSxDekxW - FSxDeDHx) 1502 | FSy = FSyNu/(FSyDeAg2 - FSyDeQy + FSyDekyW - FSyDeDHy) 1503 | 1504 | if method in [1,2,3]: 1505 | FSmx = FSmxNu/(FSmxDeWRY + FSmxDeKyWRZ + FSmxDeNig2RZ - FSmxDeNig3RY + FSmxDeQmx) 1506 | FSmy = FSmyNu/(FSmyDeWRx + FSmyDeKxWRZ + FSmyDeNig2RZ - FSmyDeNig3RX + FSmyDeQmy) 1507 | 1508 | # compare computed and inital guess FS 1509 | checkForceFS = 0 1510 | checkMomentFS = 0 1511 | 1512 | # Janbu 1513 | if method == 4: 1514 | if abs(FSx-FSx_i) <= tolFS and abs(FSy-FSy_i) <= tolFS: 1515 | FSx_f = FSx 1516 | FSy_f = FSy 1517 | checkForceFS = 1 1518 | elif abs(FSx-FSx_i) <= tolFS and abs(FSy-FSy_i) > tolFS: 1519 | iterationN_FS += 1 1520 | FSx_f = FSx 1521 | FSy_i = FSy 1522 | #FSy_i -= changeFS 1523 | elif abs(FSx-FSx_i) > tolFS and abs(FSy-FSy_i) <= tolFS: 1524 | iterationN_FS += 1 1525 | #FSx_i -= changeFS 1526 | FSx_i = FSx 1527 | FSy_f = FSy 1528 | else: 1529 | iterationN_FS += 1 1530 | #FSx_i -= changeFS 1531 | #FSy_i -= changeFS 1532 | FSx_i = FSx 1533 | FSy_i = FSy 1534 | 1535 | if counts >= iterationNMax: 1536 | print('too many iterations (iterationNN) - check code or increase maximum iteration number') 1537 | # take failed result for method 3 or 4 1538 | FS_results.append([4, iterationN_a, iterationN_FS, slidingDirection, 0, 0, 0, np.nan, np.nan, np.nan, np.nan, np.nan]) 1539 | counts = 0 1540 | iterationN_FS = 0 1541 | iterationLambda = False 1542 | iterationFS = False 1543 | #FS_final = 0.5*(FS_force_f+FS_moment_f) 1544 | else: 1545 | if checkForceFS != 0: 1546 | FS_results.append([4, iterationN_a, iterationN_FS, slidingDirection, 0, 0, 0, np.nan, np.nan, FSx_f, FSy_f, np.nan]) 1547 | counts = 0 1548 | iterationN_FS = 0 1549 | iterationLambda = False 1550 | iterationFS = False 1551 | 1552 | counts += 1 1553 | 1554 | ''' 1555 | print(FSx_i) 1556 | print(FSx) 1557 | print(FSy_i) 1558 | print(FSy) 1559 | ''' 1560 | 1561 | # Bishop 1562 | elif method == 3: 1563 | if abs(FSmx-FSmx_i) <= tolFS and abs(FSmy-FSmy_i) <= tolFS: 1564 | FSmx_f = FSmx 1565 | FSmy_f = FSmy 1566 | checkMomentFS = 1 1567 | elif abs(FSmx-FSmx_i) <= tolFS and abs(FSmy-FSmy_i) > tolFS: 1568 | iterationN_FS += 1 1569 | FSmx_f = FSmx 1570 | FSmy_i = FSmy 1571 | #FSmy_i -= changeFS 1572 | elif abs(FSmx-FSmx_i) > tolFS and abs(FSmy-FSmy_i) <= tolFS: 1573 | iterationN_FS += 1 1574 | FSmx_i = FSmx 1575 | FSmy_f = FSmy 1576 | #FSmx_i -= changeFS 1577 | else: 1578 | iterationN_FS += 1 1579 | FSmx_i = FSmx 1580 | FSmy_i = FSmy 1581 | #FSmx_i -= changeFS 1582 | #FSmy_i -= changeFS 1583 | 1584 | if counts >= iterationNMax: 1585 | print('too many iterations (iterationNN) - check code or increase maximum iteration number') 1586 | # take failed result for method 3 or 4 1587 | FS_results.append([3, iterationN_a, iterationN_FS, slidingDirection, 0, 0, 0, np.nan, np.nan, np.nan, np.nan, np.nan]) 1588 | counts = 0 1589 | iterationN_FS = 0 1590 | iterationLambda = False 1591 | iterationFS = False 1592 | #FS_final = 0.5*(FS_force_f+FS_moment_f) 1593 | else: 1594 | if checkMomentFS != 0: 1595 | FS_results.append([3, iterationN_a, iterationN_FS, slidingDirection, 0, 0, 0, FSmx_f, FSmy_f, np.nan, np.nan, np.nan]) 1596 | counts = 0 1597 | iterationN_FS = 0 1598 | iterationLambda = False 1599 | iterationFS = False 1600 | 1601 | counts += 1 1602 | #print(counts) 1603 | 1604 | # Spencer or Morgenstern-Price 1605 | elif method in [1,2]: 1606 | if abs(FSx-FSx_i) <= tolFS and abs(FSy-FSy_i) <= tolFS: 1607 | FSx_f = FSx 1608 | FSy_f = FSy 1609 | checkForceFS = 1 1610 | elif abs(FSx-FSx_i) <= tolFS and abs(FSy-FSy_i) > tolFS: 1611 | FSx_f = FSx 1612 | FSy_i = FSy 1613 | #FSy_i -= changeFS 1614 | elif abs(FSx-FSx_i) > tolFS and abs(FSy-FSy_i) <= tolFS: 1615 | FSx_i = FSx 1616 | #FSx_i -= changeFS 1617 | FSy_f = FSy 1618 | else: 1619 | FSx_i = FSx 1620 | FSy_i = FSy 1621 | #FSx_i -= changeFS 1622 | #FSy_i -= changeFS 1623 | 1624 | if abs(FSmx-FSmx_i) <= tolFS and abs(FSmy-FSmy_i) <= tolFS: 1625 | FSmx_f = FSmx 1626 | FSmy_f = FSmy 1627 | checkMomentFS = 1 1628 | elif abs(FSmx-FSmx_i) <= tolFS and abs(FSmy-FSmy_i) > tolFS: 1629 | FSmx_f = FSmx 1630 | FSmy_i = FSmy 1631 | #FSmy_i -= changeFS 1632 | elif abs(FSmx-FSmx_i) > tolFS and abs(FSmy-FSmy_i) <= tolFS: 1633 | #FSmx_i -= changeFS 1634 | FSmx_i = FSmx 1635 | FSmy_f = FSmy 1636 | else: 1637 | FSmx_i = FSmx 1638 | FSmy_i = FSmy 1639 | #FSmx_i -= changeFS 1640 | #FSmy_i -= changeFS 1641 | 1642 | if counts >= iterationNMax: 1643 | print('too many iterations (iterationNN) - check code or increase maximum iteration number') 1644 | # take failed result for method 3 or 4 1645 | #FS_results.append([method, iterationN_a, iterationN_FS, slidingDirection, lambdaX, lambdaY, lambdaXY, np.nan, np.nan, np.nan, np.nan, np.nan]) 1646 | FS_results_Temp.append([np.nan, np.nan, np.nan, np.nan]) 1647 | if scaleLambdaXList[-1] > scaleLambdaYList[-1]: 1648 | scaleLambdaYList.append(scaleLambdaYList[-1]+changeLambda) 1649 | else: 1650 | scaleLambdaXList.append(scaleLambdaXList[-1]+changeLambda) 1651 | #scaleLambdaXList, scaleLambdaYList = changeLambda3D(scaleLambdaXList, scaleLambdaYList, FS_results_Temp, tolFS) 1652 | iterationN_FS = 0 1653 | counts = 0 1654 | print(FSmx_f, FSmy_f, FSx_f, FSy_f) 1655 | print(scaleLambdaXList[-1]) 1656 | print(scaleLambdaYList[-1]) 1657 | #iterationFS = False 1658 | #iterationLambda = False 1659 | continue 1660 | 1661 | else: 1662 | if checkForceFS != 0 and checkMomentFS != 0: 1663 | 1664 | iterationN_FS = 0 1665 | counts = 0 1666 | iterationFS = False 1667 | 1668 | ''' 1669 | if round(slidingDirection,2) in [90, 270]: 1670 | tempFSforceList.append(FSx_f) 1671 | tempFSmomentList.append(FSmy_f) 1672 | 1673 | elif round(slidingDirection,2) in [0, 180, 360]: 1674 | tempFSforceList.append(FSy_f) 1675 | tempFSmomentList.append(FSmx_f) 1676 | 1677 | elif round(FSx_f, 2) == 0 and round(FSy_f, 2) != 0: 1678 | if round(FSmx_f, 2) == 0 and round(FSmy_f, 2) != 0: 1679 | tempFSforceList.append(FSy_f) 1680 | tempFSmomentList.append(FSmy_f) 1681 | elif round(FSmx_f, 2) != 0 and round(FSmy_f, 2) == 0: 1682 | tempFSforceList.append(FSy_f) 1683 | tempFSmomentList.append(FSmx_f) 1684 | 1685 | elif round(FSx_f, 2) != 0 and round(FSy_f, 2) == 0: 1686 | if round(FSmx_f, 2) == 0 and round(FSmy_f, 2) != 0: 1687 | tempFSforceList.append(FSx_f) 1688 | tempFSmomentList.append(FSmy_f) 1689 | elif round(FSmx_f, 2) != 0 and round(FSmy_f, 2) == 0: 1690 | tempFSforceList.append(FSx_f) 1691 | tempFSmomentList.append(FSmx_f) 1692 | else: 1693 | tempFSforceList.append(0.5*(FSx_f+FSy_f)) 1694 | tempFSmomentList.append(0.5*(FSmx_f+FSmy_f)) 1695 | ''' 1696 | 1697 | #FS_results_Temp.append([method, iterationN_a, iterationN_FS, slidingDirection, lambdaX, lambdaY, lambdaXY, FSmx_f, FSmy_f, FSx_f, FSy_f, np.nan]) 1698 | print([method, iterationN_a, iterationN_FS, slidingDirection, lambdaX, lambdaY, lambdaXY, FSmx_f, FSmy_f, FSx_f, FSy_f, np.nan]) 1699 | FS_results_Temp.append([FSmx_f, FSmy_f, FSx_f, FSy_f]) 1700 | #print(FS_results_Temp) 1701 | 1702 | for loopCol in range(len(analysisInput)): 1703 | f1 = fVectorDatas[loopCol][0] 1704 | f2 = fVectorDatas[loopCol][1] 1705 | f3 = fVectorDatas[loopCol][2] 1706 | 1707 | g1 = gVectorDatas[loopCol][0] 1708 | g2 = gVectorDatas[loopCol][1] 1709 | g3 = gVectorDatas[loopCol][2] 1710 | 1711 | dEx = dExDatas[loopCol] 1712 | dEy = dEyDatas[loopCol] 1713 | 1714 | Qxi = QDatas[loopCol][0] 1715 | Qyi = QDatas[loopCol][1] 1716 | Qzi = QDatas[loopCol][2] 1717 | 1718 | baseArea = analysisInput[loopCol][14]/analysisInput[loopCol][16] 1719 | Ui = baseArea*analysisInput[loopCol][5] 1720 | Wi = analysisInput[loopCol][14] 1721 | Ci = baseArea*analysisInput[loopCol][12] 1722 | phiRad = np.radians(analysisInput[loopCol][13]) 1723 | 1724 | Ai = (lambdaX*dEx + lambdaY*dEy + Wi + Qzi)/g3 1725 | Bi = -f3/g3 1726 | 1727 | Si_xx = (Ci + (Ai - Ui)*np.tan(phiRad))/(FSx_f-(Bi*np.tan(phiRad))) 1728 | Si_yy = (Ci + (Ai - Ui)*np.tan(phiRad))/(FSy_f-(Bi*np.tan(phiRad))) 1729 | 1730 | Ni_xx = Ai + Bi*Si_xx 1731 | Ni_yy = Ai + Bi*Si_yy 1732 | 1733 | dEx_new = (Si_xx*f1 - Ni_xx*g1 - seismicKx*Wi + Qxi)/(1-lambdaXY*Fxy) 1734 | dEy_new = (Si_yy*f2 - Ni_yy*g2 - seismicKy*Wi + Qyi)/(1-lambdaXY*Fxy) 1735 | 1736 | #print(dEx_new, dEy_new) 1737 | 1738 | dExDatas[loopCol] = dEx_new 1739 | dEyDatas[loopCol] = dEy_new 1740 | 1741 | if scaleLambdaXList[-1] > scaleLambdaYList[-1]: 1742 | scaleLambdaYList.append(scaleLambdaYList[-1]+changeLambda) 1743 | elif scaleLambdaXList[-1] < scaleLambdaYList[-1]: 1744 | scaleLambdaXList.append(scaleLambdaXList[-1]+changeLambda) 1745 | elif round(abs(scaleLambdaXList[-1] - scaleLambdaYList[-1]),2) < 0.01: 1746 | randomNum = np.random.choice(2) 1747 | if (randomNum%2) == 0: # even number 1748 | scaleLambdaXList.append(scaleLambdaXList[-1]+changeLambda) 1749 | else: # odd number 1750 | scaleLambdaYList.append(scaleLambdaYList[-1]+changeLambda) 1751 | 1752 | #if abs(tempFSforceList[-1]-tempFSmomentList[-1]) > tolFS: 1753 | #scaleLambdaXList, scaleLambdaYList = changeLambda3D(scaleLambdaXList, scaleLambdaYList, FS_results_Temp, tolFS) 1754 | 1755 | FS_results.append([method, iterationN_a, iterationN_FS, slidingDirection, lambdaX, lambdaY, lambdaXY, FSmx_f, FSmy_f, FSx_f, FSy_f, np.nan]) 1756 | 1757 | if round(slidingDirection,2) in [0, 180, 360]: 1758 | checkFSsM = 0 1759 | checkFSsF = 0 1760 | checkFSsFM = abs(FSmx_f - FSy_f) 1761 | elif round(slidingDirection,2) in [90, 270]: 1762 | checkFSsM = 0 1763 | checkFSsF = 0 1764 | checkFSsFM = abs(FSmy_f - FSx_f) 1765 | elif round(FSmx_f, 2) == 0 or round(FSmy_f, 2) == 0 or round(FSx_f, 2) == 0 or round(FSy_f, 2) == 0: 1766 | checkFSsM = 0 1767 | checkFSsF = 0 1768 | checkFSsFM = abs(0.5*(FSmx_f+FSmy_f) - 0.5*(FSx_f+FSy_f)) 1769 | else: 1770 | checkFSsM = abs(FSmx_f - FSmy_f) 1771 | checkFSsF = abs(FSx_f - FSy_f) 1772 | checkFSsFM = abs(0.5*(FSmx_f+FSmy_f) - 0.5*(FSx_f+FSy_f)) 1773 | 1774 | #print('checkFSsM=%f'%checkFSsM) 1775 | #print('checkFSsF=%f'%checkFSsF) 1776 | #print('checkFSsFM=%f'%checkFSsFM) 1777 | 1778 | if (checkFSsM < tolFS) and (checkFSsF < tolFS) and (checkFSsFM < tolFS): 1779 | iterationLambda = False 1780 | 1781 | else: 1782 | iterationN_FS += 1 1783 | 1784 | counts += 1 1785 | #print(counts) 1786 | 1787 | #iterationN_a 1788 | #iterationN_FS 1789 | 1790 | #if iterationN_a >= 100: #(len(iterationLambdaX)*len(iterationLambdaY)): 1791 | # print('too many iterations (100) - check code or increase maximum iteration number') 1792 | # iterationFS = False 1793 | 1794 | #print(iterationN_a) 1795 | #print(iterationN_FS) 1796 | ''' 1797 | FSx_f 1798 | FSy_f 1799 | FSmy_f 1800 | FSmx_f 1801 | ''' 1802 | 1803 | # Bishop Method 1804 | if method == 3: 1805 | 1806 | #print(FS_results) 1807 | #print(loopFS) 1808 | 1809 | FSmx_f = FS_results[loopFS][7] 1810 | FSmy_f = FS_results[loopFS][8] 1811 | 1812 | # FSs_x - FSs_y 1813 | checkFSsM = 0 1814 | if round(slidingDirection,2) in [0, 90, 180, 270, 360]: 1815 | checkFSsM = 0 1816 | elif round(FSmx_f, 2) == 0 or round(FSmy_f, 2) == 0: 1817 | checkFSsM = 0 1818 | else: 1819 | checkFSsM = abs(FSmx_f - FSmy_f) 1820 | 1821 | #print(checkFSsM) 1822 | 1823 | if checkFSsM < tolFS: 1824 | # find global FS for a given direction 1825 | ''' 1826 | if round(slidingDirection,2) in [0, 90, 180, 270, 360]: 1827 | FS_results[loopFS][11] = max([FSmy_f, FSmx_f]) 1828 | ''' 1829 | if round(slidingDirection,2) in [90, 270]: 1830 | FS_results[loopFS][11] = FSmy_f 1831 | 1832 | elif round(slidingDirection,2) in [0, 180, 360]: 1833 | FS_results[loopFS][11] = FSmx_f 1834 | 1835 | elif round(FSmx_f, 2) == 0 and round(FSmy_f, 2) != 0: 1836 | FS_results[loopFS][11] = FSmy_f 1837 | 1838 | elif round(FSmx_f, 2) != 0 and round(FSmy_f, 2) == 0: 1839 | FS_results[loopFS][11] = FSmx_f 1840 | 1841 | else: 1842 | FS_results[loopFS][11] = (FSmx_f+FSmy_f)/2 1843 | 1844 | # find min global FS for a given direction 1845 | if loopFS == 0 and not(np.isnan(FS_results[loopFS][11])): 1846 | FSg_cur = FS_results[loopFS][11] 1847 | FSg_IDX = loopFS 1848 | 1849 | else: 1850 | if not np.isnan(FS_results[loopFS][11]) and np.isnan(FSg_cur): 1851 | FSg_cur = FS_results[loopFS][11] 1852 | FSg_IDX = loopFS 1853 | 1854 | elif not(np.isnan(FS_results[loopFS][11])) and not(np.isnan(FSg_cur)) and (FSg_cur > FS_results[loopFS][11]): 1855 | FSg_cur = FS_results[loopFS][11] 1856 | FSg_IDX = loopFS 1857 | 1858 | else: 1859 | if loopFS == 0 and not(np.isnan(FS_results[loopFS][11])): 1860 | FSg_cur = FS_results[loopFS][11] 1861 | FSg_IDX = loopFS 1862 | 1863 | 1864 | loopFS += 1 1865 | iterationN_a += 1 1866 | counts = 0 1867 | continue 1868 | 1869 | # Janbu Method 1870 | elif method == 4: 1871 | 1872 | FSx_f = FS_results[loopFS][9] 1873 | FSy_f = FS_results[loopFS][10] 1874 | 1875 | # FSs_x - FSs_y 1876 | checkFSsF = 0 1877 | if round(slidingDirection,2) in [0, 90, 180, 270, 360]: 1878 | checkFSsF = 0 1879 | elif round(FSx_f, 2) == 0 or round(FSy_f, 2) == 0: 1880 | checkFSsF = 0 1881 | else: 1882 | checkFSsF = abs(FSx_f - FSy_f) 1883 | 1884 | #print(checkFSsF) 1885 | 1886 | if checkFSsF < tolFS: 1887 | # find global FS for a given direction 1888 | ''' 1889 | if round(slidingDirection,2) in [0, 90, 180, 270, 360]: 1890 | FS_results[loopFS][11] = max([FSy_f, FSx_f]) 1891 | ''' 1892 | 1893 | if round(slidingDirection,2) in [90, 270]: 1894 | FS_results[loopFS][11] = FSx_f*correctionFactor 1895 | 1896 | elif round(slidingDirection,2) in [0, 180, 360]: 1897 | FS_results[loopFS][11] = FSy_f*correctionFactor 1898 | 1899 | elif round(FSx_f, 2) == 0 and round(FSy_f, 2) != 0: 1900 | FS_results[loopFS][11] = FSy_f*correctionFactor 1901 | 1902 | elif round(FSx_f, 2) != 0 and round(FSy_f, 2) == 0: 1903 | FS_results[loopFS][11] = FSx_f*correctionFactor 1904 | 1905 | else: 1906 | FS_results[loopFS][11] = correctionFactor*(FSx_f+FSy_f)/2 1907 | 1908 | # find min global FS for a given direction 1909 | if loopFS == 0 and not(np.isnan(FS_results[loopFS][11])): 1910 | FSg_cur = FS_results[loopFS][11] 1911 | FSg_IDX = loopFS 1912 | 1913 | else: 1914 | if not np.isnan(FS_results[loopFS][11]) and np.isnan(FSg_cur): 1915 | FSg_cur = FS_results[loopFS][11] 1916 | FSg_IDX = loopFS 1917 | 1918 | elif not(np.isnan(FS_results[loopFS][11])) and not(np.isnan(FSg_cur)) and (FSg_cur > FS_results[loopFS][11]): 1919 | FSg_cur = FS_results[loopFS][11] 1920 | FSg_IDX = loopFS 1921 | 1922 | else: 1923 | if loopFS == 0 and not(np.isnan(FS_results[loopFS][11])): 1924 | FSg_cur = FS_results[loopFS][11] 1925 | FSg_IDX = loopFS 1926 | 1927 | loopFS += 1 1928 | iterationN_a += 1 1929 | counts = 0 1930 | continue 1931 | 1932 | elif method == 1 or method == 2: 1933 | #print(FS_results) 1934 | 1935 | FSmx_f = FS_results[-1][7] 1936 | FSmy_f = FS_results[-1][8] 1937 | FSx_f = FS_results[-1][9] 1938 | FSy_f = FS_results[-1][10] 1939 | 1940 | # FSs_x - FSs_y 1941 | ''' 1942 | checkFSsM = 0 1943 | checkFSsF = 0 1944 | checkFSsFM = 0 1945 | ''' 1946 | if round(slidingDirection,2) in [0, 180, 360]: 1947 | checkFSsM = 0 1948 | checkFSsF = 0 1949 | checkFSsFM = abs(FSmx_f - FSy_f) 1950 | elif round(slidingDirection,2) in [90, 270]: 1951 | checkFSsM = 0 1952 | checkFSsF = 0 1953 | checkFSsFM = abs(FSmy_f - FSx_f) 1954 | elif round(FSmx_f, 2) == 0 or round(FSmy_f, 2) == 0 or round(FSx_f, 2) == 0 or round(FSy_f, 2) == 0: 1955 | checkFSsM = 0 1956 | checkFSsF = 0 1957 | checkFSsFM = abs(0.5*(FSmx_f+FSmy_f) - 0.5*(FSx_f+FSy_f)) 1958 | else: 1959 | checkFSsM = abs(FSmx_f - FSmy_f) 1960 | checkFSsF = abs(FSx_f - FSy_f) 1961 | checkFSsFM = abs(0.5*(FSmx_f+FSmy_f) - 0.5*(FSx_f+FSy_f)) 1962 | 1963 | #print('checkFSsM=%f'%checkFSsM) 1964 | #print('checkFSsF=%f'%checkFSsF) 1965 | print('checkFSsFM=%f'%checkFSsFM) 1966 | 1967 | if (checkFSsM < tolFS) and (checkFSsF < tolFS) and (checkFSsFM < tolFS): 1968 | ''' 1969 | if round(slidingDirection,2) in [0, 90, 180, 270, 360]: 1970 | FS_results[loopFS][11] = max([(FSmx_f+FSx_f)/2, (FSmy_f+FSy_f)/2]) 1971 | ''' 1972 | 1973 | if round(slidingDirection,2) in [90, 270]: 1974 | FS_results[-1][11] = (FSmy_f+FSx_f)/2 1975 | 1976 | elif round(slidingDirection,2) in [0, 180, 360]: 1977 | FS_results[-1][11] = (FSmx_f+FSy_f)/2 1978 | 1979 | elif round(FSx_f, 2) == 0 and round(FSy_f, 2) != 0: 1980 | if round(FSmx_f, 2) == 0 and round(FSmy_f, 2) != 0: 1981 | FS_results[-1][11] = (FSy_f+FSmy_f)/2 1982 | 1983 | elif round(FSmx_f, 2) != 0 and round(FSmy_f, 2) == 0: 1984 | FS_results[-1][11] = (FSy_f+FSmx_f)/2 1985 | 1986 | elif round(FSx_f, 2) != 0 and round(FSy_f, 2) == 0: 1987 | if round(FSmx_f, 2) == 0 and round(FSmy_f, 2) != 0: 1988 | FS_results[-1][11] = (FSx_f+FSmy_f)/2 1989 | 1990 | elif round(FSmx_f, 2) != 0 and round(FSmy_f, 2) == 0: 1991 | FS_results[-1][11] = (FSx_f+FSmx_f)/2 1992 | 1993 | else: 1994 | FS_results[-1][11] = (FSmx_f+FSx_f+FSmy_f+FSy_f)/4 1995 | 1996 | # find min global FS for a given direction 1997 | ''' 1998 | if loopFS == 0 and not(np.isnan(FS_results[loopFS][11])): 1999 | FSg_cur = FS_results[-1][11] 2000 | FSg_IDX = loopFS 2001 | 2002 | else: 2003 | if not np.isnan(FS_results[loopFS][11]) and np.isnan(FSg_cur): 2004 | FSg_cur = FS_results[loopFS][11] 2005 | FSg_IDX = loopFS 2006 | 2007 | elif not(np.isnan(FS_results[loopFS][11])) and not(np.isnan(FSg_cur)) and (FSg_cur > FS_results[loopFS][11]): 2008 | FSg_cur = FS_results[loopFS][11] 2009 | FSg_IDX = loopFS 2010 | ''' 2011 | ''' 2012 | else: 2013 | if loopFS == 0 and not(np.isnan(FS_results[loopFS][11])): 2014 | FSg_cur = FS_results[loopFS][11] 2015 | FSg_IDX = loopFS 2016 | ''' 2017 | 2018 | loopFS += 1 2019 | iterationN_a += 1 2020 | counts = 0 2021 | #continue 2022 | 2023 | #print(FS_results) 2024 | #print(FSg_IDX) 2025 | #print( listAtColNum(FS_results, 11)) 2026 | #print(FS_results[int(FSg_IDX)]) 2027 | 2028 | return FS_results 2029 | 2030 | ''' 2031 | 3D LEM Slope Analysis: 2032 | 1. Hungr Bishop 2033 | 2. Hungr Janbu 2034 | 3. Hungr Janbu corrected 2035 | 4. Cheng and Yip Bishop 2036 | 5. Cheng and Yip Janbu simplified 2037 | 6. Cheng and Yip Janbu corrected 2038 | 7. Cheng and Yip Spencer 2039 | ''' 2040 | def select3DMethod(fileName, method, seismicK, materialClass, materialNameList, centerPt0, useDirectionB=None, useriterationNMax=200, usertolFS=0.001, userSideR=True): 2041 | if method == 1: 2042 | FS = analysis3DHungrBishop1989(fileName, seismicK, centerPt0, materialClass, materialNameList, iterationNMax=useriterationNMax, tolFS=usertolFS, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=useDirectionB) 2043 | elif method == 2: 2044 | FS = analysis3DHungrJanbu1989(fileName, seismicK, materialClass, materialNameList, correctFS=1, iterationNMax=useriterationNMax, tolFS=usertolFS, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=useDirectionB, sideResistance=userSideR) 2045 | elif method == 3: 2046 | FS = analysis3DHungrJanbu1989(fileName, seismicK, materialClass, materialNameList, correctFS=None, iterationNMax=useriterationNMax, tolFS=usertolFS, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=useDirectionB, sideResistance=True) 2047 | elif method == 4: 2048 | FS = analysis3DChengnYip2007(fileName, seismicK, centerPt0, 3, materialClass, lambdaIteration=None, iterationNMax=useriterationNMax, tolFS=usertolFS, correctFS=None, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=useDirectionB) 2049 | elif method == 5: 2050 | FS = analysis3DChengnYip2007(fileName, seismicK, centerPt0, 4, materialClass, lambdaIteration=None, iterationNMax=useriterationNMax, tolFS=usertolFS, correctFS=1, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=useDirectionB) 2051 | elif method == 6: 2052 | FS = analysis3DChengnYip2007(fileName, seismicK, centerPt0, 4, materialClass, lambdaIteration=None, iterationNMax=useriterationNMax, tolFS=usertolFS, correctFS=None, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=useDirectionB) 2053 | elif method == 7: 2054 | FS = analysis3DChengnYip2007(fileName, seismicK, centerPt0, 2, materialClass, lambdaIteration=None, iterationNMax=useriterationNMax, tolFS=usertolFS, correctFS=None, occuranceFactor=0.5, tolDirection_user=None, spacingDirection=0.5, avDipDirectionB_user=useDirectionB) 2055 | else: 2056 | return 'Invalid Input Method' 2057 | 2058 | return FS[-1][-1] 2059 | 2060 | #testing 2061 | #select3DMethod(fileName, method, seismicK, materialClass, centerPt0, iterationNMax=200, avDipDirectionB_user=None) 2062 | import time 2063 | time_start = time.clock() 2064 | 2065 | #fileName = 'ColumnResults_circular_Bishop.csv' # 180 2066 | #fileName = 'ColumnResults_planar.csv' # 180 2067 | #fileName = 'ColumnResults_plane_270.csv' # 270 2068 | #fileName = 'yeager_noGW_noGeogrid.csv' # 170.5 2069 | #fileName = 'ChengNYip2007_example2_ColumnResults.csv' # 225 2070 | #fileName = 'ChengNYip2007_example3_ColumnResults.csv' # 225 2071 | #fileName = 'ChengNYip2007_example4_ColumnResults.csv' # 153.4 2072 | #fileName = '3DanalysisInputFile_ss2.csv' # 180 2073 | #fileName = '3DanalysisInputFile_ssa1.csv' # 180 2074 | #fileName = '3DanalysisInputFile_ssb1.csv' # 180 2075 | #fileName = '3DanalysisInputFile.csv' # 180 2076 | 2077 | 2078 | materialClass = {'rr':[1,[[45,10000],[0,0,0],0.25],150,150,1],'w1':[1,[[10,0],[0,0,0],0.25],120,120,2],'m1':[1,[[20,600],[0,0,0],0.25],120,120,3]} 2079 | materialNameList = ['rr', 'w1', 'm1'] 2080 | 2081 | seismicK = [0, 0] 2082 | 2083 | ''' 2084 | 3D LEM Slope Analysis: 2085 | 1. Hungr Bishop simplified 2086 | 2. Hungr Janbu simplified 2087 | 3. Hungr Janbu corrected 2088 | 4. Cheng and Yip Bishop 2089 | 5. Cheng and Yip Janbu simplified 2090 | 6. Cheng and Yip Janbu corrected 2091 | 7. Cheng and Yip Spencer 2092 | ''' 2093 | #method = 4 2094 | 2095 | #centerPt0 = [5, 0, 5] 2096 | #centerPt0 = [5, 0, 8.03973] 2097 | #centerPt0 = [0, 5, 8.03973] 2098 | #centerPt0 = [1795820, 498800, 1008.41] 2099 | #centerPt0 = [0, 0, 5] 2100 | #centerPt0 = [0, 0, 9.46981] 2101 | #centerPt0 = [4, 0, 6.53953] 2102 | centerPt0 = [80, 60, 90] # [80, 50, 120] # 2103 | 2104 | #select3DMethod(fileName, method, seismicK, materialClass, materialNameList, centerPt0, useDirectionB=None, useriterationNMax=200, usertolFS=0.001, userSideR=True) 2105 | #print (select3DMethod(fileName, 1, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2106 | #print (select3DMethod(fileName, 2, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2107 | #print (select3DMethod(fileName, 3, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2108 | #print (select3DMethod(fileName, 4, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2109 | #print (select3DMethod(fileName, 5, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2110 | #print (select3DMethod(fileName, 6, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2111 | #print (select3DMethod(fileName, 7, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180, usertolFS=0.005)) 2112 | 2113 | print (select3DMethod('3DanalysisInputFile_ss2.csv', 2, seismicK, materialClass, materialNameList, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2114 | print (select3DMethod('3DanalysisInputFile_ss2.csv', 3, seismicK, materialClass, materialNameList, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2115 | 2116 | #print (select3DMethod('3DanalysisInputFile_ssb1_40_1_std85.csv', 1, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2117 | #print (select3DMethod('3DanalysisInputFile_ssc1_40_1_std85.csv', 1, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2118 | ''' 2119 | print (select3DMethod('3DanalysisInputFile_ssb3_std75.csv', 1, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2120 | print (select3DMethod('3DanalysisInputFile_ssc3_std75.csv', 1, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2121 | print (select3DMethod('3DanalysisInputFile_ssb4_std100.csv', 1, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2122 | print (select3DMethod('3DanalysisInputFile_ssc4_std100.csv', 1, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2123 | print (select3DMethod('3DanalysisInputFile_ssb5_std200.csv', 1, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2124 | print (select3DMethod('3DanalysisInputFile_ssc5_std200.csv', 1, seismicK, materialClass, centerPt0, useriterationNMax=1000, useDirectionB=180)) 2125 | ''' 2126 | time_elapsed = (time.clock() - time_start) 2127 | print(time_elapsed) # tells us the computation time in seconds --------------------------------------------------------------------------------