PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/dolfin/swig/la/la_get_set_items.i

https://bitbucket.org/aterrel/dolfin
Swig | 537 lines | 353 code | 68 blank | 116 comment | 0 complexity | 5a113c6610aaba9aed8dcb9490fbef23 MD5 | raw file
  1. /* -*- C -*- */
  2. // Copyright (C) 2009 Johan Hake
  3. //
  4. // This file is part of DOLFIN.
  5. //
  6. // DOLFIN is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU Lesser General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // DOLFIN is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU Lesser General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU Lesser General Public License
  17. // along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
  18. //
  19. // First added: 2009-04-27
  20. // Last changed: 2010-03-09
  21. // Enum for comparison functions
  22. enum DolfinCompareType {dolfin_gt, dolfin_ge, dolfin_lt, dolfin_le, dolfin_eq, dolfin_neq};
  23. // Returns the values from a Vector.
  24. // copied_values are true if the returned values are copied and need clean up.
  25. std::vector<double> _get_vector_values(dolfin::GenericVector* self)
  26. {
  27. std::vector<double> values;
  28. self->get_local(values);
  29. return values;
  30. }
  31. // A contains function for Vectors
  32. bool _contains(dolfin::GenericVector* self, double value)
  33. {
  34. bool contains = false;
  35. std::vector<double> values = _get_vector_values(self);
  36. // Check if value is in values
  37. for (std::size_t i = 0; i < self->size(); i++)
  38. {
  39. if (fabs(values[i] - value) < DOLFIN_EPS)
  40. {
  41. contains = true;
  42. break;
  43. }
  44. }
  45. return contains;
  46. }
  47. // A general compare function for Vector vs scalar comparison
  48. // The function returns a boolean numpy array
  49. PyObject* _compare_vector_with_value( dolfin::GenericVector* self, double value, DolfinCompareType cmp_type )
  50. {
  51. std::size_t i;
  52. npy_intp size = self->size();
  53. // Create the Numpy array
  54. PyArrayObject* return_array = (PyArrayObject*)PyArray_SimpleNew(1, &size, PyArray_BOOL);
  55. // Get the data array
  56. npy_bool* bool_data = (npy_bool *)PyArray_DATA(return_array);
  57. // Get the values
  58. std::vector<double> values = _get_vector_values(self);
  59. switch (cmp_type)
  60. {
  61. case dolfin_gt:
  62. for ( i = 0; i < self->size(); i++)
  63. bool_data[i] = (values[i] > value) ? 1 : 0;
  64. break;
  65. case dolfin_ge:
  66. for ( i = 0; i < self->size(); i++)
  67. bool_data[i] = (values[i] >= value) ? 1 : 0;
  68. break;
  69. case dolfin_lt:
  70. for ( i = 0; i < self->size(); i++)
  71. bool_data[i] = (values[i] < value) ? 1 : 0;
  72. break;
  73. case dolfin_le:
  74. for ( i = 0; i < self->size(); i++)
  75. bool_data[i] = (values[i] <= value) ? 1 : 0;
  76. break;
  77. case dolfin_eq:
  78. for ( i = 0; i < self->size(); i++)
  79. bool_data[i] = (values[i] == value) ? 1 : 0;
  80. break;
  81. case dolfin_neq:
  82. for ( i = 0; i < self->size(); i++)
  83. bool_data[i] = (values[i] != value) ? 1 : 0;
  84. break;
  85. default:
  86. throw std::runtime_error("invalid compare type");
  87. }
  88. return PyArray_Return(return_array);
  89. }
  90. // A general compare function for Vector vs Vector comparison
  91. // The function returns a boolean numpy array
  92. PyObject* _compare_vector_with_vector( dolfin::GenericVector* self, dolfin::GenericVector* other, DolfinCompareType cmp_type )
  93. {
  94. if (self->size() != other->size())
  95. throw std::runtime_error("non matching dimensions");
  96. std::size_t i;
  97. npy_intp size = self->size();
  98. // Create the Numpy array
  99. PyArrayObject* return_array = (PyArrayObject*)PyArray_SimpleNew(1, &size, PyArray_BOOL);
  100. // Get the data array
  101. npy_bool* bool_data = (npy_bool *)PyArray_DATA(return_array);
  102. // Get the values
  103. std::vector<double> self_values = _get_vector_values(self);
  104. std::vector<double> other_values = _get_vector_values(other);
  105. switch (cmp_type)
  106. {
  107. case dolfin_gt:
  108. for ( i = 0; i < self->size(); i++)
  109. bool_data[i] = (self_values[i] > other_values[i]) ? 1 : 0;
  110. break;
  111. case dolfin_ge:
  112. for ( i = 0; i < self->size(); i++)
  113. bool_data[i] = (self_values[i] >= other_values[i]) ? 1 : 0;
  114. break;
  115. case dolfin_lt:
  116. for ( i = 0; i < self->size(); i++)
  117. bool_data[i] = (self_values[i] < other_values[i]) ? 1 : 0;
  118. break;
  119. case dolfin_le:
  120. for ( i = 0; i < self->size(); i++)
  121. bool_data[i] = (self_values[i] <= other_values[i]) ? 1 : 0;
  122. break;
  123. case dolfin_eq:
  124. for ( i = 0; i < self->size(); i++)
  125. bool_data[i] = (self_values[i] == other_values[i]) ? 1 : 0;
  126. break;
  127. case dolfin_neq:
  128. for ( i = 0; i < self->size(); i++)
  129. bool_data[i] = (self_values[i] != other_values[i]) ? 1 : 0;
  130. break;
  131. default:
  132. throw std::runtime_error("invalid compare type");
  133. }
  134. return PyArray_Return(return_array);
  135. }
  136. // Get single Vector item
  137. double _get_vector_single_item( dolfin::GenericVector* self, int index )
  138. {
  139. double value;
  140. dolfin::la_index i(Indices::check_index(index, self->size()));
  141. // Check that requested index is owned by this process
  142. if (i < self->local_range().first || i >= self->local_range().second)
  143. throw std::runtime_error("index must belong to this process, cannot index off-process entries in a GenericVector");
  144. self->get_local(&value, 1, &i);
  145. return value;
  146. }
  147. // Get item for slice, list, or numpy array object
  148. boost::shared_ptr<dolfin::GenericVector> _get_vector_sub_vector( const dolfin::GenericVector* self, PyObject* op )
  149. {
  150. Indices* inds;
  151. dolfin::la_index* range;
  152. dolfin::la_index* indices;
  153. boost::shared_ptr<dolfin::GenericVector> return_vec;
  154. std::size_t m;
  155. // Get the correct Indices
  156. if ( (inds = indice_chooser(op, self->size())) == 0 )
  157. throw std::runtime_error("index must be either a slice, a list or a Numpy array of integer");
  158. // Fill the return vector
  159. try
  160. {
  161. indices = inds->indices();
  162. }
  163. // We can only throw and catch runtime_errors. These will be caught by swig.
  164. catch (std::runtime_error e)
  165. {
  166. delete inds;
  167. throw;
  168. }
  169. m = inds->size();
  170. // Create a default Vector
  171. return_vec = self->factory().create_vector();
  172. // Resize the vector to the size of the indices
  173. return_vec->resize(m);
  174. range = inds->range();
  175. std::vector<double> values(m);
  176. self->get_local(&values[0], m, indices);
  177. return_vec->set(&values[0], m, range);
  178. return_vec->apply("insert");
  179. delete inds;
  180. return return_vec;
  181. }
  182. // Set items using a GenericVector
  183. void _set_vector_items_vector( dolfin::GenericVector* self, PyObject* op, dolfin::GenericVector& other )
  184. {
  185. // Get the correct Indices
  186. Indices* inds;
  187. dolfin::la_index* range;
  188. dolfin::la_index* indices;
  189. std::size_t m;
  190. if ( (inds = indice_chooser(op, self->size())) == 0 )
  191. throw std::runtime_error("index must be either a slice, a list or a Numpy array of integer");
  192. // Check for size of indices
  193. if ( inds->size() != other.size() )
  194. {
  195. delete inds;
  196. throw std::runtime_error("non matching dimensions on input");
  197. }
  198. // Get the indices
  199. try
  200. {
  201. indices = inds->indices();
  202. }
  203. // We can only throw and catch runtime_errors. These will be caught by swig.
  204. catch (std::runtime_error e)
  205. {
  206. delete inds;
  207. throw;
  208. }
  209. m = inds->size();
  210. range = inds->range();
  211. std::vector<double> values(m);
  212. // Get and set values
  213. other.get_local(&values[0], m, range);
  214. self->set(&values[0], m, indices);
  215. self->apply("insert");
  216. delete inds;
  217. }
  218. // Set items using a GenericVector
  219. void _set_vector_items_array_of_float( dolfin::GenericVector* self, PyObject* op, PyObject* other )
  220. {
  221. Indices* inds;
  222. double* values;
  223. dolfin::la_index* indices;
  224. std::size_t m;
  225. bool casted = false;
  226. // Check type of values
  227. if ( !(other != Py_None and PyArray_Check(other) and PyArray_ISNUMBER(other) and PyArray_NDIM(other) == 1 and PyArray_ISCONTIGUOUS(other)))
  228. throw std::runtime_error("expected a contiguous 1D numpy array of numbers");
  229. if (PyArray_TYPE(other)!=NPY_DOUBLE)
  230. {
  231. casted = true;
  232. other = PyArray_Cast(reinterpret_cast<PyArrayObject*>(other), NPY_DOUBLE);
  233. }
  234. // Get the correct Indices
  235. if ( (inds = indice_chooser(op, self->size())) == 0 )
  236. throw std::runtime_error("index must be either a slice, a list or a Numpy array of integer");
  237. // Check for size of indices
  238. if (inds->size() != static_cast<std::size_t>(PyArray_DIM(other,0)))
  239. {
  240. delete inds;
  241. throw std::runtime_error("non matching dimensions on input");
  242. }
  243. // Fill the vector using the slice and the provided values
  244. try {
  245. indices = inds->indices();
  246. }
  247. // We can only throw and catch runtime_errors. These will be caught by swig.
  248. catch (std::runtime_error e)
  249. {
  250. delete inds;
  251. throw;
  252. }
  253. m = inds->size();
  254. // Get the contigous data from the numpy array
  255. values = (double*) PyArray_DATA(other);
  256. self->set(values, m, indices);
  257. self->apply("insert");
  258. // Clean casted array
  259. if (casted)
  260. {
  261. Py_DECREF(other);
  262. }
  263. delete inds;
  264. }
  265. // Set item(s) using single value
  266. void _set_vector_items_value(dolfin::GenericVector* self, PyObject* op, double value)
  267. {
  268. // Get the correct Indices
  269. Indices* inds;
  270. if ( (inds = indice_chooser(op, self->size())) == 0 )
  271. {
  272. // If the index is an integer
  273. if( op != Py_None and PyInteger_Check(op))
  274. self->setitem(Indices::check_index(static_cast<int>(PyInt_AsLong(op)), self->size()), value);
  275. else
  276. throw std::runtime_error("index must be either an integer, a slice, a list or a Numpy array of integer");
  277. }
  278. // The op is a Indices
  279. else
  280. {
  281. dolfin::la_index* indices;
  282. std::size_t i;
  283. // Fill the vector using the slice
  284. try {
  285. indices = inds->indices();
  286. }
  287. // We can only throw and catch runtime_errors. These will be caught by swig.
  288. catch (std::runtime_error e){
  289. delete inds;
  290. throw;
  291. }
  292. // Fill and array with the value and call set()
  293. std::vector<double> values(inds->size(), value);
  294. self->set(&values[0], inds->size(), indices);
  295. delete inds;
  296. }
  297. self->apply("insert");
  298. }
  299. // Get single item from Matrix
  300. double _get_matrix_single_item( const dolfin::GenericMatrix* self, int m, int n )
  301. {
  302. double value;
  303. dolfin::la_index _m(Indices::check_index(m, self->size(0)));
  304. dolfin::la_index _n(Indices::check_index(n, self->size(1)));
  305. self->get(&value, 1, &_m, 1, &_n);
  306. return value;
  307. }
  308. // Get items for slice, list, or numpy array object
  309. boost::shared_ptr<dolfin::GenericVector> _get_matrix_sub_vector(dolfin::GenericMatrix* self, dolfin::la_index single, PyObject* op, bool row )
  310. {
  311. // Get the correct Indices
  312. Indices* inds;
  313. if ( (inds = indice_chooser(op, self->size(row ? 1 : 0))) == 0 )
  314. throw std::runtime_error("index must be either a slice, a list or a Numpy array of integer");
  315. dolfin::la_index* indices;
  316. try
  317. {
  318. // Get the indices in a c array
  319. indices = inds->indices();
  320. }
  321. // We can only throw and catch runtime_errors. These will be caught by swig.
  322. catch (std::runtime_error e)
  323. {
  324. delete inds;
  325. throw;
  326. }
  327. // Create the value array and get the values from the matrix
  328. std::vector<double> values(inds->size());
  329. if (row)
  330. // If returning a single row
  331. self->get(&values[0], 1, &single, inds->size(), indices);
  332. else
  333. // If returning a single column
  334. self->get(&values[0], inds->size(), indices, 1, &single);
  335. // Create the return vector and set the values
  336. boost::shared_ptr<dolfin::GenericVector> return_vec = self->factory().create_vector();
  337. self->resize(*return_vec, 1);
  338. return_vec->set_local(values);
  339. return_vec->apply("insert");
  340. // Clean up
  341. delete inds;
  342. return return_vec;
  343. }
  344. /*
  345. // Get items for slice, list, or numpy array object
  346. dolfin::GenericMatrix* _get_matrix_sub_matrix(const dolfin::GenericMatrix* self,
  347. PyObject* row_op, PyObject* col_op )
  348. {
  349. dolfin::GenericMatrix* return_mat;
  350. dolfin::uint i, j, k, m, n, nz_i;
  351. dolfin::uint* col_index_array;
  352. dolfin::uint* tmp_index_array;
  353. bool same_indices;
  354. Indices* row_inds;
  355. Indices* col_inds;
  356. double* values;
  357. // Instantiate the row indices
  358. if ( (row_inds = indice_chooser(row_op, self->size(0))) == 0 )
  359. throw std::runtime_error("row indices must be either a slice, a list or a Numpy array of integer");
  360. // The number of rows
  361. m = row_inds->size();
  362. // If None is provided for col_op we assume symmetric indices
  363. if (col_op == Py_None)
  364. {
  365. same_indices = true;
  366. // Check size of cols
  367. if (m > self->size(1))
  368. {
  369. delete row_inds;
  370. throw std::runtime_error("num indices excedes the number of columns");
  371. }
  372. // Symetric rows and columns yield equal column and row indices
  373. col_inds = row_inds;
  374. n = m;
  375. }
  376. // Non symetric rows and cols
  377. else
  378. {
  379. same_indices = false;
  380. // Instantiate the col indices
  381. if ( (col_inds = indice_chooser(col_op, self->size(1))) == 0 )
  382. {
  383. delete row_inds;
  384. throw std::runtime_error("col indices must be either a slice, a list or a Numpy array of integer");
  385. }
  386. // The number of columns
  387. n = col_inds->size();
  388. }
  389. // Access the column indices
  390. try
  391. {
  392. col_index_array = col_inds->indices();
  393. }
  394. // We can only throw and catch runtime_errors. These will be caught by swig.
  395. catch (std::runtime_error e)
  396. {
  397. delete row_inds;
  398. if (!same_indices)
  399. delete col_inds;
  400. throw;
  401. }
  402. // Create the return matrix
  403. return_mat = self->factory().create_matrix();
  404. throw std::runtime_error("Python interface for slices needs to be updated.");
  405. //return_mat->resize(m, n);
  406. // Zero the matrix (needed for the uBLASDenseMatrix)
  407. return_mat->zero();
  408. // Fill the get the values from me and set non zero values in return matrix
  409. tmp_index_array = new dolfin::uint[n];
  410. values = new double[n];
  411. for (i = 0; i < row_inds->size(); i++)
  412. {
  413. // Get all column values
  414. k = row_inds->index(i);
  415. self->get(values, 1, &k, n, col_index_array);
  416. // Collect non zero values
  417. nz_i = 0;
  418. for (j = 0; j < col_inds->size(); j++)
  419. {
  420. if ( !(fabs(values[j]) < DOLFIN_EPS) )
  421. {
  422. tmp_index_array[nz_i] = j;
  423. values[nz_i] = values[j];
  424. nz_i++;
  425. }
  426. }
  427. // Set the non zero values to return matrix
  428. return_mat->set(values, 1, &i, nz_i, tmp_index_array);
  429. }
  430. // Clean up
  431. delete row_inds;
  432. if ( !same_indices )
  433. delete col_inds;
  434. delete[] values;
  435. delete[] tmp_index_array;
  436. return_mat->apply("insert");
  437. return return_mat;
  438. }
  439. */
  440. // Set single item in Matrix
  441. void _set_matrix_single_item(dolfin::GenericMatrix* self, int m, int n, double value )
  442. {
  443. dolfin::la_index _m(Indices::check_index(m, self->size(0)));
  444. dolfin::la_index _n(Indices::check_index(n, self->size(1)));
  445. self->set(&value, 1, &_m, 1, &_n);
  446. self->apply("insert");
  447. }
  448. void _set_matrix_items_array_of_float( dolfin::GenericMatrix* self, PyObject* op, PyObject* other ){}
  449. void _set_matrix_items_matrix(dolfin::GenericMatrix* self, dolfin::GenericMatrix*) {}
  450. void _set_matrix_items_vector(dolfin::GenericMatrix* self, PyObject* op, dolfin::GenericVector& other){}