Repository navigation
Multiple_GGmax_Curves.get_curve_matrix() and Multiple_Damping_Curves.get_curve_matrix() raise ValueError when a shorter curve starts at strain 0 #109
Description
Found while reviewing #74. Pre-existing on main (b764057); #74 does not change the behavior.
Problem
When the curves have different lengths, get_curve_matrix() resamples each shorter curve with np.geomspace(np.min(strain), np.max(strain), max_length). np.geomspace() cannot start at 0, so if a shorter curve has a strain of 0, get_curve_matrix() raises ValueError: Geometric sequence cannot include zero. The curve classes accept a strain of 0 (check_two_column_format(..., ensure_non_negative=True) only rejects negative values), and curves of equal length with a strain of 0 work, because they are not resampled.
PySeismoSoil/PySeismoSoil/class_curves.py
Lines 994 to 998 in b764057
| else: # otherwise we need a new strain array to match `max_length` | |
| strain_ = np.geomspace( | |
| np.min(strain), np.max(strain), max_length | |
| ) | |
| damping_ = np.interp(strain_, strain, curve_.damping) |
PySeismoSoil/PySeismoSoil/class_curves.py
Lines 1458 to 1462 in b764057
| else: # otherwise we need a new strain array to match `max_length` | |
| strain_ = np.geomspace( | |
| np.min(strain), np.max(strain), max_length | |
| ) | |
| GGmax_ = np.interp(strain_, strain, curve_.GGmax) |
import numpy as np
from PySeismoSoil.class_curves import (
Damping_Curve,
GGmax_Curve,
Multiple_Damping_Curves,
Multiple_GGmax_Curves,
)
long_strain = np.array([0.0001, 0.001, 0.01, 0.1, 1.0]) # 5 points, unit: %
short_strain = np.array([0.0, 0.01, 0.1, 1.0]) # 4 points, starts at 0
GGmax_long = np.column_stack((long_strain, [1.0, 0.98, 0.9, 0.6, 0.2]))
GGmax_short = np.column_stack((short_strain, [1.0, 0.9, 0.6, 0.2]))
damping_long = np.column_stack((long_strain, [1.0, 1.2, 2.0, 6.0, 15.0]))
damping_short = np.column_stack((short_strain, [1.0, 2.0, 6.0, 15.0]))
# Zero strain is accepted by the curve classes
print(GGmax_Curve(GGmax_short).strain, Damping_Curve(damping_short).strain)
# [0. 0.01 0.1 1. ] [0. 0.01 0.1 1. ]
# Same lengths: works
mgc = Multiple_GGmax_Curves([GGmax_short, GGmax_short])
print(mgc.get_curve_matrix().shape)
# (4, 8)
# Different lengths, the shorter curve starts at 0
for curves in [
Multiple_GGmax_Curves([GGmax_long, GGmax_short]),
Multiple_Damping_Curves([damping_long, damping_short]),
]:
try:
print(curves.get_curve_matrix().shape)
except ValueError as e:
print(f'{type(e).__name__}: {e}')
# ValueError: Geometric sequence cannot include zero
# ValueError: Geometric sequence cannot include zero
# (expected (5, 8) for both)Fix
- In both
get_curve_matrix()methods, build the resampled strain array so that it can start at 0, for example:For the 4-point curve above this givesif np.min(strain) > 0: strain_ = np.geomspace(np.min(strain), np.max(strain), max_length) else: positive = strain[strain > 0] strain_ = np.concatenate( ([0.0], np.geomspace(np.min(positive), np.max(strain), max_length - 1)) )
[0, 0.01, 0.0464, 0.215, 1.0](rounded), andnp.interp()then gives G/Gmax[1.0, 0.9, 0.779, 0.549, 0.2](rounded). The same code is in both classes, so it could move into one shared helper. - Add a test with two curves of different lengths where the shorter one starts at strain 0, for both
Multiple_GGmax_CurvesandMultiple_Damping_Curves.
Activity