SMTorg / smt

Surrogate Modeling Toolbox
https://smt.readthedocs.io/en/stable
BSD 3-Clause "New" or "Revised" License
645 stars 197 forks source link

OOB access in RMTB #579

Open NAThompson opened 1 month ago

NAThompson commented 1 month ago

To reproduce:

#!/usr/bin/env python3
from math import pi as π
import numpy as np
from smt.surrogate_models import RMTB

def generate_sine_surface_data(samples=10, dimension=2):
    training_points = np.full(shape=(samples, dimension), fill_value=np.nan)
    training_values = np.full(shape=samples, fill_value=np.nan)

    for i in range(samples):
        x = np.random.uniform(-1, 1, dimension)
        training_points[i, :] = x
        v = 1
        for j in range(dimension):
            v *= np.sin(π*x[j])
        training_values[i] = v
    return training_points, training_values

if __name__ == '__main__':
    order = 16
    samples = 10
    dimension = 2
    training_points, training_values = generate_sine_surface_data(samples=samples, dimension=dimension)
    limits = np.full(shape=(dimension, 2), fill_value=np.nan)
    for i in range(dimension):
        limits[i, 0] = -1
        limits[i, 1] = 1

    model = RMTB(xlimits=limits, order=order)
    model.set_training_values(training_points, training_values)
    model.train()

Error:

/rmtb_issue.py                                                                                                                                        master ◼
___________________________________________________________________________

                                   RMTB
___________________________________________________________________________

 Problem size

      # training points.        : 10

___________________________________________________________________________

 Training

   Training ...
      Pre-computing matrices ...
         Computing dof2coeff ...
         Computing dof2coeff - done. Time (sec):  0.0000021
         Initializing Hessian ...
         Initializing Hessian - done. Time (sec):  0.0004039
         Computing energy terms ...
Traceback (most recent call last):
  File "~/smt/./rmtb_issue.py", line 33, in <module>
    model.train()
  File "~/smt/smt/surrogate_models/surrogate_model.py", line 275, in train
    self._train()
  File "~/smt/smt/surrogate_models/rmts.py", line 443, in _train
    self._new_train()
  File "~/smt/smt/surrogate_models/rmts.py", line 406, in _new_train
    self._compute_energy_terms() * self.options["energy_weight"]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/smt/smt/surrogate_models/rmts.py", line 202, in _compute_energy_terms
    self.rmtsc.compute_quadrature_points(
  File "smt/src/rmts/rmtsclib.pyx", line 40, in smt.surrogate_models.rmtsclib.PyRMTB.compute_quadrature_points
    self.thisptr.compute_quadrature_points(n, &nelem_list[0], &x[0])
IndexError: Out of bounds on buffer access (axis 0)

Tracing this down a bit, I found that x is an empty list, which does indeed make &x[0] a out-of-bounds access.

As an aside, if you specify the order as anything > 16, you get the following error message:

Traceback (most recent call last):
  File "~/smt/./rmtb_issue.py", line 33, in <module>
    model.train()
  File "~/smt/smt/surrogate_models/surrogate_model.py", line 275, in train
    self._train()
  File "~/smt/smt/surrogate_models/rmts.py", line 443, in _train
    self._new_train()
  File "~/smt/smt/surrogate_models/rmts.py", line 406, in _new_train
    self._compute_energy_terms() * self.options["energy_weight"]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/smt/smt/surrogate_models/rmts.py", line 209, in _compute_energy_terms
    mtx = self._compute_jac(kx + 1, kx + 1, x)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/smt/smt/surrogate_models/rmts.py", line 142, in _compute_jac
    full_jac = scipy.sparse.csc_matrix(
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/smt/venv_smt/lib/python3.12/site-packages/scipy/sparse/_compressed.py", line 54, in __init__
    self._coo_container(arg1, shape=shape, dtype=dtype)
  File "~/smt/venv_smt/lib/python3.12/site-packages/scipy/sparse/_coo.py", line 99, in __init__
    self._check()
  File "~/smt/venv_smt/lib/python3.12/site-packages/scipy/sparse/_coo.py", line 190, in _check
    raise ValueError('column index exceeds matrix dimensions')
ValueError: column index exceeds matrix dimensions
NAThompson commented 1 month ago

@relf : I've attempted a fix, but this one is beyond my powers and everything I've tried thus far makes the problem worse . . .