MFEM  v3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
vector.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.googlecode.com.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 // Implementation of data type vector
13 
14 #include <iostream>
15 #include <iomanip>
16 #include <cmath>
17 #include <cstdlib>
18 #include <ctime>
19 #include <limits>
20 
21 #include "vector.hpp"
22 
23 namespace mfem
24 {
25 
27 {
28  int s = v.Size();
29  if (s > 0)
30  {
31  allocsize = size = s;
32  data = new double[s];
33  for (int i = 0; i < s; i++)
34  data[i] = v(i);
35  }
36  else
37  {
38  allocsize = size = 0;
39  data = NULL;
40  }
41 }
42 
43 void Vector::Load(std::istream **in, int np, int *dim)
44 {
45  int i, j, s;
46 
47  s = 0;
48  for (i = 0; i < np; i++)
49  s += dim[i];
50 
51  SetSize(s);
52 
53  int p = 0;
54  for (i = 0; i < np; i++)
55  for (j = 0; j < dim[i]; j++)
56  *in[i] >> data[p++];
57 }
58 
59 void Vector::Load(std::istream &in, int Size)
60 {
61  SetSize(Size);
62 
63  for (int i = 0; i < size; i++)
64  in >> data[i];
65 }
66 
67 double &Vector::Elem(int i)
68 {
69  return operator()(i);
70 }
71 
72 const double &Vector::Elem(int i) const
73 {
74  return operator()(i);
75 }
76 
77 double Vector::operator*(const double *v) const
78 {
79  int s = size;
80  const double *d = data;
81  double prod = 0.0;
82 #ifdef MFEM_USE_OPENMP
83 #pragma omp parallel for reduction(+:prod)
84 #endif
85  for (int i = 0; i < s; i++)
86  prod += d[i] * v[i];
87  return prod;
88 }
89 
90 double Vector::operator*(const Vector &v) const
91 {
92 #ifdef MFEM_DEBUG
93  if (v.size != size)
94  mfem_error("Vector::operator*(const Vector &) const");
95 #endif
96 
97  return operator*(v.data);
98 }
99 
100 Vector &Vector::operator=(const double *v)
101 {
102  for (int i = 0; i < size; i++)
103  data[i] = v[i];
104  return *this;
105 }
106 
108 {
109  SetSize(v.Size());
110  for (int i = 0; i < size; i++)
111  data[i] = v.data[i];
112  return *this;
113 }
114 
115 Vector &Vector::operator=(double value)
116 {
117  int i, s = size;
118  double *p = data, v = value;
119  for (i = 0; i < s; i++)
120  *(p++) = v;
121  return *this;
122 }
123 
125 {
126  for (int i = 0; i < size; i++)
127  data[i] *= c;
128  return *this;
129 }
130 
132 {
133  double m = 1.0/c;
134  for (int i = 0; i < size; i++)
135  data[i] *= m;
136  return *this;
137 }
138 
140 {
141  for (int i = 0; i < size; i++)
142  data[i] -= c;
143  return *this;
144 }
145 
147 {
148 #ifdef MFEM_DEBUG
149  if (size != v.size)
150  mfem_error("Vector::operator-=(const Vector &)");
151 #endif
152  for (int i = 0; i < size; i++)
153  data[i] -= v(i);
154  return *this;
155 }
156 
158 {
159 #ifdef MFEM_DEBUG
160  if (size != v.size)
161  mfem_error("Vector::operator+=(const Vector &)");
162 #endif
163  for (int i = 0; i < size; i++)
164  data[i] += v(i);
165  return *this;
166 }
167 
168 Vector &Vector::Add(const double a, const Vector &Va)
169 {
170 #ifdef MFEM_DEBUG
171  if (size != Va.size)
172  mfem_error("Vector::Add(const double, const Vector &)");
173 #endif
174  if (a != 0.0)
175  {
176  for (int i = 0; i < size; i++)
177  data[i] += a * Va(i);
178  }
179  return *this;
180 }
181 
182 Vector &Vector::Set(const double a, const Vector &Va)
183 {
184 #ifdef MFEM_DEBUG
185  if (size != Va.size)
186  mfem_error("Vector::Set(const double, const Vector &)");
187 #endif
188  for (int i = 0; i < size; i++)
189  data[i] = a * Va(i);
190  return *this;
191 }
192 
193 void Vector::SetVector(const Vector &v, int offset)
194 {
195  int vs = v.Size();
196  double *vp = v.data, *p = data + offset;
197 
198 #ifdef MFEM_DEBUG
199  if (offset+vs > size)
200  mfem_error("Vector::SetVector(const Vector &, int)");
201 #endif
202 
203  for (int i = 0; i < vs; i++)
204  p[i] = vp[i];
205 }
206 
208 {
209  for (int i = 0; i < size; i++)
210  data[i] = -data[i];
211 }
212 
213 void swap(Vector *v1, Vector *v2)
214 {
215  int size = v1->size, allocsize = v1->allocsize;
216  double *data = v1->data;
217 
218  v1->size = v2->size;
219  v1->allocsize = v2->allocsize;
220  v1->data = v2->data;
221 
222  v2->size = size;
223  v2->allocsize = allocsize;
224  v2->data = data;
225 }
226 
227 void add(const Vector &v1, const Vector &v2, Vector &v)
228 {
229 #ifdef MFEM_DEBUG
230  if (v.size != v1.size || v.size != v2.size)
231  mfem_error("add(Vector &v1, Vector &v2, Vector &v)");
232 #endif
233 
234 #ifdef MFEM_USE_OPENMP
235 #pragma omp parallel for
236 #endif
237  for (int i = 0; i < v.size; i++)
238  v.data[i] = v1.data[i] + v2.data[i];
239 }
240 
241 void add(const Vector &v1, double alpha, const Vector &v2, Vector &v)
242 {
243 #ifdef MFEM_DEBUG
244  if (v.size != v1.size || v.size != v2.size)
245  mfem_error ("add(Vector &v1, double alpha, Vector &v2, Vector &v)");
246 #endif
247  if (alpha == 0.0)
248  {
249  v = v1;
250  }
251  else if (alpha == 1.0)
252  {
253  add(v1, v2, v);
254  }
255  else
256  {
257  const double *v1p = v1.data, *v2p = v2.data;
258  double *vp = v.data;
259  int s = v.size;
260 #ifdef MFEM_USE_OPENMP
261 #pragma omp parallel for
262 #endif
263  for (int i = 0; i < s; i++)
264  vp[i] = v1p[i] + alpha*v2p[i];
265  }
266 }
267 
268 void add(const double a, const Vector &x, const Vector &y, Vector &z)
269 {
270 #ifdef MFEM_DEBUG
271  if (x.size != y.size || x.size != z.size)
272  mfem_error ("add(const double a, const Vector &x, const Vector &y,"
273  " Vector &z)");
274 #endif
275  if (a == 0.0)
276  {
277  z = 0.0;
278  }
279  else if (a == 1.0)
280  {
281  add(x, y, z);
282  }
283  else
284  {
285  const double *xp = x.data;
286  const double *yp = y.data;
287  double *zp = z.data;
288  int s = x.size;
289 
290 #ifdef MFEM_USE_OPENMP
291 #pragma omp parallel for
292 #endif
293  for (int i = 0; i < s; i++)
294  zp[i] = a * (xp[i] + yp[i]);
295  }
296 }
297 
298 void add(const double a, const Vector &x,
299  const double b, const Vector &y, Vector &z)
300 {
301 #ifdef MFEM_DEBUG
302  if (x.size != y.size || x.size != z.size)
303  mfem_error("add(const double a, const Vector &x,\n"
304  " const double b, const Vector &y, Vector &z)");
305 #endif
306  if (a == 0.0)
307  {
308  z.Set(b, y);
309  }
310  else if (b == 0.0)
311  {
312  z.Set(a, x);
313  }
314  else if (a == 1.0)
315  {
316  add(x, b, y, z);
317  }
318  else if (b == 1.0)
319  {
320  add(y, a, x, z);
321  }
322  else if (a == b)
323  {
324  add(a, x, y, z);
325  }
326  else
327  {
328  const double *xp = x.data;
329  const double *yp = y.data;
330  double *zp = z.data;
331  int s = x.size;
332 
333 #ifdef MFEM_USE_OPENMP
334 #pragma omp parallel for
335 #endif
336  for (int i = 0; i < s; i++)
337  zp[i] = a * xp[i] + b * yp[i];
338  }
339 }
340 
341 void subtract(const Vector &x, const Vector &y, Vector &z)
342 {
343 #ifdef MFEM_DEBUG
344  if (x.size != y.size || x.size != z.size)
345  mfem_error ("subtract(const Vector &, const Vector &, Vector &)");
346 #endif
347  const double *xp = x.data;
348  const double *yp = y.data;
349  double *zp = z.data;
350  int s = x.size;
351 
352 #ifdef MFEM_USE_OPENMP
353 #pragma omp parallel for
354 #endif
355  for (int i = 0; i < s; i++)
356  zp[i] = xp[i] - yp[i];
357 }
358 
359 void subtract(const double a, const Vector &x, const Vector &y, Vector &z)
360 {
361 #ifdef MFEM_DEBUG
362  if (x.size != y.size || x.size != z.size)
363  mfem_error("subtract(const double a, const Vector &x,"
364  " const Vector &y, Vector &z)");
365 #endif
366 
367  if (a == 0.)
368  {
369  z = 0.;
370  }
371  else if (a == 1.)
372  {
373  subtract(x, y, z);
374  }
375  else
376  {
377  const double *xp = x.data;
378  const double *yp = y.data;
379  double *zp = z.data;
380  int s = x.size;
381 
382 #ifdef MFEM_USE_OPENMP
383 #pragma omp parallel for
384 #endif
385  for (int i = 0; i < s; i++)
386  zp[i] = a * (xp[i] - yp[i]);
387  }
388 }
389 
390 void Vector::median(const Vector &lo, const Vector &hi)
391 {
392  double *v = data;
393 
394  for (int i = 0; i < size; i++)
395  {
396  if (v[i] < lo[i])
397  v[i] = lo[i];
398  else if (v[i] > hi[i])
399  v[i] = hi[i];
400  }
401 }
402 
403 void Vector::GetSubVector(const Array<int> &dofs, Vector &elemvect) const
404 {
405  int i, j, n = dofs.Size();
406 
407  elemvect.SetSize (n);
408 
409  for (i = 0; i < n; i++)
410  if ((j=dofs[i]) >= 0)
411  elemvect(i) = data[j];
412  else
413  elemvect(i) = -data[-1-j];
414 }
415 
416 void Vector::GetSubVector(const Array<int> &dofs, double *elem_data) const
417 {
418  int i, j, n = dofs.Size();
419 
420  for (i = 0; i < n; i++)
421  if ((j=dofs[i]) >= 0)
422  elem_data[i] = data[j];
423  else
424  elem_data[i] = -data[-1-j];
425 }
426 
427 void Vector::SetSubVector(const Array<int> &dofs, const Vector &elemvect)
428 {
429  int i, j, n = dofs.Size();
430 
431  for (i = 0; i < n; i++)
432  if ((j=dofs[i]) >= 0)
433  data[j] = elemvect(i);
434  else
435  data[-1-j] = -elemvect(i);
436 }
437 
438 void Vector::SetSubVector(const Array<int> &dofs, double *elem_data)
439 {
440  int i, j, n = dofs.Size();
441 
442  for (i = 0; i < n; i++)
443  if ((j=dofs[i]) >= 0)
444  data[j] = elem_data[i];
445  else
446  data[-1-j] = -elem_data[i];
447 }
448 
449 void Vector::AddElementVector(const Array<int> &dofs, const Vector &elemvect)
450 {
451  int i, j, n = dofs.Size();
452 
453  for (i = 0; i < n; i++)
454  if ((j=dofs[i]) >= 0)
455  data[j] += elemvect(i);
456  else
457  data[-1-j] -= elemvect(i);
458 }
459 
460 void Vector::AddElementVector(const Array<int> &dofs, double *elem_data)
461 {
462  int i, j, n = dofs.Size();
463 
464  for (i = 0; i < n; i++)
465  if ((j=dofs[i]) >= 0)
466  data[j] += elem_data[i];
467  else
468  data[-1-j] -= elem_data[i];
469 }
470 
471 void Vector::AddElementVector(const Array<int> &dofs, const double a,
472  const Vector &elemvect)
473 {
474  int i, j, n = dofs.Size();
475 
476  for (i = 0; i < n; i++)
477  if ((j=dofs[i]) >= 0)
478  data[j] += a * elemvect(i);
479  else
480  data[-1-j] -= a * elemvect(i);
481 }
482 
483 void Vector::Print(std::ostream &out, int width) const
484 {
485  if (!size) return;
486 
487  for (int i = 0; 1; )
488  {
489  out << data[i];
490  i++;
491  if (i == size)
492  break;
493  if ( i % width == 0 )
494  out << '\n';
495  else
496  out << ' ';
497  }
498  out << '\n';
499 }
500 
501 void Vector::Print_HYPRE(std::ostream &out) const
502 {
503  int i;
504  std::ios::fmtflags old_fmt = out.flags();
505  out.setf(std::ios::scientific);
506  std::streamsize old_prec = out.precision(14);
507 
508  out << size << '\n'; // number of rows
509 
510  for (i = 0; i < size; i++)
511  out << data[i] << '\n';
512 
513  out.precision(old_prec);
514  out.flags(old_fmt);
515 }
516 
517 void Vector::Randomize(int seed)
518 {
519  // static unsigned int seed = time(0);
520  const double max = (double)(RAND_MAX) + 1.;
521 
522  if (seed == 0)
523  seed = (int)time(0);
524 
525  // srand(seed++);
526  srand((unsigned)seed);
527 
528  for (int i = 0; i < size; i++)
529  data[i] = fabs(rand()/max);
530 }
531 
532 double Vector::Norml2() const
533 {
534  return sqrt((*this)*(*this));
535 }
536 
537 double Vector::Normlinf() const
538 {
539  double max = fabs(data[0]);
540 
541  for (int i = 1; i < size; i++)
542  if (fabs(data[i]) > max)
543  max = fabs(data[i]);
544 
545  return max;
546 }
547 
548 double Vector::Norml1() const
549 {
550  double sum = 0.0;
551 
552  for (int i = 0; i < size; i++)
553  sum += fabs (data[i]);
554 
555  return sum;
556 }
557 
558 double Vector::Normlp(double p) const
559 {
560  MFEM_ASSERT(p > 0.0, "Vector::Normlp");
561  if (p == 1.0)
562  return Norml1();
563  if (p == 2.0)
564  return Norml2();
565  if (p < std::numeric_limits<double>::infinity())
566  {
567  double sum = 0.0;
568  for (int i = 0; i < size; i++)
569  sum += pow(fabs(data[i]), p);
570  return pow(sum, 1.0/p);
571  }
572  else
573  return Normlinf();
574 }
575 
576 double Vector::Max() const
577 {
578  double max = data[0];
579 
580  for (int i = 1; i < size; i++)
581  if (data[i] > max)
582  max = data[i];
583 
584  return max;
585 }
586 
587 double Vector::Min() const
588 {
589  double min = data[0];
590 
591  for (int i = 1; i < size; i++)
592  if (data[i] < min)
593  min = data[i];
594 
595  return min;
596 }
597 
598 double Vector::Sum() const
599 {
600  double sum = 0.0;
601 
602  for (int i = 0; i < size; i++)
603  sum += data[i];
604 
605  return sum;
606 }
607 
608 double Vector::DistanceTo(const double *p) const
609 {
610  return Distance(data, p, size);
611 }
612 
613 }
int Size() const
Logical size of the array.
Definition: array.hpp:108
void SetVector(const Vector &v, int offset)
Definition: vector.cpp:193
Vector()
Default constructor for Vector. Sets size = 0 and data = NULL.
Definition: vector.hpp:39
double & Elem(int i)
Sets value in vector. Index i = 0 .. size-1.
Definition: vector.cpp:67
void Print(std::ostream &out=std::cout, int width=8) const
Prints vector to stream out.
Definition: vector.cpp:483
void SetSize(int s)
Resizes the vector if the new size is different.
Definition: vector.hpp:248
double Norml2() const
Returns the l2 norm of the vector.
Definition: vector.cpp:532
double & operator()(int i)
Sets value in vector. Index i = 0 .. size-1.
Definition: vector.hpp:271
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Definition: vector.cpp:403
int Size() const
Returns the size of the vector.
Definition: vector.hpp:76
double Normlinf() const
Returns the l_infinity norm of the vector.
Definition: vector.cpp:537
void Randomize(int seed=0)
Set random values in the vector.
Definition: vector.cpp:517
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition: vector.cpp:227
double operator*(const double *) const
Definition: vector.cpp:77
Vector & operator=(const double *v)
Definition: vector.cpp:100
void Load(std::istream **in, int np, int *dim)
Reads a vector from multiple files.
Definition: vector.cpp:43
double Normlp(double p) const
Returns the l_p norm of the vector.
Definition: vector.cpp:558
void median(const Vector &lo, const Vector &hi)
v = median(v,lo,hi) entrywise. Implementation assumes lo &lt;= hi.
Definition: vector.cpp:390
void AddElementVector(const Array< int > &dofs, const Vector &elemvect)
Add (element) subvector to the vector.
Definition: vector.cpp:449
Vector & operator/=(double c)
Definition: vector.cpp:131
double DistanceTo(const double *p) const
Compute the Euclidian distance to another vector.
Definition: vector.cpp:608
Vector & operator*=(double c)
Definition: vector.cpp:124
double Min() const
Returns the minimal element of the vector.
Definition: vector.cpp:587
double Norml1() const
Returns the l_1 norm of the vector.
Definition: vector.cpp:548
double Distance(const double *x, const double *y, const int n)
Definition: vector.hpp:297
void subtract(const Vector &x, const Vector &y, Vector &z)
Definition: vector.cpp:341
void swap(Vector *v1, Vector *v2)
Definition: vector.cpp:213
void mfem_error(const char *msg)
Definition: error.cpp:23
void SetSubVector(const Array< int > &dofs, const Vector &elemvect)
Definition: vector.cpp:427
void Print_HYPRE(std::ostream &out) const
Prints vector to stream out in HYPRE_Vector format.
Definition: vector.cpp:501
Vector & Set(const double a, const Vector &x)
(*this) = a * x
Definition: vector.cpp:182
Vector & Add(const double a, const Vector &Va)
(*this) += a * Va
Definition: vector.cpp:168
double Max() const
Returns the maximal element of the vector.
Definition: vector.cpp:576
Vector & operator-=(double c)
Definition: vector.cpp:139
Vector data type.
Definition: vector.hpp:29
int allocsize
Definition: vector.hpp:33
Vector & operator+=(const Vector &v)
Definition: vector.cpp:157
double * data
Definition: vector.hpp:34
double Sum() const
Return the sum of the vector entries.
Definition: vector.cpp:598
void Neg()
(*this) = -(*this)
Definition: vector.cpp:207