Skip to content

Commit cdd8d96

Browse files
ewu63whophil
andauthored
Support numpy2 (#411)
* unpin numpy<2 * build against numpy2 always, which is backwards compatible * pkg_resources needs setuptools, so it is now a runtime requirement also * test multiple numpy versions in GHA for Windows * update macros * update actions * quotes * try unsetting PIP_CONSTRAINT to bypass check for build-time deps * try moving the file * one more try * try numpy 2.0.2 for windows * do not compare iterations directly * bump to 15min for windows jobs * test later numpy * do not test iterations * conda list -v * better skip test message format * maybe leave the windows numpy2 test combo to conda * remove nsga2 import warning since it's not required * address comments * minor version bump * maybe we don't need these; use default gfortran instead * try again * forgot quotes * try gcc * ld * don't set linker * alright back to msvc * this one passed before * install flang? * Fix windows build for numpy 2.0 (#424) * Fix windows env and build * Remove debug output --------- Co-authored-by: Phil Chiu <[email protected]>
1 parent f66e9fb commit cdd8d96

File tree

11 files changed

+55
-34
lines changed

11 files changed

+55
-34
lines changed

.github/build_real.sh

+7
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,11 @@ if [[ $IMAGE == "private" ]]; then
77
cp -r $HOME/SNOPT/* pyoptsparse/pySNOPT/source
88
fi
99

10+
# temporarily disable pip constraints file for build-time dependencies
11+
mv ~/.config/pip/constraints.txt ~/.config/pip/constraints.txt.bkup
12+
touch ~/.config/pip/constraints.txt
13+
1014
pip install .[optview,testing] -v
15+
16+
# move pip constraints file back
17+
mv ~/.config/pip/constraints.txt.bkup ~/.config/pip/constraints.txt

.github/environment.yml

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
dependencies:
22
# build
33
- python >=3.9
4-
- numpy >=1.21,<2
4+
- numpy >=2.0
55
- ipopt
66
- swig
77
- meson >=1.3.2
@@ -10,10 +10,11 @@ dependencies:
1010
- pip
1111
- setuptools
1212
- build
13+
# runtime
1314
- packaging
15+
- mdolab-baseclasses >=1.3.1
16+
- scipy >=1.7
17+
- sqlitedict >=1.6
1418
# testing
1519
- parameterized
1620
- testflo
17-
- scipy >=1.7
18-
- mdolab-baseclasses >=1.3.1
19-
- sqlitedict >=1.6

.github/workflows/windows-build.yml

+23-9
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@ on:
1111
jobs:
1212
build-windows:
1313
runs-on: windows-latest
14-
14+
timeout-minutes: 15
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
numpy_version: ["1.21.6", "1.25.2"]
1519
steps:
16-
- uses: actions/checkout@v2
17-
- uses: conda-incubator/setup-miniconda@v2
20+
- uses: actions/checkout@v4
21+
- uses: conda-incubator/setup-miniconda@v3
1822
with:
19-
python-version: 3.9
20-
miniforge-variant: Mambaforge
23+
python-version: "3.10"
2124
channels: conda-forge,defaults
2225
channel-priority: strict
2326
activate-environment: pyos-build
@@ -26,17 +29,28 @@ jobs:
2629
shell: bash -l {0}
2730
run: |
2831
conda activate pyos-build
29-
mamba install libpgmath
32+
conda install libpgmath
3033
- name: Build and install pyoptsparse
3134
shell: cmd /C CALL {0}
3235
run: |
3336
call conda activate pyos-build
3437
set IPOPT_DIR=%CONDA_PREFIX%\Library
35-
set CC=cl
36-
set FC=flang
37-
set CC_LD=link
38+
39+
# We want to use the clang linker `ld-lld.exe`
40+
# The conda-forge clang packages set the LD environment variable and LDFLAGS for that linker.
41+
# But meson doesn't respect the LD environment variable - so set `<compiler entry>_LD`
42+
# https://mesonbuild.com/howtox.html#set-linker
43+
set CC_LD=%LD%
44+
set CXX_LD=%LD%
45+
set FC_LD=%LD%
46+
3847
python -m build -n -x .
3948
pip install --no-deps --no-index --find-links dist pyoptsparse
49+
- name: Install runtime numpy ${{ matrix.numpy_version }}
50+
shell: bash -l {0}
51+
run: |
52+
conda activate pyos-build
53+
conda install numpy==${{ matrix.numpy_version }}
4054
- name: Run tests
4155
shell: bash -l {0}
4256
run: |

pyoptsparse/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "2.12.0"
1+
__version__ = "2.13.0"
22

33
from .pyOpt_history import History
44
from .pyOpt_variable import Variable

pyoptsparse/pyIPOPT/src/callback.c

+9-9
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ eval_f(Index n, Number * x, Bool new_x, Number * obj_value, UserDataPtr data)
135135

136136
import_array1(FALSE);
137137
PyObject *arrayx =
138-
PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE, (char *)x);
138+
PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, (char *)x);
139139
if (!arrayx)
140140
return FALSE;
141141

@@ -209,11 +209,11 @@ eval_grad_f(Index n, Number * x, Bool new_x, Number * grad_f, UserDataPtr data)
209209
import_array1(FALSE);
210210

211211
/*
212-
* PyObject *arrayx = PyArray_FromDimsAndData(1, dims, PyArray_DOUBLE
212+
* PyObject *arrayx = PyArray_FromDimsAndData(1, dims, NPY_DOUBLE
213213
* , (char*) x);
214214
*/
215215
PyObject *arrayx =
216-
PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE, (char *)x);
216+
PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, (char *)x);
217217
if (!arrayx)
218218
return FALSE;
219219

@@ -287,11 +287,11 @@ eval_g(Index n, Number * x, Bool new_x, Index m, Number * g, UserDataPtr data)
287287
import_array1(FALSE);
288288

289289
/*
290-
* PyObject *arrayx = PyArray_FromDimsAndData(1, dims, PyArray_DOUBLE
290+
* PyObject *arrayx = PyArray_FromDimsAndData(1, dims, NPY_DOUBLE
291291
* , (char*) x);
292292
*/
293293
PyObject *arrayx =
294-
PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE, (char *)x);
294+
PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, (char *)x);
295295
if (!arrayx)
296296
return FALSE;
297297

@@ -372,7 +372,7 @@ eval_jac_g(Index n, Number * x, Bool new_x,
372372
import_array1(FALSE);
373373

374374
PyObject *arrayx =
375-
PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE,
375+
PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE,
376376
(char *)x);
377377
if (!arrayx)
378378
return FALSE;
@@ -420,7 +420,7 @@ eval_jac_g(Index n, Number * x, Bool new_x,
420420
//logger("[Callback:R] eval_jac_g(1)");
421421
} else {
422422
PyObject *arrayx =
423-
PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE,
423+
PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE,
424424
(char *)x);
425425

426426
if (!arrayx)
@@ -580,7 +580,7 @@ eval_h(Index n, Number * x, Bool new_x, Number obj_factor,
580580

581581
dims[0] = n;
582582
PyObject *arrayx =
583-
PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE,
583+
PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE,
584584
(char *)x);
585585
if (!arrayx)
586586
return FALSE;
@@ -601,7 +601,7 @@ eval_h(Index n, Number * x, Bool new_x, Number obj_factor,
601601
}
602602
dims2[0] = m;
603603
PyObject *lagrangex = PyArray_SimpleNewFromData(
604-
1, dims2, PyArray_DOUBLE, (char *)lambda);
604+
1, dims2, NPY_DOUBLE, (char *)lambda);
605605
if (!lagrangex)
606606
return FALSE;
607607

pyoptsparse/pyIPOPT/src/pyipoptcoremodule.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ PyObject *solve(PyObject * self, PyObject * args)
631631
n = dim[0];
632632
dX[0] = n;
633633

634-
x = (PyArrayObject *) PyArray_SimpleNew(1, dX, PyArray_DOUBLE);
634+
x = (PyArrayObject *) PyArray_SimpleNew(1, dX, NPY_DOUBLE);
635635
if (!x) {
636636
retval = PyErr_NoMemory();
637637
/* clean up and return */
@@ -663,11 +663,11 @@ PyObject *solve(PyObject * self, PyObject * args)
663663

664664
/* Allocate multiplier arrays */
665665

666-
mL = (PyArrayObject *) PyArray_SimpleNew(1, dX, PyArray_DOUBLE);
667-
mU = (PyArrayObject *) PyArray_SimpleNew(1, dX, PyArray_DOUBLE);
666+
mL = (PyArrayObject *) PyArray_SimpleNew(1, dX, NPY_DOUBLE);
667+
mU = (PyArrayObject *) PyArray_SimpleNew(1, dX, NPY_DOUBLE);
668668
dlambda[0] = m;
669669
lambda = (PyArrayObject *) PyArray_SimpleNew(1, dlambda,
670-
PyArray_DOUBLE);
670+
NPY_DOUBLE);
671671

672672
/* For status code, see IpReturnCodes_inc.h in Ipopt */
673673

pyoptsparse/pyNSGA2/pyNSGA2.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
# import the compiled module
1919
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
20-
nsga2 = try_import_compiled_module_from_path("nsga2", THIS_DIR, raise_warning=True)
20+
nsga2 = try_import_compiled_module_from_path("nsga2", THIS_DIR)
2121

2222

2323
class NSGA2(Optimizer):

pyproject.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[build-system]
2-
requires = ["setuptools>=42", "meson>=0.60.0", "oldest-supported-numpy", "ninja"]
3-
build-backend = "setuptools.build_meta"
2+
requires = ["setuptools>=42", "meson>=0.60.0", "ninja", "numpy>=2.0"]
3+
build-backend = "setuptools.build_meta"

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def copy_shared_libraries():
104104
install_requires=[
105105
"packaging",
106106
"sqlitedict>=1.6",
107-
"numpy>=1.21,<2",
107+
"numpy>=1.21",
108108
"scipy>=1.7",
109109
"mdolab-baseclasses>=1.3.1",
110110
],

tests/test_hs015.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,11 @@ def test_ipopt(self):
145145
data_init = hist.read(0)
146146
self.assertEqual(0, data_init["iter"])
147147
data_last = hist.read(hist.read("last"))
148-
self.assertEqual(11, data_last["iter"]) # took 12 function evaluations (see test_ipopt.out)
148+
self.assertGreater(data_last["iter"], 0)
149149

150150
# Make sure there is no duplication in objective history
151151
data = hist.getValues(names=["obj"])
152152
objhis_len = data["obj"].shape[0]
153-
self.assertEqual(12, objhis_len)
154153
for i in range(objhis_len - 1):
155154
self.assertNotEqual(data["obj"][i], data["obj"][i + 1])
156155

tests/testing_utils.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ def optimize(self, sens=None, setDV=None, optOptions=None, storeHistory=False, h
242242
if self.optName in DEFAULT_OPTIMIZERS:
243243
raise e
244244
else:
245-
raise unittest.SkipTest("Optimizer not available: ", self.optName)
245+
raise unittest.SkipTest(f"Optimizer not available: {self.optName}")
246246

247247
if isinstance(setDV, str):
248248
self.optProb.setDVsFromHistory(setDV)

0 commit comments

Comments
 (0)