Module beef.newmark
Newmark time simulation module
Expand source code
"""
Newmark time simulation module
===============================
"""
import numpy as np
from scipy.linalg import solve
def is_converged(values, tols, scaling=None):
"""
Check whether multiple values are below specified tolerances. (value/scaling)
Arguments
-----------------
values : double
list of values to check
tols : double
corresponding list of tolerances to compare values to
scaling : double, optional
corresponding list of scaling of values
Returns
-----------------
ok : boolean
converged or not?
Notes
--------------------
If entry in tols is None, the corresponding value is assumed to pass tolerance criterion.
If entry in tols is different than None, the value pass if value <= tol * scaling.
"""
if scaling is None:
scaling = np.ones([len(tols)])
for ix, value in enumerate(values):
if (tols[ix] is not None) and (value>(tols[ix]*scaling[ix])):
return False
return True
def residual(f, f_int, C, M, udot, uddot):
return f - (M @ uddot + C @ udot + f_int)
def residual_hht(f, f_prev, f_int, f_int_prev, K, C, M, u_prev, udot, udot_prev, uddot, alpha, gamma, beta, dt):
return (1+alpha)*f - alpha*f_prev - ((1+alpha)*f_int - alpha*f_int_prev + C @ ((1+alpha)*udot - alpha*udot_prev) + M @ uddot)
def effective_mass(M, C, K, dt, gamma, beta, alpha=0.0):
return M + C*gamma*dt*(1+alpha) + K*beta*dt**2*(1+alpha)
def acc_estimate(K, C, M, f, udot, u=None, f_int=None, dt=None, beta=None, gamma=None):
"""
Predict acceleration for time integration, based on internal forces,
damping matrix, mass matrix, current velocity and external force.
Arguments
-----------
K : double
Next-step (tangent) stiffness matrix (time step k+1),
ndofs-by-ndofs Numpy array.
C : double
Damping matrix, ndofs-by-ndofs Numpy array.
M : double
Mass matrix, ndofs-by-ndofs Numpy array.
f : double
Current external forces (time step k), ndofs-by-1 Numpy array.
udot : double
Velocity at chosen time instance, ndofs-by-1 Numpy array.
u : optional, double
Displacement at chosen time instance, ndofs-by-1 Numpy array.
f_int : optional, double
Current internal forces (time step k). Equal K @ u if not given,
ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
beta : double
Scalar value specifying the beta parameter.
gamma : double
Scalar value specifying the gamma parameter.
Returns
-----------
uddot : double
Resulting acceleration array, ndofs-by-1 Numpy array.
"""
if f_int is None: # assume linear system/solution
if u is not None:
f_int = K @ u
else:
raise ValueError('Input _either_ f_int or u!')
acc = solve(M, f - C @ udot - f_int)
return acc
def pred(u, udot, uddot, dt, beta=0, gamma=0):
"""
Predictor step in non-linear Newmark algorithm.
Arguments
-----------
u : double
Current displacement (time step k), ndofs-by-1 Numpy array.
udot : double
Current velocity (time step k), ndofs-by-1 Numpy array.
uddot : double
Current acceleration (time step k), ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
beta : double
Beta Newmark parameter. In Chatzi implementation,
this is included in predictor as well as corrector - in Krenk,
it is only used in corrector. The chosen values (0) are based
on Krenk's approach.
gamma : double
gamma Newmark parameter. In Chatzi implementation,
this is included in predictor as well as corrector - in Krenk,
it is only used in corrector. The chosen values (0) are based
on Krenk's approach.
Returns
-----------
u : double
Predicted next-step displacement (time step k+1), ndofs-by-1 Numpy array.
udot : double
Predicted next-step velocity (time step k+1), ndofs-by-1 Numpy array.
uddot : double
Predicted next-step acceleration (time step k+1), ndofs-by-1 Numpy array.
(Input uddot is output without modifications)
"""
du = dt*udot + (0.5-beta)*dt**2*uddot
u = u + du
udot = udot + (1-gamma)*dt*uddot
return u, udot, uddot, du
def corr(r, K, C, M, u, udot, uddot, dt, beta, gamma):
"""
Corrector step in non-linear Newmark algorithm.
Arguments
-----------
r : double
Residual forces.
K : double
Next-step (tangent) stiffness matrix (time step k+1),
ndofs-by-ndofs Numpy array.
C : double
Damping matrix, ndofs-by-ndofs Numpy array.
M : double
Mass matrix, ndofs-by-ndofs Numpy array.
u : double
Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot : double
Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot : double
Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
beta : double
Scalar value specifying the beta parameter.
gamma : double
Scalar value specifying the gamma parameter.
Returns
-----------
u : double
Predicted next-step displacement, time step k+1, iteration i+1, ndofs-by-1 Numpy array.
udot : double
Predicted next-step velocity, time step k+1, iteration i+1, ndofs-by-1 Numpy array.
uddot : double
Predicted next-step acceleration, time step k+1), iteration i+1, ndofs-by-1 Numpy array.
norm_r : double
Frobenius norm of residual force vector
norm_u : double
Frobenius norm of added displacement
"""
K_eff = K + (gamma*dt)/(beta*dt**2)*C + 1/(beta*dt**2)*M
du = solve(K_eff, r)
u = u + du
udot = udot + gamma*dt/(beta*dt**2)*du
uddot = uddot + 1/(beta*dt**2)*du
return u, udot, uddot, du
def corr_alt(r, K, C, M, u, udot, uddot, dt, beta, gamma, alpha=0.0):
"""
Corrector step in non-linear Newmark algorithm. Alternative version - uses Meff rather than Keff and allows for alpha damping.
Arguments
-----------
r : double
Residual forces.
K : double
Next-step (tangent) stiffness matrix (time step k+1),
ndofs-by-ndofs Numpy array.
C : double
Damping matrix, ndofs-by-ndofs Numpy array.
M : double
Mass matrix, ndofs-by-ndofs Numpy array.
u : double
Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot : double
Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot : double
Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
beta : double
Scalar value specifying the beta parameter.
gamma : double
Scalar value specifying the gamma parameter.
Returns
-----------
u : double
Predicted next-step displacement, time step k+1, iteration i+1, ndofs-by-1 Numpy array.
udot : double
Predicted next-step velocity, time step k+1, iteration i+1, ndofs-by-1 Numpy array.
uddot : double
Predicted next-step acceleration, time step k+1), iteration i+1, ndofs-by-1 Numpy array.
norm_r : double
Frobenius norm of residual force vector
norm_u : double
Frobenius norm of added displacement
"""
Meff = effective_mass(M, C, K, dt, gamma, beta, alpha)
duddot = solve(Meff, r)
uddot = uddot + duddot
udot = udot + duddot*gamma*dt
du = duddot * beta*dt**2
u = u + du
return u, udot, uddot, du
def dnewmark(K, C, M, f, u, udot, uddot, dt, f_int=None, beta=1.0/4.0, gamma=0.5,
tol_u=1e-5, tol_r=1e-5, itmax=10):
"""
Combined stepwise non-linear Newmark (predictor-corrector),
based on Algorithm 9.2 in Krenk, 2009. Because f_int is not updated each iteration
this is equivalent to modified NR iteration.
Arguments
-----------
K : double
Next-step (tangent) stiffness matrix (time step k+1),
ndofs-by-ndofs Numpy array.
C : double
Damping matrix, ndofs-by-ndofs Numpy array.
M : double
Mass matrix, ndofs-by-ndofs Numpy array.
f : double
Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u : double
Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot : double
Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot : double
Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
f_int : optional, double
Current internal forces (time step k). Equal K @ u if not given,
ndofs-by-1 Numpy array.
beta : 1/4, double
Scalar value specifying the beta parameter.
gamma : 0.5, double
Scalar value specifying the gamma parameter.
tol_u : 1e-5, double
Convergence satisfied when |du_{k+1}| < tol_u.
tol_r : 1e-5, double
Convergence satisfied when |dr_{k+1}| < tol_r.
itmax : 10, int
Maximum number of iterations allowed per time step / increment.
Returns
-----------
u : double
Predicted displacement at time step k+1, ndofs-by-1 Numpy array.
udot : double
Predicted velocity at time step k+1, ndofs-by-1 Numpy array.
uddot : double
Predicted acceleration at time step k+1, ndofs-by-1 Numpy array.
References:
--------------------
:cite:`Krenk2009`
Other:
--------------
Because predictor and corrector steps are both included,
only modified Newton-Raphson is possible (can't update tangent stiffness
each iteration), because that would require updating model and reassembly of system.
Use newmark.pred and newmark.corr separately for full non-linear Newton-Raphson.
"""
# If no internal stiffness force is provided, assume linear system => f_int = K u
if f_int is None:
f_int = K @ u
# Predictor step and initial residual calc
u, udot, uddot, du = pred(u, udot, uddot, dt)
f_int += K @ du
r = residual(f, f_int, C, M, udot, uddot)
# Loop through iterations until convergence is met
for it in range(itmax):
# Corrector step
u, udot, uddot, du = corr(r, K, C, M, u, udot, uddot, dt, beta, gamma)
# Update internal forces and calculate residual
f_int += K @ du
r = residual(f, f_int, C, M, udot, uddot)
# Check convergence and break if convergence is met
converged = is_converged([np.linalg.norm(du), np.linalg.norm(r)],
[tol_u, tol_r])
if converged:
break
return u, udot, uddot
def dnewmark_hht(K, C, M, f, u, udot, uddot, dt, f_prev, f_int=None, beta=1.0/4.0, gamma=0.5, alpha=0.0,
tol_u=1e-5, tol_r=1e-5, itmax=10):
"""
Incremental formulation of Newmark allowing for alpha-damping.
Arguments
-----------
K : double
Next-step (tangent) stiffness matrix (time step k+1),
ndofs-by-ndofs Numpy array.
C : double
Damping matrix, ndofs-by-ndofs Numpy array.
M : double
Mass matrix, ndofs-by-ndofs Numpy array.
f : double
Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u : double
Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot : double
Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot : double
Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
f_int : optional, double
Current internal forces (time step k). Equal K @ u if not given,
ndofs-by-1 Numpy array.
beta : 1/4, double
Scalar value specifying the beta parameter.
gamma : 0.5, double
Scalar value specifying the gamma parameter.
tol_u : 1e-5, double
Convergence satisfied when |du_{k+1}| < tol_u.
tol_r : 1e-5, double
Convergence satisfied when |dr_{k+1}| < tol_r.
itmax : 10, int
Maximum number of iterations allowed per time step / increment.
Returns
-----------
u : double
Predicted displacement at time step k+1, ndofs-by-1 Numpy array.
udot : double
Predicted velocity at time step k+1, ndofs-by-1 Numpy array.
uddot : double
Predicted acceleration at time step k+1, ndofs-by-1 Numpy array.
References:
--------------------
Elena Chatzi, presentation.
Other:
--------------
Because predictor and corrector steps are both included,
only modified Newton-Raphson is possible (can't update tangent stiffness
each iteration), because that would require updating model and reassembly of system.
Use newmark.pred and newmark.corr separately for full non-linear Newton-Raphson.
"""
# If no internal stiffness force is provided, assume linear system => f_int = K u
if f_int is None:
f_int = K @ u
# Save current status as previous
u_prev = 1.0*u
udot_prev = 1.0*udot
f_int_prev = 1.0*f_int
# Predictor step and initial residual calc
u, udot, uddot, du = pred(u, udot, uddot, dt)
f_int += K @ du
r = residual_hht(f, f_prev, f_int, f_int_prev, K, C, M, u_prev, udot, udot_prev, uddot, alpha, gamma, beta, dt)
# Loop through iterations until convergence is met
for it in range(itmax):
# Corrector step
u, udot, uddot, du = corr_alt(r, K, C, M, u, udot, uddot, dt, beta, gamma, alpha=alpha)
# Update internal forces and calculate residual
f_int += K @ du
r = residual_hht(f, f_prev, f_int, f_int_prev, K, C, M, u_prev, udot, udot_prev, uddot, alpha, gamma, beta, dt)
# Check convergence and break if convergence is met
converged = is_converged([np.linalg.norm(du), np.linalg.norm(r)],
[tol_u, tol_r])
if converged:
break
# Save current status as previous
u_prev = 1.0*u
udot_prev = 1.0*udot
f_int_prev = 1.0*f_int
return u, udot, uddot
def pred_lin(u, udot, uddot, dt, beta, gamma):
"""
Predictor step in linear Newmark algorithm.
Arguments
-----------
u : double
Current displacement (time step k), ndofs-by-1 Numpy array.
udot : double
Current velocity (time step k), ndofs-by-1 Numpy array.
uddot : double
Current acceleration (time step k), ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
beta : double
Scalar value specifying the beta parameter.
gamma : double
Scalar value specifying the gamma parameter.
Returns
-----------
u : double
Predicted next-step displacement (time step k+1), ndofs-by-1 Numpy array.
udot : double
Predicted next-step velocity (time step k+1), ndofs-by-1 Numpy array.
uddot : double
Predicted next-step acceleration (time step k+1), ndofs-by-1 Numpy array.
Input is output without modification.
"""
du = dt*udot + (0.5-beta)*dt**2*uddot
u = u + du
udot = udot + (1-gamma)*dt*uddot
return u, udot, uddot, du
def corr_lin(K, C, M, f, u, udot, uddot, dt, beta, gamma):
"""
Corrector step in inear Newmark algorithm.
Arguments
-----------
K : double
Next-step (tangent) stiffness matrix (time step k+1),
ndofs-by-ndofs Numpy array.
C : double
Damping matrix, ndofs-by-ndofs Numpy array.
M : double
Mass matrix, ndofs-by-ndofs Numpy array.
f : double
Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u : double
Next-step displacement, time step k+1, ndofs-by-1 Numpy array.
udot : double
Next-step velocity, time step k+1, ndofs-by-1 Numpy array.
uddot : double
Next-step acceleration, time step k+1, ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
beta : double
Scalar value specifying the beta parameter.
gamma : double
Scalar value specifying the gamma parameter.
Returns
-----------
u : double
Predicted next-step displacement, time step k+1, ndofs-by-1 Numpy array.
udot : double
Predicted next-step velocity, time step k+1, ndofs-by-1 Numpy array.
uddot : double
Predicted next-step acceleration, time step k+1), ndofs-by-1 Numpy array.
"""
M_eff = effective_mass(M, C, K, dt, gamma, beta)
uddot = acc_estimate(K, C, M_eff, f, udot, u=u)
udot = udot + gamma*dt*uddot
du = beta*dt**2*uddot
u = u + du
return u, udot, uddot, du
def dnewmark_lin(K, C, M, f, u, udot, uddot, dt, beta=1.0/4.0, gamma=0.5):
"""
Combined (predictor-corrector) stepwise linear Newmark based on Algorithm 9.1 in Krenk, 2009.
Arguments
-----------
K : double
Stiffness matrix, ndofs-by-ndofs Numpy array.
C : double
Damping matrix, ndofs-by-ndofs Numpy array.
M : double
Mass matrix, ndofs-by-ndofs Numpy array.
f : double
Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u : double
Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot : double
Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot : double
Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
beta : 1.0/6.0, optional
Scalar value specifying the beta parameter.
gamma : 0.5, optional
Scalar value specifying the gamma parameter.
Returns
-----------
u : double
Predicted displacement at time step k+1, ndofs-by-1 Numpy array.
udot : double
Predicted velocity at time step k+1, ndofs-by-1 Numpy array.
uddot : double
Predicted acceleration at time step k+1, ndofs-by-1 Numpy array.
References:
--------------------
:cite:`Krenk2009`
"""
u, udot, uddot, __ = pred_lin(u, udot, uddot, dt, beta, gamma)
u, udot, uddot, __ = corr_lin(K, C, M, f, u, udot, uddot, dt, beta, gamma)
return u, udot, uddot
def dnewmark_lin_alt(K, C, M, df, u, udot, uddot, dt, beta=1.0/4.0, gamma=0.5):
"""
Alternative implementation, stepwise linear Newmark.
Arguments
-----------
K : double
Stiffness matrix, ndofs-by-ndofs Numpy array.
C : double
Damping matrix, ndofs-by-ndofs Numpy array.
M : double
Mass matrix, ndofs-by-ndofs Numpy array.
f : double
Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u : double
Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot : double
Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot : double
Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt : double
Current time step, from k to k+1.
beta : 1.0/4.0, optional
Scalar value specifying the beta parameter.
gamma : 0.5, optional
Scalar value specifying the gamma parameter.
Returns
-----------
u : double
Predicted displacement at time step k+1, ndofs-by-1 Numpy array.
udot : double
Predicted velocity at time step k+1, ndofs-by-1 Numpy array.
uddot : double
Predicted acceleration at time step k+1, ndofs-by-1 Numpy array.
"""
a = 1/(beta*dt)*M + gamma/beta*C
b = 1/(2*beta)*M + dt*(gamma/(2*beta)-1)*C
K_eff = K + gamma/(beta*dt)*C + 1/(beta*dt**2)*M
df_hat = df + a @ udot + b @ uddot
du = solve(K_eff, df_hat)
dudot = gamma/(beta*dt)*du - gamma/beta*udot + dt*(1-gamma/(2*beta))*uddot
duddot = 1/(beta*dt**2)*du - 1/(beta*dt)*udot - 1/(2*beta)*uddot
u = u + du
udot = udot + dudot
uddot = uddot + duddot
return u, udot, uddot
def newmark_lin(K, C, M, f, t, u0, udot0, beta=1.0/4.0, gamma=0.5, solver='full_hht', alpha=0.0):
"""
Combined linear Newmark (predictor-corrector), full time history.
Arguments
-----------
K : double
Stiffness matrix, ndofs-by-ndofs Numpy array.
C : double
Damping matrix, ndofs-by-ndofs Numpy array.
M : double
Mass matrix, ndofs-by-ndofs Numpy array.
f : double
Full history of external forces, ndofs-by-nsamples Numpy array.
u0 : double
Initial displacement, ndofs-by-1 Numpy array.
udot0 : double
Initial velocity, ndofs-by-1 Numpy array.
t : double
Time instances corresponding to f, nsamples long Numpy array.
beta : 1/4, optional
Scalar value specifying the beta parameter.
gamma : 0.5, optional
Scalar value specifying the gamma parameter.
solver : {'full_hht', 'full', 'lin', 'lin_alt'}, optional
What step-wise solver to enforce each time step. Useful for debugging.
alpha : 0.0, optional
Only used when 'nonlin_hht' is enforced
Returns
-----------
u : double
Predicted displacement time history, ndofs-by-nsamples Numpy array.
udot : double
Predicted velocity time history, ndofs-by-nsamples Numpy array.
uddot : double
Predicted acceleration time history, ndofs-by-nsamples Numpy array.
"""
# Initialize response arrays
u = f*0
udot = f*0
uddot = f*0
n_samples = f.shape[1]
args = [[]]*n_samples
# Assign initial conditions
u[:, 0] = u0
udot[:, 0] = udot0
uddot[:, 0] = acc_estimate(K, C, M, f[:, 0], udot0, u0)
# Prepare for different solver types
if solver == 'lin':
dnmrk_fun = dnewmark_lin
kwargs = {}
elif solver == 'lin_alt': #BJF
# This version uses df_k = f_k+1-f_k for each time step,
# so needs to redefine f
dnmrk_fun = dnewmark_lin_alt
f = np.diff(f, axis=1)
f = np.insert(f, 0, f[:,0]*0, axis=1)
kwargs = {}
uddot[:, 0] = uddot[:, 0]*0 #remove initial acceleration estimate
elif solver == 'full':
dnmrk_fun = dnewmark
kwargs = {'itmax': 1}
elif solver == 'full_hht':
dnmrk_fun = dnewmark_hht
kwargs = {'itmax': 1, 'alpha': alpha}
for k in range(n_samples):
args[k] = [f[:, k]]
# Loop through all time steps
for k in range(n_samples-1):
dt = t[k+1] - t[k]
u[:, k+1], udot[:, k+1], uddot[:, k+1] = dnmrk_fun(K, C, M, f[:, k+1], u[:, k], udot[:, k], uddot[:, k], dt, beta=beta, gamma=gamma, *args[k], **kwargs)
return u, udot, uddot
def factors_from_alpha(alpha):
if alpha>0 or alpha<(-1.0/3.0):
raise ValueError('alpha must be in range [-1/3, 0]')
gamma = 0.5 * (1-2*alpha)
beta = 0.25 * (1-alpha)**2
return dict(beta=beta, gamma=gamma, alpha=alpha)
def factors(version='linear'):
""" Gamma and beta factors for Newmark. Alpha is also output as zero, for convenience.
Arguments
--------------
version : {'linear', 'constant', 'average', 'fox-goodwin'}, optional
String characterizing what method to use for Newmark simulation.
Returns
-------------
beta : double
Beta factor for Newmark analysis.
gamma : double
Gamma factor for Newmark analysis.
alpha : double
Hard coded to zero for all cases herein
"""
factors = {'average': {'beta': 0.25, 'gamma': 0.5, 'alpha': 0.0},
'constant': {'beta': 0.25, 'gamma': 0.5, 'alpha': 0.0},
'linear': {'beta': 1.0/6.0, 'gamma': 0.5, 'alpha': 0.0},
'fox-goodwin': {'beta': 1.0/12.0, 'gamma':0.5, 'alpha': 0.0},
'explicit': {'beta': 0, 'gamma': 0.5, 'alpha': 0.0}}
return factors[version]
def stable_increment(omega_max, gamma=1/2, beta=1/6):
return 1/(omega_max*np.sqrt(gamma*0.5-beta))
Functions
def acc_estimate(K, C, M, f, udot, u=None, f_int=None, dt=None, beta=None, gamma=None)
-
Predict acceleration for time integration, based on internal forces, damping matrix, mass matrix, current velocity and external force.
Arguments
K
:double
- Next-step (tangent) stiffness matrix (time step k+1), ndofs-by-ndofs Numpy array.
C
:double
- Damping matrix, ndofs-by-ndofs Numpy array.
M
:double
- Mass matrix, ndofs-by-ndofs Numpy array.
f
:double
- Current external forces (time step k), ndofs-by-1 Numpy array.
udot
:double
- Velocity at chosen time instance, ndofs-by-1 Numpy array.
u
:optional, double
- Displacement at chosen time instance, ndofs-by-1 Numpy array.
f_int
:optional, double
- Current internal forces (time step k). Equal K @ u if not given, ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
beta
:double
- Scalar value specifying the beta parameter.
gamma
:double
- Scalar value specifying the gamma parameter.
Returns
uddot
:double
- Resulting acceleration array, ndofs-by-1 Numpy array.
def corr(r, K, C, M, u, udot, uddot, dt, beta, gamma)
-
Corrector step in non-linear Newmark algorithm.
Arguments
r
:double
- Residual forces.
K
:double
- Next-step (tangent) stiffness matrix (time step k+1), ndofs-by-ndofs Numpy array.
C
:double
- Damping matrix, ndofs-by-ndofs Numpy array.
M
:double
- Mass matrix, ndofs-by-ndofs Numpy array.
u
:double
- Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot
:double
- Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot
:double
- Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
beta
:double
- Scalar value specifying the beta parameter.
gamma
:double
- Scalar value specifying the gamma parameter.
Returns
u
:double
- Predicted next-step displacement, time step k+1, iteration i+1, ndofs-by-1 Numpy array.
udot
:double
- Predicted next-step velocity, time step k+1, iteration i+1, ndofs-by-1 Numpy array.
uddot
:double
- Predicted next-step acceleration, time step k+1), iteration i+1, ndofs-by-1 Numpy array.
norm_r
:double
- Frobenius norm of residual force vector
norm_u
:double
- Frobenius norm of added displacement
def corr_alt(r, K, C, M, u, udot, uddot, dt, beta, gamma, alpha=0.0)
-
Corrector step in non-linear Newmark algorithm. Alternative version - uses Meff rather than Keff and allows for alpha damping.
Arguments
r
:double
- Residual forces.
K
:double
- Next-step (tangent) stiffness matrix (time step k+1), ndofs-by-ndofs Numpy array.
C
:double
- Damping matrix, ndofs-by-ndofs Numpy array.
M
:double
- Mass matrix, ndofs-by-ndofs Numpy array.
u
:double
- Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot
:double
- Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot
:double
- Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
beta
:double
- Scalar value specifying the beta parameter.
gamma
:double
- Scalar value specifying the gamma parameter.
Returns
u
:double
- Predicted next-step displacement, time step k+1, iteration i+1, ndofs-by-1 Numpy array.
udot
:double
- Predicted next-step velocity, time step k+1, iteration i+1, ndofs-by-1 Numpy array.
uddot
:double
- Predicted next-step acceleration, time step k+1), iteration i+1, ndofs-by-1 Numpy array.
norm_r
:double
- Frobenius norm of residual force vector
norm_u
:double
- Frobenius norm of added displacement
def corr_lin(K, C, M, f, u, udot, uddot, dt, beta, gamma)
-
Corrector step in inear Newmark algorithm.
Arguments
K
:double
- Next-step (tangent) stiffness matrix (time step k+1), ndofs-by-ndofs Numpy array.
C
:double
- Damping matrix, ndofs-by-ndofs Numpy array.
M
:double
- Mass matrix, ndofs-by-ndofs Numpy array.
f
:double
- Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u
:double
- Next-step displacement, time step k+1, ndofs-by-1 Numpy array.
udot
:double
- Next-step velocity, time step k+1, ndofs-by-1 Numpy array.
uddot
:double
- Next-step acceleration, time step k+1, ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
beta
:double
- Scalar value specifying the beta parameter.
gamma
:double
- Scalar value specifying the gamma parameter.
Returns
u
:double
- Predicted next-step displacement, time step k+1, ndofs-by-1 Numpy array.
udot
:double
- Predicted next-step velocity, time step k+1, ndofs-by-1 Numpy array.
uddot
:double
- Predicted next-step acceleration, time step k+1), ndofs-by-1 Numpy array.
def dnewmark(K, C, M, f, u, udot, uddot, dt, f_int=None, beta=0.25, gamma=0.5, tol_u=1e-05, tol_r=1e-05, itmax=10)
-
Combined stepwise non-linear Newmark (predictor-corrector), based on Algorithm 9.2 in Krenk, 2009. Because f_int is not updated each iteration this is equivalent to modified NR iteration.
Arguments
K
:double
- Next-step (tangent) stiffness matrix (time step k+1), ndofs-by-ndofs Numpy array.
C
:double
- Damping matrix, ndofs-by-ndofs Numpy array.
M
:double
- Mass matrix, ndofs-by-ndofs Numpy array.
f
:double
- Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u
:double
- Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot
:double
- Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot
:double
- Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
f_int
:optional, double
- Current internal forces (time step k). Equal K @ u if not given, ndofs-by-1 Numpy array.
beta
:1/4, double
- Scalar value specifying the beta parameter.
gamma
:0.5, double
- Scalar value specifying the gamma parameter.
tol_u
:1e-5, double
- Convergence satisfied when |du_{k+1}| < tol_u.
tol_r
:1e-5, double
- Convergence satisfied when |dr_{k+1}| < tol_r.
itmax
:10, int
- Maximum number of iterations allowed per time step / increment.
Returns
u
:double
- Predicted displacement at time step k+1, ndofs-by-1 Numpy array.
udot
:double
- Predicted velocity at time step k+1, ndofs-by-1 Numpy array.
uddot
:double
- Predicted acceleration at time step k+1, ndofs-by-1 Numpy array.
References:
:cite:
Krenk2009
Other:
Because predictor and corrector steps are both included, only modified Newton-Raphson is possible (can't update tangent stiffness each iteration), because that would require updating model and reassembly of system. Use newmark.pred and newmark.corr separately for full non-linear Newton-Raphson.
def dnewmark_hht(K, C, M, f, u, udot, uddot, dt, f_prev, f_int=None, beta=0.25, gamma=0.5, alpha=0.0, tol_u=1e-05, tol_r=1e-05, itmax=10)
-
Incremental formulation of Newmark allowing for alpha-damping.
Arguments
K
:double
- Next-step (tangent) stiffness matrix (time step k+1), ndofs-by-ndofs Numpy array.
C
:double
- Damping matrix, ndofs-by-ndofs Numpy array.
M
:double
- Mass matrix, ndofs-by-ndofs Numpy array.
f
:double
- Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u
:double
- Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot
:double
- Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot
:double
- Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
f_int
:optional, double
- Current internal forces (time step k). Equal K @ u if not given, ndofs-by-1 Numpy array.
beta
:1/4, double
- Scalar value specifying the beta parameter.
gamma
:0.5, double
- Scalar value specifying the gamma parameter.
tol_u
:1e-5, double
- Convergence satisfied when |du_{k+1}| < tol_u.
tol_r
:1e-5, double
- Convergence satisfied when |dr_{k+1}| < tol_r.
itmax
:10, int
- Maximum number of iterations allowed per time step / increment.
Returns
u
:double
- Predicted displacement at time step k+1, ndofs-by-1 Numpy array.
udot
:double
- Predicted velocity at time step k+1, ndofs-by-1 Numpy array.
uddot
:double
- Predicted acceleration at time step k+1, ndofs-by-1 Numpy array.
References:
Elena Chatzi, presentation.
Other:
Because predictor and corrector steps are both included, only modified Newton-Raphson is possible (can't update tangent stiffness each iteration), because that would require updating model and reassembly of system. Use newmark.pred and newmark.corr separately for full non-linear Newton-Raphson.
def dnewmark_lin(K, C, M, f, u, udot, uddot, dt, beta=0.25, gamma=0.5)
-
Combined (predictor-corrector) stepwise linear Newmark based on Algorithm 9.1 in Krenk, 2009.
Arguments
K
:double
- Stiffness matrix, ndofs-by-ndofs Numpy array.
C
:double
- Damping matrix, ndofs-by-ndofs Numpy array.
M
:double
- Mass matrix, ndofs-by-ndofs Numpy array.
f
:double
- Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u
:double
- Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot
:double
- Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot
:double
- Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
beta
:1.0/6.0
, optional- Scalar value specifying the beta parameter.
gamma
:0.5
, optional- Scalar value specifying the gamma parameter.
Returns
u
:double
- Predicted displacement at time step k+1, ndofs-by-1 Numpy array.
udot
:double
- Predicted velocity at time step k+1, ndofs-by-1 Numpy array.
uddot
:double
- Predicted acceleration at time step k+1, ndofs-by-1 Numpy array.
References:
:cite:
Krenk2009
def dnewmark_lin_alt(K, C, M, df, u, udot, uddot, dt, beta=0.25, gamma=0.5)
-
Alternative implementation, stepwise linear Newmark.
Arguments
K
:double
- Stiffness matrix, ndofs-by-ndofs Numpy array.
C
:double
- Damping matrix, ndofs-by-ndofs Numpy array.
M
:double
- Mass matrix, ndofs-by-ndofs Numpy array.
f
:double
- Next-step external forces (time step k+1), ndofs-by-1 Numpy array.
u
:double
- Next-step displacement, time step k+1, iteration i, ndofs-by-1 Numpy array.
udot
:double
- Next-step velocity, time step k+1, iteration i, ndofs-by-1 Numpy array.
uddot
:double
- Next-step acceleration, time step k+1, iteration i, ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
beta
:1.0/4.0
, optional- Scalar value specifying the beta parameter.
gamma
:0.5
, optional- Scalar value specifying the gamma parameter.
Returns
u
:double
- Predicted displacement at time step k+1, ndofs-by-1 Numpy array.
udot
:double
- Predicted velocity at time step k+1, ndofs-by-1 Numpy array.
uddot
:double
- Predicted acceleration at time step k+1, ndofs-by-1 Numpy array.
def effective_mass(M, C, K, dt, gamma, beta, alpha=0.0)
def factors(version='linear')
-
Gamma and beta factors for Newmark. Alpha is also output as zero, for convenience.
Arguments
version
:{'linear', 'constant', 'average', 'fox-goodwin'}
, optional- String characterizing what method to use for Newmark simulation.
Returns
beta
:double
- Beta factor for Newmark analysis.
gamma
:double
- Gamma factor for Newmark analysis.
alpha
:double
- Hard coded to zero for all cases herein
def factors_from_alpha(alpha)
def is_converged(values, tols, scaling=None)
-
Check whether multiple values are below specified tolerances. (value/scaling)
Arguments
values
:double
- list of values to check
tols
:double
- corresponding list of tolerances to compare values to
scaling
:double
, optional- corresponding list of scaling of values
Returns
ok
:boolean
- converged or not?
Notes
If entry in tols is None, the corresponding value is assumed to pass tolerance criterion. If entry in tols is different than None, the value pass if value <= tol * scaling.
def newmark_lin(K, C, M, f, t, u0, udot0, beta=0.25, gamma=0.5, solver='full_hht', alpha=0.0)
-
Combined linear Newmark (predictor-corrector), full time history.
Arguments
K
:double
- Stiffness matrix, ndofs-by-ndofs Numpy array.
C
:double
- Damping matrix, ndofs-by-ndofs Numpy array.
M
:double
- Mass matrix, ndofs-by-ndofs Numpy array.
f
:double
- Full history of external forces, ndofs-by-nsamples Numpy array.
u0
:double
- Initial displacement, ndofs-by-1 Numpy array.
udot0
:double
- Initial velocity, ndofs-by-1 Numpy array.
t
:double
- Time instances corresponding to f, nsamples long Numpy array.
beta
:1/4
, optional- Scalar value specifying the beta parameter.
gamma
:0.5
, optional- Scalar value specifying the gamma parameter.
solver
:{'full_hht', 'full', 'lin', 'lin_alt'}
, optional- What step-wise solver to enforce each time step. Useful for debugging.
alpha
:0.0
, optional- Only used when 'nonlin_hht' is enforced
Returns
u
:double
- Predicted displacement time history, ndofs-by-nsamples Numpy array.
udot
:double
- Predicted velocity time history, ndofs-by-nsamples Numpy array.
uddot
:double
- Predicted acceleration time history, ndofs-by-nsamples Numpy array.
def pred(u, udot, uddot, dt, beta=0, gamma=0)
-
Predictor step in non-linear Newmark algorithm.
Arguments
u
:double
- Current displacement (time step k), ndofs-by-1 Numpy array.
udot
:double
- Current velocity (time step k), ndofs-by-1 Numpy array.
uddot
:double
- Current acceleration (time step k), ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
beta
:double
- Beta Newmark parameter. In Chatzi implementation, this is included in predictor as well as corrector - in Krenk, it is only used in corrector. The chosen values (0) are based on Krenk's approach.
gamma
:double
- gamma Newmark parameter. In Chatzi implementation, this is included in predictor as well as corrector - in Krenk, it is only used in corrector. The chosen values (0) are based on Krenk's approach.
Returns
u
:double
- Predicted next-step displacement (time step k+1), ndofs-by-1 Numpy array.
udot
:double
- Predicted next-step velocity (time step k+1), ndofs-by-1 Numpy array.
uddot
:double
- Predicted next-step acceleration (time step k+1), ndofs-by-1 Numpy array. (Input uddot is output without modifications)
def pred_lin(u, udot, uddot, dt, beta, gamma)
-
Predictor step in linear Newmark algorithm.
Arguments
u
:double
- Current displacement (time step k), ndofs-by-1 Numpy array.
udot
:double
- Current velocity (time step k), ndofs-by-1 Numpy array.
uddot
:double
- Current acceleration (time step k), ndofs-by-1 Numpy array.
dt
:double
- Current time step, from k to k+1.
beta
:double
- Scalar value specifying the beta parameter.
gamma
:double
- Scalar value specifying the gamma parameter.
Returns
u
:double
- Predicted next-step displacement (time step k+1), ndofs-by-1 Numpy array.
udot
:double
- Predicted next-step velocity (time step k+1), ndofs-by-1 Numpy array.
uddot
:double
- Predicted next-step acceleration (time step k+1), ndofs-by-1 Numpy array. Input is output without modification.
def residual(f, f_int, C, M, udot, uddot)
def residual_hht(f, f_prev, f_int, f_int_prev, K, C, M, u_prev, udot, udot_prev, uddot, alpha, gamma, beta, dt)
def stable_increment(omega_max, gamma=0.5, beta=0.16666666666666666)