Skip to content

Commit 2a4df9d

Browse files
committed
rfcnt-0.2.0
Python: - New parameter "lc_method" to control counting of falling and/or rising slopes. Default changed from rising AND falling slopes to rising only! - Results of range pair counting now hold the ranges instead of the amplitudes.
1 parent 436e296 commit 2a4df9d

File tree

6 files changed

+46
-21
lines changed

6 files changed

+46
-21
lines changed

python/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ predefined functions.
2525
pip install {packagename}.tar.gz
2626
where _{packagename}_ is the current package release, for example:
2727

28-
pip install rfcnt-0.1.1.tar.gz
28+
pip install rfcnt-0.2.0.tar.gz
2929

3030
### Test
3131
_rfcnt_ packages include some unit tests, which can be run:

python/jupyter_screenshot.png

-37 KB
Loading

python/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from setuptools import setup, Extension
22
from os import path
33

4-
version = (0, 1, 2)
4+
version = (0, 2, 0)
55

66
try:
77
from numpy import get_include as get_numpy_include

python/src/rfcnt.cpp

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,28 @@ const char* rfc_err_str( int nr )
3333
static
3434
int parse_rfc_kwargs( PyObject* kwargs, Py_ssize_t len, Rainflow *rf, Rainflow::rfc_res_method *res_method )
3535
{
36-
PyObject *empty = PyTuple_New(0);
37-
int class_count = 100;
38-
double class_width = -1;
39-
double class_offset = 0;
40-
double hysteresis = -1;
41-
int enforce_margin = 1;
42-
int use_hcm = 0;
43-
int use_astm = 0;
44-
int spread_damage = Rainflow::RFC_SD_TRANSIENT_23c;
45-
PyObject *wl = NULL;
46-
double wl_sd = 1e3, wl_nd = 1e7,
47-
wl_k = 5, wl_k2 = 5;
36+
PyObject *empty = PyTuple_New(0);
37+
int class_count = 100;
38+
double class_width = -1; // -1 = "calculated"
39+
double class_offset = 0;
40+
double hysteresis = -1; // -1 = "calculated"
41+
int enforce_margin = 1; // true
42+
int use_hcm = 0; // false
43+
int use_astm = 0; // false
44+
int lc_method = 0; // Count rising slopes only
45+
int flags = Rainflow::RFC_FLAGS_DEFAULT;
46+
int spread_damage = Rainflow::RFC_SD_TRANSIENT_23c;
47+
PyObject *wl = NULL;
48+
double wl_sd = 1e3, wl_nd = 1e7,
49+
wl_k = 5, wl_k2 = 5;
4850

4951
*res_method = Rainflow::RFC_RES_REPEATED;
5052

5153
char* kw[] = {"class_width", "class_count", "class_offset",
5254
"hysteresis","residual_method", "enforce_margin",
53-
"use_HCM", "use_ASTM", "spread_damage", "wl", NULL};
55+
"use_HCM", "use_ASTM", "spread_damage", "lc_method", "wl", NULL};
5456

55-
if( !PyArg_ParseTupleAndKeywords( empty, kwargs, "d|iddiiiiiO", kw,
57+
if( !PyArg_ParseTupleAndKeywords( empty, kwargs, "d|iddiiiiiiO", kw,
5658
&class_width,
5759
&class_count,
5860
&class_offset,
@@ -62,6 +64,7 @@ int parse_rfc_kwargs( PyObject* kwargs, Py_ssize_t len, Rainflow *rf, Rainflow::
6264
&use_hcm,
6365
&use_astm,
6466
&spread_damage,
67+
&lc_method,
6568
&wl ) )
6669
{
6770
Py_DECREF( empty );
@@ -117,7 +120,29 @@ int parse_rfc_kwargs( PyObject* kwargs, Py_ssize_t len, Rainflow *rf, Rainflow::
117120
if( hysteresis < 0 ) hysteresis = class_width;
118121
}
119122

120-
if( !rf->init( class_count, class_width, class_offset, hysteresis ) )
123+
// lc_method
124+
flags &= ~Rainflow::RFC_FLAGS_COUNT_LC;
125+
126+
switch( lc_method )
127+
{
128+
case 0:
129+
flags |= Rainflow::RFC_FLAGS_COUNT_LC_UP;
130+
break;
131+
132+
case 1:
133+
flags |= Rainflow::RFC_FLAGS_COUNT_LC_DN;
134+
break;
135+
136+
case 2:
137+
flags |= Rainflow::RFC_FLAGS_COUNT_LC;
138+
break;
139+
140+
default:
141+
PyErr_SetString( PyExc_RuntimeError, "Parameter 'lc_method' must be in range 0 to 2!" );
142+
return 0;
143+
}
144+
145+
if( !rf->init( class_count, class_width, class_offset, hysteresis, (Rainflow::rfc_flags_e)flags ) )
121146
{
122147
PyErr_Format( PyExc_RuntimeError, "Rainflow initialization error (%s)", rfc_err_str( rf->error_get() ) );
123148
return 0;
@@ -275,7 +300,7 @@ int prepare_results( Rainflow *rf, Rainflow::rfc_res_method res_method, PyObject
275300
PyArray_FILLWBYTE( arr, 0 );
276301
for( unsigned i = 0; i < class_count; i++ )
277302
{
278-
*(double*)PyArray_GETPTR2( arr, i, 0 ) = (double)sa[i];
303+
*(double*)PyArray_GETPTR2( arr, i, 0 ) = (double)sa[i] * 2; // range = 2 * amplitude
279304
*(double*)PyArray_GETPTR2( arr, i, 1 ) = (double)ct[i];
280305
}
281306
PyDict_SetItemString( *ret, "rp", (PyObject*)arr );
@@ -290,7 +315,7 @@ int prepare_results( Rainflow *rf, Rainflow::rfc_res_method res_method, PyObject
290315
PyArray_FILLWBYTE( arr, 0 );
291316
for( unsigned i = 0; i < class_count; i++ )
292317
{
293-
*(double*)PyArray_GETPTR2( arr, i, 0 ) = (double)sa[i];
318+
*(double*)PyArray_GETPTR2( arr, i, 0 ) = (double)sa[i]; // class upper limit
294319
*(double*)PyArray_GETPTR2( arr, i, 1 ) = (double)ct[i];
295320
}
296321
PyDict_SetItemString( *ret, "lc", (PyObject*)arr );

python/tests/examples.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def example_1():
5454
y=r["sa"],
5555
drawstyle='steps-pre', ci=None, ax=ax2)
5656
plt.xscale("log")
57-
plt.ylim(bottom=0, top=1000)
57+
plt.ylim(bottom=0, top=2000)
5858
plt.xlim(left=0.9)
5959
plt.grid(which="both")
6060
plt.xlabel("N (log) [1]")

python/tests/test_rfcnt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def test_long_series(self):
155155
class_width = 50
156156
x = pd.read_csv(os.path.join(self.get_script_path(), "long_series.csv"), header=None)
157157
x = x.to_numpy().squeeze()
158-
hysteresis = class_width
158+
hysteresis = class_width
159159
use_HCM = 0
160160
enforce_margin = 1 # Enforce first and last data point included in tp
161161
use_HCM = 0 # Use 4 point method, not HCM

0 commit comments

Comments
 (0)