HermesCommon  3.0
vector.cpp
Go to the documentation of this file.
1 // This file is part of HermesCommon
2 //
3 // Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR).
4 // Email: hpfem-group@unr.edu, home page: http://www.hpfem.org/.
5 //
6 // Hermes2D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published
8 // by the Free Software Foundation; either version 2 of the License,
9 // or (at your option) any later version.
10 //
11 // Hermes2D 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 General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with Hermes2D; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "common.h"
23 #include "matrix.h"
24 #include "callstack.h"
25 
34 #include "qsort.h"
35 #include "api.h"
36 #include "util/memory_handling.h"
37 
38 namespace Hermes
39 {
40  namespace Algebra
41  {
42  double inline real(double x)
43  {
44  return x;
45  }
46 
47  double inline imag(double x)
48  {
49  return 0;
50  }
51 
52  double inline real(std::complex<double> x)
53  {
54  return x.real();
55  }
56 
57  double inline imag(std::complex<double> x)
58  {
59  return x.imag();
60  }
61 
62  template<typename Scalar>
64  {
65  }
66 
67  template<typename Scalar>
68  Vector<Scalar>::Vector(unsigned int size) : size(size)
69  {
70  }
71 
72  template<typename Scalar>
74  {
75  assert(this->get_size() == vec->get_size());
76  for (unsigned int i = 0; i < this->get_size(); i++)
77  this->set(i, vec->get(i));
78  return this;
79  }
80 
81  template<typename Scalar>
83  {
84  for (unsigned int i = 0; i < this->get_size(); i++)
85  this->set(i, vec[i]);
86  return this;
87  }
88 
89  template<typename Scalar>
91  {
92  assert(this->get_size() == vec->get_size());
93  for (unsigned int i = 0; i < this->get_size(); i++)
94  this->add(i, vec->get(i));
95  return this;
96  }
97 
98  template<typename Scalar>
100  {
101  for (unsigned int i = 0; i < this->get_size(); i++)
102  this->add(i, vec[i]);
103  return this;
104  }
105 
106  template<typename Scalar>
108  {
109  assert(this->get_size() == vec->get_size());
110  for (unsigned int i = 0; i < this->get_size(); i++)
111  this->add(i, -vec->get(i));
112  return this;
113  }
114 
115  template<typename Scalar>
117  {
118  for (unsigned int i = 0; i < this->get_size(); i++)
119  this->add(i, -vec[i]);
120  return this;
121  }
122 
123  template<typename Scalar>
124  void SimpleVector<Scalar>::export_to_file(const char *filename, const char *var_name, MatrixExportFormat fmt, char* number_format)
125  {
126  if (!v)
127  throw Exceptions::MethodNotOverridenException("Vector<Scalar>::export_to_file");
128 
129  switch (fmt)
130  {
132  {
133  FILE* file = fopen(filename, "w");
134  if (!file)
135  throw Exceptions::IOException(Exceptions::IOException::Write, filename);
137  fprintf(file, "%%%%MatrixMarket matrix coordinate real general\n");
138  else
139  fprintf(file, "%%%%MatrixMarket matrix coordinate complex general\n");
140 
141  fprintf(file, "%d 1 %d\n", this->size, this->size);
142 
143  for (unsigned int j = 0; j < this->size; j++)
144  {
145  Hermes::Helpers::fprint_coordinate_num(file, j + 1, 1, v[j], number_format);
146  fprintf(file, "\n");
147  }
148 
149  fclose(file);
150  }
151  break;
152 
154  {
155 #ifdef WITH_MATIO
156  size_t dims[2];
157  dims[0] = this->size;
158  dims[1] = 1;
159 
160  mat_t *mat = Mat_CreateVer(filename, "", MAT_FT_MAT5);
161  matvar_t *matvar;
162 
163  // For complex.
164  double* v_re = nullptr;
165  double* v_im = nullptr;
166 
167  void* data;
169  {
170  data = v;
171  matvar = Mat_VarCreate(var_name, MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, data, MAT_F_DONT_COPY_DATA);
172  }
173  else
174  {
175  v_re = malloc_with_check<SimpleVector<Scalar>, double>(this->size, this);
176  v_im = malloc_with_check<SimpleVector<Scalar>, double>(this->size, this);
177  struct mat_complex_split_t z = { v_re, v_im };
178 
179  for (int i = 0; i < this->size; i++)
180  {
181  v_re[i] = ((std::complex<double>)(this->v[i])).real();
182  v_im[i] = ((std::complex<double>)(this->v[i])).imag();
183  data = &z;
184  }
185  matvar = Mat_VarCreate(var_name, MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, data, MAT_F_DONT_COPY_DATA | MAT_F_COMPLEX);
186  }
187 
188  if (matvar)
189  {
190  Mat_VarWrite(mat, matvar, MAT_COMPRESSION_ZLIB);
191  Mat_VarFree(matvar);
192  }
193 
194  free_with_check(v_re);
195  free_with_check(v_im);
196  Mat_Close(mat);
197 
198  if (!matvar)
199  throw Exceptions::IOException(Exceptions::IOException::Write, filename);
200 #else
201  throw Exceptions::Exception("MATIO not included.");
202 #endif
203  }
204  break;
205 
207  case EXPORT_FORMAT_MATLAB_SIMPLE:
208  {
209  FILE* file = fopen(filename, "w");
210  if (!file)
211  throw Exceptions::IOException(Exceptions::IOException::Write, filename);
212  for (unsigned int i = 0; i < this->size; i++)
213  {
214  Hermes::Helpers::fprint_num(file, v[i], number_format);
215  fprintf(file, "\n");
216  }
217  fclose(file);
218  }
219  break;
220 
221 #ifdef WITH_BSON
222  case EXPORT_FORMAT_BSON:
223  {
224  // Init bson
225  bson bw;
226  bson_init(&bw);
227 
228  // Matrix size.
229  bson_append_int(&bw, "size", this->size);
230 
231  bson_append_start_array(&bw, "v");
232  for (unsigned int i = 0; i < this->size; i++)
233  bson_append_double(&bw, "v_i", real(this->v[i]));
234  bson_append_finish_array(&bw);
235 
237  {
238  bson_append_start_array(&bw, "v-imag");
239  for (unsigned int i = 0; i < this->size; i++)
240  bson_append_double(&bw, "v_i", imag(this->v[i]));
241  bson_append_finish_array(&bw);
242  }
243 
244  // Done.
245  bson_finish(&bw);
246 
247  // Write to disk.
248  FILE *fpw;
249  fpw = fopen(filename, "wb");
250  const char *dataw = (const char *)bson_data(&bw);
251  fwrite(dataw, bson_size(&bw), 1, fpw);
252  fclose(fpw);
253 
254  bson_destroy(&bw);
255  }
256 #endif
257  }
258  }
259 
260  template<typename Scalar>
261  void SimpleVector<Scalar>::import_from_file(const char *filename, const char *var_name, MatrixExportFormat fmt)
262  {
263  switch (fmt)
264  {
266  {
267  std::vector<Scalar> data;
268  std::ifstream input(filename);
269  if (input.bad())
270  throw Exceptions::IOException(Exceptions::IOException::Read, filename);
271  std::string lineData;
272 
273  while (getline(input, lineData))
274  {
275  Scalar d;
276  std::stringstream lineStream(lineData);
277  lineStream >> d;
278  data.push_back(d);
279  }
280 
281  this->alloc(data.size());
282  memcpy(this->v, &data[0], sizeof(Scalar)*data.size());
283  }
284  break;
286 #ifdef WITH_MATIO
287  mat_t *matfp;
288  matvar_t *matvar;
289 
290  matfp = Mat_Open(filename, MAT_ACC_RDONLY);
291 
292  if (!matfp)
293  {
294  throw Exceptions::IOException(Exceptions::IOException::Read, filename);
295  return;
296  }
297 
298  matvar = Mat_VarRead(matfp, var_name);
299  if (matvar)
300  {
301  this->alloc(matvar->dims[0]);
303  memcpy(this->v, matvar->data, sizeof(Scalar)*this->size);
304  else
305  {
306  std::complex<double>* complex_data = malloc_with_check<SimpleVector<Scalar>, std::complex<double> >(this->size, this);
307  double* real_array = (double*)((mat_complex_split_t*)matvar->data)->Re;
308  double* imag_array = (double*)((mat_complex_split_t*)matvar->data)->Im;
309  for (int i = 0; i < this->size; i++)
310  complex_data[i] = std::complex<double>(real_array[i], imag_array[i]);
311  memcpy(this->v, complex_data, sizeof(Scalar)*this->size);
312  free_with_check(complex_data);
313  }
314  }
315 
316  Mat_Close(matfp);
317  if (!matvar)
318  throw Exceptions::IOException(Exceptions::IOException::Read, filename);
319 #else
320  throw Exceptions::Exception("MATIO not included.");
321 #endif
322  break;
324  throw Hermes::Exceptions::MethodNotImplementedException("SimpleVector<Scalar>::import_from_file - Matrix Market");
325  break;
326 #ifdef WITH_BSON
327  case EXPORT_FORMAT_BSON:
328  {
329  FILE *fpr;
330  fpr = fopen(filename, "rb");
331 
332  // file size:
333  fseek(fpr, 0, SEEK_END);
334  int size = ftell(fpr);
335  rewind(fpr);
336 
337  // allocate memory to contain the whole file:
338  char *datar = malloc_with_check<char>(size);
339  fread(datar, size, 1, fpr);
340  fclose(fpr);
341 
342  bson br;
343  bson_init_finished_data(&br, datar, 0);
344 
345  bson_iterator it;
346  bson sub;
347  bson_find(&it, &br, "size");
348  this->size = bson_iterator_int(&it);
349 
350  this->v = malloc_with_check<SimpleVector<Scalar>, Scalar>(this->size, this);
351 
352  bson_iterator it_coeffs;
353  bson_find(&it_coeffs, &br, "v");
354  bson_iterator_subobject_init(&it_coeffs, &sub, 0);
355  bson_iterator_init(&it, &sub);
356  int index_coeff = 0;
357  while (bson_iterator_next(&it))
358  this->v[index_coeff++] = bson_iterator_double(&it);
359 
361  {
362  bson_find(&it_coeffs, &br, "v-imag");
363  bson_iterator_subobject_init(&it_coeffs, &sub, 0);
364  bson_iterator_init(&it, &sub);
365  index_coeff = 0;
366  while (bson_iterator_next(&it))
367  ((std::complex<double>)this->v[index_coeff++]).imag(bson_iterator_double(&it));
368  }
369 
370  bson_destroy(&br);
371  free_with_check(datar);
372  }
373  break;
374 #endif
375  }
376  }
377 
378  template<typename Scalar>
379  SimpleVector<Scalar>::SimpleVector() : Vector<Scalar>(), v(nullptr)
380  {
381  }
382 
383  template<typename Scalar>
384  SimpleVector<Scalar>::SimpleVector(unsigned int size) : Vector<Scalar>(size), v(nullptr)
385  {
386  if (this->size == 0)
387  throw Exceptions::ValueException("size", this->size, 1);
388  this->alloc(this->size);
389  }
390 
391  template<typename Scalar>
393  {
394  free();
395  }
396 
397  template<typename Scalar>
399  {
400  assert(this->get_size() == vec->get_size());
401  SimpleVector<Scalar>* simple_vec = (SimpleVector<Scalar>*)vec;
402  if (simple_vec)
403  memcpy(this->v, simple_vec->v, sizeof(Scalar)*this->size);
404  else
406  return this;
407  }
408 
409  template<typename Scalar>
411  {
412  memcpy(this->v, vec, sizeof(Scalar)*this->size);
413  return this;
414  }
415 
416  template<typename Scalar>
417  void SimpleVector<Scalar>::alloc(unsigned int n)
418  {
419  free();
420  this->size = n;
421  this->v = malloc_with_check<SimpleVector<Scalar>, Scalar>(n, this);
422  zero();
423  }
424 
425  template<typename Scalar>
427  {
428  for (unsigned int i = 0; i < this->size; i++)
429  v[i] *= -1.;
430  return this;
431  }
432 
433  template<typename Scalar>
435  {
436  memset(this->v, 0, this->size * sizeof(Scalar));
437  }
438 
439  template<typename Scalar>
441  {
442  free_with_check(this->v);
443  this->size = 0;
444  }
445 
446  template<typename Scalar>
447  void SimpleVector<Scalar>::set(unsigned int idx, Scalar y)
448  {
449  this->v[idx] = y;
450  }
451  template<>
452  void SimpleVector<double>::add(unsigned int idx, double y)
453  {
454  if(y != 0.0)
455  {
456 #pragma omp atomic
457  this->v[idx] += y;
458  }
459  }
460 
461  template<>
462  void SimpleVector<std::complex<double> >::add(unsigned int idx, std::complex<double> y)
463  {
464 #pragma omp critical (SimpleVector_add)
465  this->v[idx] += y;
466  }
467 
468  template<typename Scalar>
469  void SimpleVector<Scalar>::add(unsigned int n, unsigned int *idx, Scalar *y)
470  {
471  for (unsigned int i = 0; i < n; i++)
472  this->v[idx[i]] += y[i];
473  }
474 
475  template<typename Scalar>
476  Scalar SimpleVector<Scalar>::get(unsigned int idx) const
477  {
478  return this->v[idx];
479  }
480 
481  template<typename Scalar>
483  {
484  SimpleVector<Scalar>* new_vector = new SimpleVector<Scalar>(this->size);
485  new_vector->set_vector(this->v);
486  return new_vector;
487  }
488 
489  template<typename Scalar>
490  void SimpleVector<Scalar>::extract(Scalar *v) const
491  {
492  memcpy(v, this->v, this->size * sizeof(Scalar));
493  }
494 
495  template<typename Scalar>
497  {
498  assert(this->get_size() == vec->get_size());
499  for (unsigned int i = 0; i < this->size; i++)
500  this->v[i] -= vec->get(i);
501  return this;
502  }
503 
504  template<typename Scalar>
506  {
507  for (unsigned int i = 0; i < this->size; i++)
508  this->v[i] -= vec[i];
509  return this;
510  }
511 
512  template<typename Scalar>
514  {
515  assert(this->get_size() == vec->get_size());
516  for (unsigned int i = 0; i < this->size; i++)
517  this->v[i] += vec->get(i);
518  return this;
519  }
520 
521  template<typename Scalar>
523  {
524  for (unsigned int i = 0; i < this->get_size(); i++)
525  this->v[i] += vec[i];
526  return this;
527  }
528 
529  template<>
530  HERMES_API Vector<double>* create_vector(bool use_direct_solver)
531  {
532  switch (use_direct_solver ? Hermes::HermesCommonApi.get_integral_param_value(Hermes::directMatrixSolverType) : Hermes::HermesCommonApi.get_integral_param_value(Hermes::matrixSolverType))
533  {
534  case Hermes::SOLVER_EXTERNAL:
535  {
536  return new SimpleVector < double > ;
537  }
538  case Hermes::SOLVER_AMESOS:
539  {
540 #if defined HAVE_AMESOS && defined HAVE_EPETRA
541  return new EpetraVector < double > ;
542 #else
543  throw Hermes::Exceptions::Exception("Amesos not installed.");
544 #endif
545  break;
546  }
547  case Hermes::SOLVER_AZTECOO:
548  {
549  if (use_direct_solver)
550  throw Hermes::Exceptions::Exception("The iterative solver AztecOO selected as a direct solver.");
551 #if defined HAVE_AZTECOO && defined HAVE_EPETRA
552  return new EpetraVector < double > ;
553 #else
554  throw Hermes::Exceptions::Exception("AztecOO not installed.");
555 #endif
556  break;
557  }
558  case Hermes::SOLVER_MUMPS:
559  {
560 #ifdef WITH_MUMPS
561  return new SimpleVector < double > ;
562 #else
563  throw Hermes::Exceptions::Exception("MUMPS was not installed.");
564 #endif
565  break;
566  }
567  case Hermes::SOLVER_PETSC:
568  {
569  if (use_direct_solver)
570  throw Hermes::Exceptions::Exception("The iterative solver PETSc selected as a direct solver.");
571 #ifdef WITH_PETSC
572  return new PetscVector < double > ;
573 #else
574  throw Hermes::Exceptions::Exception("PETSc not installed.");
575 #endif
576  break;
577  }
578  case Hermes::SOLVER_UMFPACK:
579  {
580 #ifdef WITH_UMFPACK
581  return new SimpleVector < double > ;
582 #else
583  throw Hermes::Exceptions::Exception("UMFPACK was not installed.");
584 #endif
585  break;
586  }
587  case Hermes::SOLVER_PARALUTION_ITERATIVE:
588  case Hermes::SOLVER_PARALUTION_AMG:
589  {
590  if (use_direct_solver)
591  throw Hermes::Exceptions::Exception("The iterative solver PARALUTION selected as a direct solver.");
592 #ifdef WITH_PARALUTION
593  return new ParalutionVector < double > ;
594 #else
595  throw Hermes::Exceptions::Exception("PARALUTION was not installed.");
596 #endif
597  break;
598  }
599  case Hermes::SOLVER_SUPERLU:
600  {
601 #ifdef WITH_SUPERLU
602  return new SimpleVector < double > ;
603 #else
604  throw Hermes::Exceptions::Exception("SuperLU was not installed.");
605 #endif
606  break;
607  }
608  default:
609  throw Hermes::Exceptions::Exception("Unknown matrix solver requested in create_vector().");
610  }
611  return nullptr;
612  }
613 
614  template<>
615  HERMES_API Vector<std::complex<double> >* create_vector(bool use_direct_solver)
616  {
617  switch (use_direct_solver ? Hermes::HermesCommonApi.get_integral_param_value(Hermes::directMatrixSolverType) : Hermes::HermesCommonApi.get_integral_param_value(Hermes::matrixSolverType))
618  {
619  case Hermes::SOLVER_EXTERNAL:
620  {
622  }
623 
624  case Hermes::SOLVER_AMESOS:
625  {
626 #if defined HAVE_AMESOS && defined HAVE_EPETRA
628 #else
629  throw Hermes::Exceptions::Exception("Amesos not installed.");
630 #endif
631  break;
632  }
633  case Hermes::SOLVER_AZTECOO:
634  {
635  if (use_direct_solver)
636  throw Hermes::Exceptions::Exception("The iterative solver AztecOO selected as a direct solver.");
637 
638 #if defined HAVE_AZTECOO && defined HAVE_EPETRA
640 #else
641  throw Hermes::Exceptions::Exception("AztecOO not installed.");
642 #endif
643  break;
644  }
645  case Hermes::SOLVER_MUMPS:
646  {
647 #ifdef WITH_MUMPS
649 #else
650  throw Hermes::Exceptions::Exception("MUMPS was not installed.");
651 #endif
652  break;
653  }
654  case Hermes::SOLVER_PETSC:
655  {
656  if (use_direct_solver)
657  throw Hermes::Exceptions::Exception("The iterative solver PETSc selected as a direct solver.");
658 #ifdef WITH_PETSC
659  return new PetscVector < std::complex<double> > ;
660 #else
661  throw Hermes::Exceptions::Exception("PETSc not installed.");
662 #endif
663  break;
664  }
665  case Hermes::SOLVER_UMFPACK:
666  {
667 #ifdef WITH_UMFPACK
669 #else
670  throw Hermes::Exceptions::Exception("UMFPACK was not installed.");
671 #endif
672  break;
673  }
674  case Hermes::SOLVER_PARALUTION_ITERATIVE:
675  case Hermes::SOLVER_PARALUTION_AMG:
676  {
677  if (use_direct_solver)
678  throw Hermes::Exceptions::Exception("The iterative solver PARALUTION selected as a direct solver.");
679 #ifdef WITH_PARALUTION
680  throw Hermes::Exceptions::Exception("PARALUTION works only for real problems.");
681 #else
682  throw Hermes::Exceptions::Exception("PARALUTION was not installed.");
683 #endif
684  break;
685  }
686  case Hermes::SOLVER_SUPERLU:
687  {
688 #ifdef WITH_SUPERLU
690 #else
691  throw Hermes::Exceptions::Exception("SuperLU was not installed.");
692 #endif
693  break;
694  }
695  default:
696  throw Hermes::Exceptions::Exception("Unknown matrix solver requested in create_vector().");
697  }
698  return nullptr;
699  }
700 
701  template class Vector < double > ;
702  template class Vector < std::complex<double> > ;
703 
704  template class SimpleVector < double > ;
705  template class SimpleVector < std::complex<double> > ;
706  }
707 }
AmesosSolver class as an interface to Amesos.
General namespace for the Hermes library.
Linear matrix solver functionality.
Exception interface Basically a std::exception, but with a constructor with string and with print_msg...
Definition: exceptions.h:49
Main Hermes API.
General (abstract) vector representation in Hermes.
virtual Scalar get(unsigned int idx) const =0
PARALUTION solver interface.
virtual void alloc(unsigned int ndofs)
Definition: vector.cpp:417
virtual void add(unsigned int idx, Scalar y)
File containing common definitions, and basic global enums etc. for HermesCommon. ...
virtual void set(unsigned int idx, Scalar y)
Definition: vector.cpp:447
virtual Vector< Scalar > * add_vector(Vector< Scalar > *vec)
Add a vector.
Definition: vector.cpp:513
virtual void zero()
Zero the vector.
Definition: vector.cpp:434
MatrixExportFormat
Format of file matrix and vector output.
virtual void extract(Scalar *v) const
Definition: vector.cpp:490
Plain ascii file lines contains row column and value.
Vector used with MUMPS solver.
Definition: vector.h:116
Vector()
Default constructor.
Definition: vector.cpp:63
virtual Vector< Scalar > * set_vector(Vector< Scalar > *vec)
Set values from a user-provided vector.
Definition: vector.cpp:73
AztecOOSolver class as an interface to AztecOO.
HERMES_COMMON_API Hermes::Api HermesCommonApi
Global instance used inside Hermes which is also accessible to users.
Definition: api.cpp:158
IO exception. Internal. Exception occurs when something fails to be written to / read from the disk...
Definition: exceptions.h:76
virtual void free()
free the memory
Definition: vector.cpp:440
File containing functionality for investigating call stack.
virtual Vector< Scalar > * set_vector(Vector< Scalar > *vec)
Set values from a user-provided vector.
Definition: vector.cpp:398
HERMES_API Vector< Scalar > * create_vector(bool use_direct_solver=false)
Function returning a vector according to the users's choice.
Definition: vector.cpp:530
virtual Vector< Scalar > * subtract_vector(Vector< Scalar > *vec)
Subtract a vector.
Definition: vector.cpp:107
Basic matrix classes and operations.
UMFPACK solver interface.
Vector< Scalar > * duplicate() const
Duplicates a matrix (including allocation).
Definition: vector.cpp:482
Type deductors.
Definition: common.h:276
MUMPS solver interface.
unsigned int get_size() const
Get vector length.
Definition: vector.h:108
virtual Vector< Scalar > * add_vector(Vector< Scalar > *vec)
Add a vector.
Definition: vector.cpp:90
virtual Vector< Scalar > * subtract_vector(Vector< Scalar > *vec)
Subtract a vector.
Definition: vector.cpp:496
virtual Vector< Scalar > * change_sign()
Multiply by minus one.
Definition: vector.cpp:426
The QuickSort routine from glibc-2.5 modified for sorting int arrays.
virtual Scalar get(unsigned int idx) const
Definition: vector.cpp:476
virtual void export_to_file(const char *filename, const char *var_name, MatrixExportFormat fmt, char *number_format="%lf")
Definition: vector.cpp:124
Method is not overriden and should be.
Definition: exceptions.h:201
PETSc solver interface.
File containing common definitions, and basic global enums etc. for HermesCommon. ...
SuperLU solver interface.
Numeric value is out of allowed range.
Definition: exceptions.h:174
virtual void import_from_file(const char *filename, const char *var_name, MatrixExportFormat fmt)
Definition: vector.cpp:261
Class representing the vector for UMFPACK.
Matrix Market which can be read by pysparse library.
Method is not overriden and should be.
Definition: exceptions.h:212