1"""Module with pre-made analysis and postprocessing functions. \n
6import matplotlib.pyplot
as plt
9import openseespy.postprocessing.Get_Rendering
as opsplt
17 """Class dedicated to the analysis of the OpenSeesPy model. The Gravity method should be run first to perform the Load-control analysis (apply the vertical load). If no vertical load, this method can be omitted. \n
18 Then only one of the Displacement-control (Pushover or LoadingProtocol)
or Load-control (LateralForce) analysis can ran. \n
19 After the analysis reach convergence
in the last step,
for the postprocessing, the DeformedShape method can be used to see the final deformed shape
and the animation of the entire loading protocol;
20 the FiberResponse method can be used to see the animation of the same fiber section recorded during the analysis (strain
and/
or stress).
22 def __init__(self, data_dir: str, name_ODB: str, algo =
"KrylovNewton", test_type =
"NormDispIncr", test_opt = 0, max_iter = MAX_ITER, tol = TOL, allow_smaller_step =
False):
24 The constructor of the class.
26 @param data_dir (str): Directory
in which the results
from the analysis will be stored. Use the recorders (
from OpenSeesPy)
or the Record method
from MemberModel.
27 @param name_ODB (str): Name
for the folder
in which the data
for the animations
and the fibers are stored.
28 @param algo (str, optional): Type of alghoritm chosen
for the analysis. It detemines how to construct a SolutionAlgorithm object, which determines the sequence of steps taken to solve the non-linear equation.
29 For more information on the available types, see the OpenSeesPy documentation. Defaults to
"KrylovNewton".
30 @param test_type (str, optional): Type of test chosen
for the analysis. It determines how to construct a ConvergenceTest object.
31 Certain SolutionAlgorithm objects require a ConvergenceTest object to determine
if convergence has been achieved at the end of an iteration step.
32 For more information on the available types, see the OpenSeesPy documentation. Defaults to
"NormDispIncr".
33 @param test_opt (int, optional): Print-flag
from 0 to 5 used to receive more info during the iteration
34 (
for example: 0
print nothing
and 2
print information on norms
and number of iterations at end of successful test).
35 For more information, see the OpenSeesPy documentation. Defaults to 0.
36 @param max_iter (float, optional): Maximal number of iterations to check. Defaults to MAX_ITER (
from Constants Module).
37 @param tol (float, optional): Tolerance criteria used to check
for convergence. Defaults to TOL (
from Constants Module).
38 @param allow_smaller_step (bool, optional): Allow smaller steps
in the displacement-control analysis. Defaults to
False.
40 @exception NegativeValue: The argument max_iter should be positive.
41 @exception NegativeValue: The argument tol should be positive.
43 if max_iter < 0:
raise NegativeValue()
44 if tol < 0:
raise NegativeValue()
45 if not os.path.exists(data_dir):
46 print(
"Folder {} not found in this directory; creating one".format(data_dir))
60 def Gravity(self, loaded_nodes: list, Fy: list, timeSeries_ID: int, pattern_ID: int, n_step = 10, timeSeries_type =
"Linear", pattern_type =
"Plain",
61 constraints_type =
"Plain", numberer_type =
"RCM", system_type =
"BandGeneral", analysis_type =
"Static", show_plot =
False):
63 Method to perform the gravity analyisis with vertical loadings (load-control).
64 It can be used before calling the Pushover
or LoadingProtocol methods that perform the actual anlysis. If no vertical loadings present, this method can be avoided.
66 @param loaded_nodes (list): List of nodes that are loaded by the the forces
in Fy. The first node will be recorded (thus usually should be
in the roof).
67 @param Fy (list): List of vertical loadings (negative
is toward the ground, thus compression; see
global coordinate system).
68 @param timeSeries_ID (int): ID of the timeseries.
69 @param pattern_ID (int): ID of the pattern.
70 @param n_step (int, optional): Number of steps used to during the analysis to reach the objective state (
with 100% vertical loadings imposed). Defaults to 10.
71 @param timeSeries_type (str, optional): Type of timeseries chosen.
72 For more information, see the OpenSeesPy documentation. Defaults to
"Linear".
73 @param pattern_type (str, optional): Type of pattern chosen.
74 For more information, see the OpenSeesPy documentation. Defaults to
"Plain".
75 @param constraints_type (str, optional): Type of contraints chosen. It detemines how the constraint equations are enforced
in the analysis.
76 For more information, see the OpenSeesPy documentation. Defaults to
"Plain".
77 @param numberer_type (str, optional): Type of numberer chosen. It determines the mapping between equation numbers
and degrees-of-freedom.
78 For more information, see the OpenSeesPy documentation. Defaults to
"RCM".
79 @param system_type (str, optional): Type of system of equations chosen. It determines how to construct the LinearSOE
and LinearSolver objects to store
and solve the system of equations
in the analysis.
80 For more information, see the OpenSeesPy documentation. Defaults to
"BandGeneral".
81 @param analysis_type (str, optional): Type of analysis chosen. It determines how to construct the Analysis object, which defines what type of analysis
is to be performed.
82 For more information, see the OpenSeesPy documentation. Defaults to
"Static".
83 @param show_plot (bool, optional): Option to show the
'vertical displacement vs. vertical loading' curve after the analysis. Defaults to
False.
85 @exception WrongDimension: The dimension of the loaded_nodes
and Fy arguments needs to be the same.
86 @exception NegativeValue: The ID of timeSeries_ID needs to be a positive integer.
87 @exception NegativeValue: The ID of pattern_ID needs to be a positive integer.
89 if len(loaded_nodes) != len(Fy):
raise WrongDimension()
90 if timeSeries_ID < 1:
raise NegativeValue()
91 if pattern_ID < 1:
raise NegativeValue()
97 timeSeries(timeSeries_type, timeSeries_ID)
98 pattern(pattern_type, timeSeries_ID, pattern_ID)
99 for ii, node_ID
in enumerate(loaded_nodes):
100 load(node_ID, 0.0, Fy[ii], 0.0)
101 DGravity = 1.0/n_step
104 constraints(constraints_type)
105 numberer(numberer_type)
108 integrator(
"LoadControl", DGravity)
111 analysis(analysis_type)
114 dataG = np.zeros((n_step+1,2))
116 print(
"Gravity analysis starts")
117 for iteration
in range(n_step):
118 convergence = self.
__LoadCtrlLoop__LoadCtrlLoop(DGravity, iteration,
120 if convergence != 0:
break
121 dataG[iteration+1,0] = nodeDisp(loaded_nodes[0], 2)/mm_unit
122 dataG[iteration+1,1] = getLoadFactor(pattern_ID)*Fy[0]/kN_unit
125 plt.plot(dataG[:,0], dataG[:,1])
126 plt.xlabel(
'Vertical Displacement [mm]')
127 plt.ylabel(
'Vertical Load [kN]')
128 plt.title(
'Gravity curve')
131 loadConst(
"-time", 0.0)
134 print(
"Gravity complete")
137 def LateralForce(self, loaded_nodes: list, Fx: list, timeSeries_ID: int, pattern_ID: int, n_step = 1000, fiber_ID_analysed = -1, fiber_section = 1,
138 timeSeries_type =
"Linear", pattern_type =
"Plain", constraints_type =
"Plain", numberer_type =
"RCM", system_type =
"BandGeneral", analysis_type =
"Static",
139 show_plot =
True, block =
False):
141 Method to perform the lateral force analyisis with lateral loading (load-control).
142 If this method
is called, the LoadingProtocol
and Pushover methods should be avoided.
144 @param loaded_nodes (list): List of nodes that are loaded by the the forces
in Fx. The first node will be recorded (thus usually should be
in the roof).
145 @param Fx (list): List of horizontal loadings (negative
is toward left; see
global coordinate system).
146 @param timeSeries_ID (int): ID of the timeseries.
147 @param pattern_ID (int): ID of the pattern.
148 @param n_step (int, optional): Number of steps used to during the analysis to reach the objective state (
with 100% horizontal loadings imposed). Defaults to 1000.
149 @param fiber_ID_analysed (int, optional): The ID of the analysed fiber. If fibers are present
in the model
and the user wants to save ODB data
150 (to use
in the post-processing
with for example FiberResponse), assign to this argument the ID of the fiber chosen.
151 -1 will ignore the storage of data
for fibers. Defaults to -1.
152 @param fiber_section (int, optional): The section number, i.e. the Gauss integratio number.
153 If the fiber_ID_analysed
is equal to -1, this argument
is not used. Defaults to 1.
154 @param timeSeries_type (str, optional): Type of timeseries chosen.
155 For more information, see the OpenSeesPy documentation. Defaults to
"Linear".
156 @param pattern_type (str, optional): Type of pattern chosen.
157 For more information, see the OpenSeesPy documentation. Defaults to
"Plain".
158 @param constraints_type (str, optional): Type of contraints chosen. It detemines how the constraint equations are enforced
in the analysis.
159 For more information, see the OpenSeesPy documentation. Defaults to
"Plain".
160 @param numberer_type (str, optional): Type of numberer chosen. It determines the mapping between equation numbers
and degrees-of-freedom.
161 For more information, see the OpenSeesPy documentation. Defaults to
"RCM".
162 @param system_type (str, optional): Type of system of equations chosen. It determines how to construct the LinearSOE
and LinearSolver objects to store
and solve the system of equations
in the analysis.
163 For more information, see the OpenSeesPy documentation. Defaults to
"BandGeneral".
164 @param analysis_type (str, optional): Type of analysis chosen. It determines how to construct the Analysis object, which defines what type of analysis
is to be performed.
165 For more information, see the OpenSeesPy documentation. Defaults to
"Static".
166 @param show_plot (bool, optional): Option to show the
'Horizontal displacement vs. Horizontal loading' curve after the analysis. Defaults to
True.
167 @param block (bool, optional): Option to wait the user command
'plt.show()' (avoiding the stop of the program everytime that a plot should pop up). Defaults to
False.
169 @exception WrongDimension: The dimension of the loaded_nodes
and Fx arguments needs to be the same.
170 @exception NegativeValue: The ID of timeSeries_ID needs to be a positive integer.
171 @exception NegativeValue: The ID of pattern_ID needs to be a positive integer.
172 @exception NegativeValue: The ID of fiber_ID_analysed needs to be a positive integer.
174 if len(loaded_nodes) != len(Fx):
raise WrongDimension()
175 if timeSeries_ID < 1:
raise NegativeValue()
176 if pattern_ID < 1:
raise NegativeValue()
177 if fiber_ID_analysed != -1
and fiber_ID_analysed < 1:
raise NegativeValue()
180 opsplt.createODB(self.
name_ODBname_ODB,
"LateralForce");
181 if fiber_ID_analysed != -1: opsplt.saveFiberData2D(self.
name_ODBname_ODB,
"LateralForce", fiber_ID_analysed, fiber_section)
184 timeSeries(timeSeries_type, timeSeries_ID)
185 pattern(pattern_type, timeSeries_ID, pattern_ID)
186 for ii, node_ID
in enumerate(loaded_nodes):
187 load(node_ID, Fx[ii], 0.0, 0.0)
191 constraints(constraints_type)
192 numberer(numberer_type)
195 integrator(
"LoadControl", force)
198 analysis(analysis_type)
201 dataLF = np.zeros((n_step+1,2))
203 print(
"Lateral Force analysis starts")
204 for iteration
in range(n_step):
207 if convergence != 0:
break
208 dataLF[iteration+1,0] = nodeDisp(loaded_nodes[0], 1)/mm_unit
209 dataLF[iteration+1,1] = getLoadFactor(pattern_ID)*Fx[0]/kN_unit
212 plt.plot(dataLF[:,0], dataLF[:,1])
213 plt.xlabel(
'Lateral Displacement [mm]')
214 plt.ylabel(
'Lateral Load [kN]')
215 plt.title(
'Lateral force curve')
219 loadConst(
"-time", 0.0)
222 print(
"Lateral force complete")
228 def Pushover(self, CtrlNode: int, Dmax, Dincr, timeSeries_ID: int, pattern_ID: int, Fx = 1*kN_unit, ele_fiber_ID_analysed = -1, fiber_section = 1,
229 timeSeries_type =
"Linear", pattern_type =
"Plain", constraints_type =
"Plain", numberer_type =
"RCM", system_type =
"UmfPack", analysis_type =
"Static",
230 show_plot =
True, block =
False):
232 Method to perform a pushover analysis (displacement-control). If this method is called, the LoadingProtocol
and LateralForce methods should be avoided.
234 @param CtrlNode (int): The node that will be used to impose the displacement Dmax of the pushover analysis.
235 If the show_plot option
is True, the curve displayed follows this node.
236 @param Dmax (float): The imposed displacement.
237 @param Dincr (float): The incremental displacement to reach Dmax. To converge, it should be small enough (1000 times smaller of Dmax).
238 @param timeSeries_ID (int): ID of the timeseries.
239 @param pattern_ID (int): ID of the pattern.
240 @param Fx (float, optional): The force imposed at the control node CtrlNode. It
is used
for convergence reasons
and it can be arbitrarly small.
241 Defaults to 1*kN_unit.
242 @param ele_fiber_ID_analysed (int, optional): The ID of the analysed element
with fibers. If fibers are present
in the model
and the user wants to save ODB data
243 (to use
in the post-processing
with for example FiberResponse), assign to this argument the ID of the element
with fibers chosen.
244 -1 will ignore the storage of data
for fibers. Defaults to -1.
245 @param fiber_section (int, optional): The section number, i.e. the Gauss integratio number.
246 If the fiber_ID_analysed
is equal to -1, this argument
is not used. Defaults to 1.
247 @param timeSeries_type (str, optional): Type of timeseries chosen.
248 For more information, see the OpenSeesPy documentation. Defaults to
"Linear".
249 @param pattern_type (str, optional): Type of pattern chosen.
250 For more information, see the OpenSeesPy documentation. Defaults to
"Plain".
251 @param constraints_type (str, optional): Type of contraints chosen. It detemines how the constraint equations are enforced
in the analysis.
252 For more information, see the OpenSeesPy documentation. Defaults to
"Plain".
253 @param numberer_type (str, optional): Type of numberer chosen. It determines the mapping between equation numbers
and degrees-of-freedom.
254 For more information, see the OpenSeesPy documentation. Defaults to
"RCM".
255 @param system_type (str, optional): Type of system of equations chosen. It determines how to construct the LinearSOE
and LinearSolver objects to store
and solve the system of equations
in the analysis.
256 For more information, see the OpenSeesPy documentation. Defaults to
"UmfPack".
257 @param analysis_type (str, optional): Type of analysis chosen. It determines how to construct the Analysis object, which defines what type of analysis
is to be performed.
258 For more information, see the OpenSeesPy documentation. Defaults to
"Static".
259 @param show_plot (bool, optional): Option to show the
'lateral displacement vs. lateral loading' curve after the analysis. Defaults to
True.
260 @param block (bool, optional): Option to wait the user command
'plt.show()' (avoiding the stop of the program everytime that a plot should pop up). Defaults to
False.
262 @exception NegativeValue: The ID of CtrlNode needs to be a positive integer.
263 @exception NegativeValue: The ID of timeSeries_ID needs to be a positive integer.
264 @exception NegativeValue: The ID of pattern_ID needs to be a positive integer.
265 @exception NegativeValue: The ID of ele_fiber_ID_analysed needs to be a positive integer
if is different
from -1.
267 if CtrlNode < 1:
raise NegativeValue()
268 if timeSeries_ID < 1:
raise NegativeValue()
269 if pattern_ID < 1:
raise NegativeValue()
270 if ele_fiber_ID_analysed != -1
and ele_fiber_ID_analysed < 1:
raise NegativeValue()
273 opsplt.createODB(self.
name_ODBname_ODB,
"Pushover");
274 if ele_fiber_ID_analysed != -1: opsplt.saveFiberData2D(self.
name_ODBname_ODB,
"Pushover", ele_fiber_ID_analysed, fiber_section)
277 timeSeries(timeSeries_type, timeSeries_ID)
278 pattern(pattern_type, timeSeries_ID, pattern_ID)
279 load(CtrlNode, Fx, 0.0, 0.0)
280 Nsteps = int(abs(Dmax/Dincr))
283 constraints(constraints_type)
284 numberer(numberer_type)
287 integrator(
"LoadControl", 1)
289 analysis(analysis_type)
292 dataPO = np.zeros((Nsteps+1,2))
295 print(
"Pushover analysis starts")
296 for iteration
in range(Nsteps):
298 convergence = self.
__LatDispCtrlLoop__LatDispCtrlLoop(CtrlNode, Dincr, iteration,
300 if convergence != 0:
break
301 dataPO[iteration+1,0] = nodeDisp(CtrlNode, 1)/mm_unit
302 dataPO[iteration+1,1] = getLoadFactor(pattern_ID)*Fx/kN_unit
305 plt.plot(dataPO[:,0], dataPO[:,1])
306 plt.xlabel(
'Horizontal Displacement [mm]')
307 plt.ylabel(
'Horizontal Load [kN]')
308 plt.title(
'Pushover curve')
313 print(
"Pushover complete")
319 def LoadingProtocol(self, CtrlNode: int, discr_LP: np.ndarray, timeSeries_ID: int, pattern_ID: int, Fx = 1*kN_unit, ele_fiber_ID_analysed = -1, fiber_section = 1,
320 timeSeries_type =
"Linear", pattern_type =
"Plain", constraints_type =
"Plain", numberer_type =
"RCM", system_type =
"UmfPack", analysis_type =
"Static",
321 show_plot =
True, block =
False):
323 Method to perform a loading protocol analysis (displacement-control). If this method is called, the Pushover
and LateralForce methods should be avoided.
325 @param CtrlNode (int): The node that will be used to impose the displacement
from the discr_LP to perform the analysis.
326 @param discr_LP (np.ndarray): The loading protocol array (1 dimension) discretised. It needs to be filled
with imposed displacement,
not SDR.
327 Use the functions DiscretizeLoadProtocol
and DiscretizeLinearly
in FunctionalFeatures module to help create
and/
or discretise one.
328 @param timeSeries_ID (int): ID of the timeseries.
329 @param pattern_ID (int): ID of the pattern.
330 @param Fx (float, optional): The force imposed at the control node CtrlNode. It
is used
for convergence reasons
and it can be arbitrarly small.
331 Defaults to 1*kN_unit.
332 @param ele_fiber_ID_analysed (int, optional): The ID of the analysed element
with fibers. If fibers are present
in the model
and the user wants to save ODB data
333 (to use
in the post-processing
with for example FiberResponse), assign to this argument the ID of the element
with fibers chosen.
334 -1 will ignore the storage of data
for fibers. Defaults to -1.
335 @param fiber_section (int, optional): The section number, i.e. the Gauss integratio number.
336 If the fiber_ID_analysed
is equal to -1, this argument
is not used. Defaults to 1.
337 @param timeSeries_type (str, optional): Type of timeseries chosen.
338 For more information, see the OpenSeesPy documentation. Defaults to
"Linear".
339 @param pattern_type (str, optional): Type of pattern chosen.
340 For more information, see the OpenSeesPy documentation. Defaults to
"Plain".
341 @param constraints_type (str, optional): Type of contraints chosen. It detemines how the constraint equations are enforced
in the analysis.
342 For more information, see the OpenSeesPy documentation. Defaults to
"Plain".
343 @param numberer_type (str, optional): Type of numberer chosen. It determines the mapping between equation numbers
and degrees-of-freedom.
344 For more information, see the OpenSeesPy documentation. Defaults to
"RCM".
345 @param system_type (str, optional): Type of system of equations chosen. It determines how to construct the LinearSOE
and LinearSolver objects to store
and solve the system of equations
in the analysis.
346 For more information, see the OpenSeesPy documentation. Defaults to
"UmfPack".
347 @param analysis_type (str, optional): Type of analysis chosen. It determines how to construct the Analysis object, which defines what type of analysis
is to be performed.
348 For more information, see the OpenSeesPy documentation. Defaults to
"Static".
349 @param show_plot (bool, optional): Option to show the
'lateral displacement vs. lateral loading' curve after the analysis. Defaults to
True.
350 @param block (bool, optional): Option to wait the user command
'plt.show()' (avoiding the stop of the program everytime that a plot should pop up). Defaults to
False.
352 @exception NegativeValue: The ID of CtrlNode needs to be a positive integer.
353 @exception NegativeValue: The ID of timeSeries_ID needs to be a positive integer.
354 @exception NegativeValue: The ID of pattern_ID needs to be a positive integer.
355 @exception NegativeValue: The ID of fiber_ID_analysed needs to be a positive integer
if is different
from -1.
357 if CtrlNode < 1:
raise NegativeValue()
358 if timeSeries_ID < 1:
raise NegativeValue()
359 if pattern_ID < 1:
raise NegativeValue()
360 if ele_fiber_ID_analysed != -1
and ele_fiber_ID_analysed < 1:
raise NegativeValue()
363 opsplt.createODB(self.
name_ODBname_ODB,
"LoadingProtocol");
364 if ele_fiber_ID_analysed != -1: opsplt.saveFiberData2D(self.
name_ODBname_ODB,
"LoadingProtocol", ele_fiber_ID_analysed, fiber_section)
367 timeSeries(timeSeries_type, timeSeries_ID)
368 pattern(pattern_type, timeSeries_ID, pattern_ID)
369 load(CtrlNode, Fx, 0.0, 0.0)
371 Nsteps = np.size(discr_LP)
374 constraints(constraints_type)
375 numberer(numberer_type)
378 integrator(
"LoadControl", 1)
380 analysis(analysis_type)
383 dataLP = np.zeros((Nsteps+1,2))
386 print(
"Loading Protocol analysis starts")
387 for iteration
in range(Nsteps):
389 dU_next = discr_LP[iteration]
390 dU = dU_next - dU_prev
396 if convergence != 0:
break
397 dataLP[iteration+1,0] = nodeDisp(CtrlNode, 1)/mm_unit
398 dataLP[iteration+1,1] = getLoadFactor(pattern_ID)*Fx/kN_unit
401 plt.plot(dataLP[:,0], dataLP[:,1])
402 plt.xlabel(
'Horizontal Displacement [mm]')
403 plt.ylabel(
'Horizontal Load [kN]')
404 plt.title(
'Loading Protocol curve')
409 print(
"Loading Protocol complete")
410 self.
load_caseload_case =
"LoadingProtocol"
415 def __LoadCtrlLoop(self, force, iteration: int, algo =
"KrylovNewton", test_type =
"NormDispIncr", tol = TOL, test_opt = 0, max_iter = MAX_ITER):
417 PRIVATE METHOD. It is used perform one load increment
'force' load-control analysis step using
'algo' and 'test_type' as algorithm
and test.
418 The integrator
is LoadControl. If convergence issues are encountered, the method performa a convergence analysis trying different ways to converge.
420 @param force (dougle): The load increment performed.
421 @param iteration (int): The current iteration.
422 @param algo (str, optional): Type of alghoritm chosen
for the analysis. It detemines how to construct a SolutionAlgorithm object, which determines the sequence of steps taken to solve the non-linear equation.
423 For more information on the available types, see the OpenSeesPy documentation. Defaults to
"KrylovNewton".
424 @param test_type (str, optional): Type of test chosen
for the analysis. It determines how to construct a ConvergenceTest object.
425 Certain SolutionAlgorithm objects require a ConvergenceTest object to determine
if convergence has been achieved at the end of an iteration step.
426 For more information on the available types, see the OpenSeesPy documentation. Defaults to
"NormDispIncr".
427 @param tol (float, optional): Tolerance criteria used to check
for convergence. Defaults to TOL (
from Constants Module).
428 @param test_opt (int, optional): Print-flag
from 0 to 5 used to receive more info during the iteration
429 (
for example: 0
print nothing
and 2
print information on norms
and number of iterations at end of successful test).
430 For more information, see the OpenSeesPy documentation. Defaults to 0.
431 @param max_iter (float, optional): Maximal number of iterations to check. Defaults to MAX_ITER (
from Constants Module).
433 @exception NegativeValue: iteration needs to be a positive integer.
434 @exception NegativeValue: tol needs to be positive.
435 @exception NegativeValue: max_iter needs to be positive.
437 @returns int: 0
if the interation converged.
439 if iteration < 0:
raise NegativeValue()
440 if tol < 0:
raise NegativeValue()
441 if max_iter < 0:
raise NegativeValue()
444 integrator(
"LoadControl", force)
446 test(test_type, tol, max_iter, test_opt)
449 convergence = analyze(1)
453 print(
"---------------------------------------------------------------------------------------")
454 print(
"Vertical Load-control analysis failed at iteration {}".format(iteration))
455 print(
"Convergence analysis starts")
456 print(
"---------------------------------------------------------------------------------------")
460 convergence = _ConvergenceTest(
"KrylovNewton",
"NormDispIncr", tol, max_iter, test_opt)
464 convergence = _ConvergenceTest(
"KrylovNewton",
"NormDispIncr", tol*10, max_iter*10, test_opt)
468 convergence = _ConvergenceTest(
"KrylovNewton",
"EnergyIncr", tol, max_iter, test_opt)
472 convergence = _ConvergenceTest(
"KrylovNewton",
"EnergyIncr", tol*10, max_iter*10, test_opt)
476 convergence = _ConvergenceTest(
"Newton",
"NormDispIncr", tol, max_iter, test_opt)
480 convergence = _ConvergenceTest(
"Newton",
"NormDispIncr", tol*10, max_iter*10, test_opt)
484 convergence = _ConvergenceTest(
"Newton",
"EnergyIncr", tol, max_iter, test_opt)
488 convergence = _ConvergenceTest(
"Newton",
"EnergyIncr", tol*10, max_iter*10, test_opt)
492 convergence = _ConvergenceTest(
"ModifiedNewton",
"NormDispIncr", tol, max_iter, test_opt)
496 convergence = _ConvergenceTest(
"ModifiedNewton",
"NormDispIncr", tol*10, max_iter*10, test_opt)
500 convergence = _ConvergenceTest(
"ModifiedNewton",
"EnergyIncr", tol, max_iter, test_opt)
504 convergence = _ConvergenceTest(
"ModifiedNewton",
"EnergyIncr", tol*10, max_iter*10, test_opt)
508 print(
"#############################################################################")
509 print(
"NO CONVERGENCE! Load-control analysis stops at iteration {} ".format(iteration))
510 print(
"#############################################################################")
513 print(
"Convergence reached, convergence analysis ends.")
518 def __LatDispCtrlLoop(self, CtrlNode, dU, iteration, algo = "KrylovNewton", test_type = "NormDispIncr", tol = TOL, test_opt = 0, max_iter = MAX_ITER, allow_smaller_step = False):
520 PRIVATE METHOD. It is used perform one imposed displacement increment
'dU' displacement-control analysis step using
'algo' and 'test_type' as algorithm
and test.
521 The integrator
is DisplacementControl. If convergence issues are encountered, the method performa a convergence analysis trying different ways to converge.
523 @param CtrlNode ([type]): [description]
524 @param dU (float): The imposed displacement increment
for the current iteration
525 @param iteration (int): The current iteration.
526 @param algo (str, optional): Type of alghoritm chosen
for the analysis. It detemines how to construct a SolutionAlgorithm object, which determines the sequence of steps taken to solve the non-linear equation.
527 For more information on the available types, see the OpenSeesPy documentation. Defaults to
"KrylovNewton".
528 @param test_type (str, optional): Type of test chosen
for the analysis. It determines how to construct a ConvergenceTest object.
529 Certain SolutionAlgorithm objects require a ConvergenceTest object to determine
if convergence has been achieved at the end of an iteration step.
530 For more information on the available types, see the OpenSeesPy documentation. Defaults to
"NormDispIncr".
531 @param tol (float, optional): Tolerance criteria used to check
for convergence. Defaults to TOL (
from Constants Module).
532 @param test_opt (int, optional): Print-flag
from 0 to 5 used to receive more info during the iteration
533 (
for example: 0
print nothing
and 2
print information on norms
and number of iterations at end of successful test).
534 For more information, see the OpenSeesPy documentation. Defaults to 0.
535 @param max_iter (float, optional): Maximal number of iterations to check. Defaults to MAX_ITER (
from Constants Module).
536 @param allow_smaller_step (bool, optional): Allow smaller steps
in the displacement-control analysis. Defaults to
False.
538 @exception NegativeValue: iteration needs to be a positive integer.
539 @exception NegativeValue: tol needs to be positive.
540 @exception NegativeValue: max_iter needs to be positive.
542 @returns int: 0
if the interation converged.
544 if iteration < 0:
raise NegativeValue()
545 if tol < 0:
raise NegativeValue()
546 if max_iter < 0:
raise NegativeValue()
550 integrator(
"DisplacementControl", CtrlNode, CtrlDOF, dU, 1, dU, dU)
551 test(test_type, tol, max_iter, test_opt)
554 convergence = analyze(1)
558 print(
"---------------------------------------------------------------------------------------")
559 print(
"Lateral Displacement-control analysis failed at iteration {} and control node lateral displacement = {} mm.".format(iteration, nodeDisp(CtrlNode, CtrlDOF)/mm_unit))
560 print(
"Convergence analysis starts")
561 print(
"---------------------------------------------------------------------------------------")
565 convergence = _ConvergenceTest(
"KrylovNewton",
"NormDispIncr", tol, max_iter, test_opt)
569 convergence = _ConvergenceTest(
"KrylovNewton",
"NormDispIncr", tol*10, max_iter*10, test_opt)
573 convergence = _ConvergenceTest(
"KrylovNewton",
"EnergyIncr", tol, max_iter, test_opt)
577 convergence = _ConvergenceTest(
"KrylovNewton",
"EnergyIncr", tol*10, max_iter*10, test_opt)
581 convergence = _ConvergenceTest(
"Newton",
"NormDispIncr", tol, max_iter, test_opt)
585 convergence = _ConvergenceTest(
"Newton",
"NormDispIncr", tol*10, max_iter*10, test_opt)
589 convergence = _ConvergenceTest(
"Newton",
"EnergyIncr", tol, max_iter, test_opt)
593 convergence = _ConvergenceTest(
"Newton",
"EnergyIncr", tol*10, max_iter*10, test_opt)
597 convergence = _ConvergenceTest(
"ModifiedNewton",
"NormDispIncr", tol, max_iter, test_opt)
601 convergence = _ConvergenceTest(
"ModifiedNewton",
"NormDispIncr", tol*10, max_iter*10, test_opt)
605 convergence = _ConvergenceTest(
"ModifiedNewton",
"EnergyIncr", tol, max_iter, test_opt)
609 convergence = _ConvergenceTest(
"ModifiedNewton",
"EnergyIncr", tol*10, max_iter*10, test_opt)
611 if convergence != 0
and allow_smaller_step:
612 print(
"Use smaller steps")
613 print(
"10 times more intergator iteration, min_dU = dU/10")
614 integrator(
"DisplacementControl", CtrlNode, CtrlDOF, dU, 10, dU/10, dU)
618 convergence = _ConvergenceTest(
"KrylovNewton",
"NormDispIncr", tol, max_iter, test_opt)
622 convergence = _ConvergenceTest(
"KrylovNewton",
"EnergyIncr", tol, max_iter, test_opt)
626 convergence = _ConvergenceTest(
"Newton",
"NormDispIncr", tol, max_iter, test_opt)
630 convergence = _ConvergenceTest(
"Newton",
"EnergyIncr", tol, max_iter, test_opt)
634 convergence = _ConvergenceTest(
"ModifiedNewton",
"NormDispIncr", tol, max_iter, test_opt)
638 convergence = _ConvergenceTest(
"ModifiedNewton",
"EnergyIncr", tol, max_iter, test_opt)
642 print(
"#############################################################################")
643 print(
"NO CONVERGENCE! Lateral Displacement-control analysis stops at iteration {} and control node lateral displacement = {} mm.".format(iteration, nodeDisp(CtrlNode, CtrlDOF)/mm_unit))
644 print(
"#############################################################################")
647 print(
"Convergence reached, convergence analysis ends.")
654 Method that shows the final deformed shape of the model. It can also show the animation that shows how the model behaved during the analysis.
656 @param scale (int, optional): The scaling factor to magnify the deformation. The value should be adjusted
for each model. Defaults to 1.
657 @param animate (bool, optional): Option to show the animation of the model during the analysis. Defaults to
False.
658 @param dt (float, optional): The time step between every iteration. Defaults to 0.01.
660 @exception NameError: The methods
for the analysis were
not called.
662 if self.
load_caseload_case ==
"None":
raise NameError(
"The analysis is not complete.")
665 opsplt.plot_deformedshape(Model = self.
name_ODBname_ODB, LoadCase=self.
load_caseload_case, scale = scale)
667 opsplt.animate_deformedshape(Model = self.
name_ODBname_ODB, LoadCase=self.
load_caseload_case, dt = dt, scale = scale)
670 def FiberResponse(self, ele_fiber_ID_analysed: int, fiber_section = 1, animate_stress =
False, animate_strain =
False, fps = 25):
672 Method that shows the final stress response of the fiber section chosen.
673 It can also show the animation that shows how the fiber section behaved during the analysis. The fiber ID and section needs to be recorded during the analysis,
674 thus
if the method LateralForce, Pushover
or LoadingProtocol was used, the same fiber ID
and section need to be used.
676 @param ele_fiber_ID_analysed (int): The ID of the analysed fiber. If fibers are present
in the model
and the user wants to save ODB data
677 (to use
in the post-processing
with for example FiberResponse), assign to this argument the ID of the fiber chosen.
678 -1 will ignore the storage of data
for fibers.
679 @param fiber_section (int, optional): The section number, i.e. the Gauss integratio number.
680 If the fiber_ID_analysed
is equal to -1, this argument
is not used. Defaults to 1.
681 @param animate_stress (bool, optional): Option to show the animation of the fiber stress during the analysis. Defaults to
False.
682 @param animate_strain (bool, optional): Option to show the animation of the fiber strain during the analysis. Defaults to
False.
683 @param fps (int, optional): Number of frame per seconds
for the animations. Defaults to 25.
684 @exception NameError: The methods
for the analysis were
not called.
686 if self.
load_caseload_case ==
"None":
raise NameError(
"The analysis is not complete.")
688 opsplt.plot_fiberResponse2D(self.
name_ODBname_ODB, self.
load_caseload_case, ele_fiber_ID_analysed, fiber_section, InputType =
'stress')
690 ani1 = opsplt.animate_fiberResponse2D(self.
name_ODBname_ODB, self.
load_caseload_case, ele_fiber_ID_analysed, fiber_section, InputType =
'stress', fps = fps)
692 ani1 = opsplt.animate_fiberResponse2D(self.
name_ODBname_ODB, self.
load_caseload_case, ele_fiber_ID_analysed, fiber_section, InputType =
'strain', fps = fps)
695def _ConvergenceTest(algo_type: str, test_type: str, tol, max_iter, test_opt = 0):
697 PRIVATE FUNCTION. It is used during the convergence analysis to test different ways to reach convergence.
699 @param algo_type (str): Type of alghoritm chosen
for the analysis. It detemines how to construct a SolutionAlgorithm object, which determines the sequence of steps taken to solve the non-linear equation.
700 For more information on the available types, see the OpenSeesPy documentation.
701 @param test_type (str): Type of test chosen
for the analysis. It determines how to construct a ConvergenceTest object.
702 Certain SolutionAlgorithm objects require a ConvergenceTest object to determine
if convergence has been achieved at the end of an iteration step.
703 For more information on the available types, see the OpenSeesPy documentation.
704 @param tol (float): Tolerance criteria used to check
for convergence.
705 @param max_iter (float): Maximal number of iterations to check.
706 @param test_opt (int, optional): Print-flag
from 0 to 5 used to receive more info during the iteration
707 (
for example: 0
print nothing
and 2
print information on norms
and number of iterations at end of successful test).
708 For more information, see the OpenSeesPy documentation. Defaults to 0.
710 @returns int: 0
if the interation converged.
712 print("algorithm: {}".format(algo_type))
713 print(
"test: {}, tol = {}, max iter = {}".format(test_type, tol, max_iter))
714 test(test_type, tol, max_iter, test_opt)
Class dedicated to the analysis of the OpenSeesPy model.
def LateralForce(self, list loaded_nodes, list Fx, int timeSeries_ID, int pattern_ID, n_step=1000, fiber_ID_analysed=-1, fiber_section=1, timeSeries_type="Linear", pattern_type="Plain", constraints_type="Plain", numberer_type="RCM", system_type="BandGeneral", analysis_type="Static", show_plot=True, block=False)
Method to perform the lateral force analyisis with lateral loading (load-control).
def LoadingProtocol(self, int CtrlNode, np.ndarray discr_LP, int timeSeries_ID, int pattern_ID, Fx=1 *kN_unit, ele_fiber_ID_analysed=-1, fiber_section=1, timeSeries_type="Linear", pattern_type="Plain", constraints_type="Plain", numberer_type="RCM", system_type="UmfPack", analysis_type="Static", show_plot=True, block=False)
Method to perform a loading protocol analysis (displacement-control).
def __LoadCtrlLoop(self, force, int iteration, algo="KrylovNewton", test_type="NormDispIncr", tol=TOL, test_opt=0, max_iter=MAX_ITER)
def Pushover(self, int CtrlNode, Dmax, Dincr, int timeSeries_ID, int pattern_ID, Fx=1 *kN_unit, ele_fiber_ID_analysed=-1, fiber_section=1, timeSeries_type="Linear", pattern_type="Plain", constraints_type="Plain", numberer_type="RCM", system_type="UmfPack", analysis_type="Static", show_plot=True, block=False)
Method to perform a pushover analysis (displacement-control).
def __init__(self, str data_dir, str name_ODB, algo="KrylovNewton", test_type="NormDispIncr", test_opt=0, max_iter=MAX_ITER, tol=TOL, allow_smaller_step=False)
The constructor of the class.
def DeformedShape(self, scale=1, animate=False, dt=0.01)
Method that shows the final deformed shape of the model.
def Gravity(self, list loaded_nodes, list Fy, int timeSeries_ID, int pattern_ID, n_step=10, timeSeries_type="Linear", pattern_type="Plain", constraints_type="Plain", numberer_type="RCM", system_type="BandGeneral", analysis_type="Static", show_plot=False)
Method to perform the gravity analyisis with vertical loadings (load-control).
def FiberResponse(self, int ele_fiber_ID_analysed, fiber_section=1, animate_stress=False, animate_strain=False, fps=25)
Method that shows the final stress response of the fiber section chosen.
def __LatDispCtrlLoop(self, CtrlNode, dU, iteration, algo="KrylovNewton", test_type="NormDispIncr", tol=TOL, test_opt=0, max_iter=MAX_ITER, allow_smaller_step=False)
def ProgressingPercentage(max_iter, int i, int next_step, step=10)
Function that shows the progressing percentage of an iterative process.