1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2020 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
19
20
21 #ifndef LIBMESH_LASPACK_VECTOR_H
22 #define LIBMESH_LASPACK_VECTOR_H
23
24
25
26 #include "libmesh/libmesh_common.h"
27
28 #ifdef LIBMESH_HAVE_LASPACK
29
30 // Local includes
31 #include "libmesh/numeric_vector.h"
32
33 // C++ includes
34 #include <cstdio> // for std::sprintf
35
36 // Laspack includes
37 #include <operats.h>
38 #include <qvector.h>
39
40 namespace libMesh
41 {
42
43 // Forward declarations
44 template <typename T> class LaspackLinearSolver;
45 template <typename T> class SparseMatrix;
46
47 /**
48 * This class provides a nice interface to the Laspack C-based data
49 * structures for serial vectors. All overridden virtual functions
50 * are documented in numeric_vector.h.
51 *
52 * \author Benjamin S. Kirk
53 * \date 2002
54 */
55 template <typename T>
56 class LaspackVector final : public NumericVector<T>
57 {
58 public:
59
60 /**
61 * Dummy-Constructor. Dimension=0
62 */
63 explicit
64 LaspackVector (const Parallel::Communicator & comm,
65 const ParallelType = AUTOMATIC);
66
67 /**
68 * Constructor. Set dimension to \p n and initialize all elements with zero.
69 */
70 explicit
71 LaspackVector (const Parallel::Communicator & comm,
72 const numeric_index_type n,
73 const ParallelType = AUTOMATIC);
74
75 /**
76 * Constructor. Set local dimension to \p n_local, the global dimension
77 * to \p n, and initialize all elements with zero.
78 */
79 LaspackVector (const Parallel::Communicator & comm,
80 const numeric_index_type n,
81 const numeric_index_type n_local,
82 const ParallelType = AUTOMATIC);
83
84 /**
85 * Constructor. Set local dimension to \p n_local, the global
86 * dimension to \p n, but additionally reserve memory for the
87 * indices specified by the \p ghost argument.
88 */
89 LaspackVector (const Parallel::Communicator & comm,
90 const numeric_index_type N,
91 const numeric_index_type n_local,
92 const std::vector<numeric_index_type> & ghost,
93 const ParallelType = AUTOMATIC);
94
95 /**
96 * Copy assignment operator.
97 * Calls Asgn_VV() to assign the contents of one vector to another.
98 * \returns A reference to *this as the derived type.
99 */
100 LaspackVector<T> & operator= (const LaspackVector<T> & v);
101
102 /**
103 * This class manages a C-style struct (QVector) manually, so we
104 * don't want to allow any automatic copy/move functions to be
105 * generated, and we can't default the destructor.
106 */
107 LaspackVector (LaspackVector &&) = delete;
108 LaspackVector (const LaspackVector &) = delete;
109 LaspackVector & operator= (LaspackVector &&) = delete;
110 virtual ~LaspackVector ();
111
112 virtual void close () override;
113
114 virtual void clear () override;
115
116 virtual void zero () override;
117
118 virtual std::unique_ptr<NumericVector<T>> zero_clone () const override;
119
120 virtual std::unique_ptr<NumericVector<T>> clone () const override;
121
122 virtual void init (const numeric_index_type N,
123 const numeric_index_type n_local,
124 const bool fast=false,
125 const ParallelType ptype=AUTOMATIC) override;
126
127 virtual void init (const numeric_index_type N,
128 const bool fast=false,
129 const ParallelType ptype=AUTOMATIC) override;
130
131 virtual void init (const numeric_index_type N,
132 const numeric_index_type n_local,
133 const std::vector<numeric_index_type> & ghost,
134 const bool fast = false,
135 const ParallelType = AUTOMATIC) override;
136
137 virtual void init (const NumericVector<T> & other,
138 const bool fast = false) override;
139
140 virtual NumericVector<T> & operator= (const T s) override;
141
142 virtual NumericVector<T> & operator= (const NumericVector<T> & v) override;
143
144 virtual NumericVector<T> & operator= (const std::vector<T> & v) override;
145
146 virtual Real min () const override;
147
148 virtual Real max () const override;
149
150 virtual T sum () const override;
151
152 virtual Real l1_norm () const override;
153
154 virtual Real l2_norm () const override;
155
156 virtual Real linfty_norm () const override;
157
158 virtual numeric_index_type size () const override;
159
160 virtual numeric_index_type local_size() const override;
161
162 virtual numeric_index_type first_local_index() const override;
163
164 virtual numeric_index_type last_local_index() const override;
165
166 virtual T operator() (const numeric_index_type i) const override;
167
168 virtual NumericVector<T> & operator += (const NumericVector<T> & v) override;
169
170 virtual NumericVector<T> & operator -= (const NumericVector<T> & v) override;
171
172 virtual NumericVector<T> & operator *= (const NumericVector<T> & v) override;
173
174 virtual NumericVector<T> & operator /= (const NumericVector<T> & v) override;
175
176 virtual void reciprocal() override;
177
178 virtual void conjugate() override;
179
180 virtual void set (const numeric_index_type i, const T value) override;
181
182 virtual void add (const numeric_index_type i, const T value) override;
183
184 virtual void add (const T s) override;
185
186 virtual void add (const NumericVector<T> & v) override;
187
188 virtual void add (const T a, const NumericVector<T> & v) override;
189
190 /**
191 * We override one NumericVector<T>::add_vector() method but don't
192 * want to hide the other defaults.
193 */
194 using NumericVector<T>::add_vector;
195
196 virtual void add_vector (const NumericVector<T> & v,
197 const SparseMatrix<T> & A) override;
198
199 virtual void add_vector_transpose (const NumericVector<T> & v,
200 const SparseMatrix<T> & A) override;
201
202 virtual void scale (const T factor) override;
203
204 virtual void abs() override;
205
206 virtual T dot(const NumericVector<T> & v) const override;
207
208 virtual void localize (std::vector<T> & v_local) const override;
209
210 virtual void localize (NumericVector<T> & v_local) const override;
211
212 virtual void localize (NumericVector<T> & v_local,
213 const std::vector<numeric_index_type> & send_list) const override;
214
215 virtual void localize (std::vector<T> & v_local,
216 const std::vector<numeric_index_type> & indices) const override;
217
218 virtual void localize (const numeric_index_type first_local_idx,
219 const numeric_index_type last_local_idx,
220 const std::vector<numeric_index_type> & send_list) override;
221
222 virtual void localize_to_one (std::vector<T> & v_local,
223 const processor_id_type proc_id=0) const override;
224
225 virtual void pointwise_mult (const NumericVector<T> & vec1,
226 const NumericVector<T> & vec2) override;
227
228 virtual void swap (NumericVector<T> & v) override;
229
230 private:
231
232 /**
233 * Actual Laspack vector datatype
234 * to hold vector entries
235 */
236 QVector _vec;
237
238 /**
239 * Make other Laspack datatypes friends
240 */
241 friend class LaspackLinearSolver<T>;
242 };
243
244
245
246 //----------------------------------------------------------
247 // LaspackVector inline methods
248 template <typename T>
249 inline
LaspackVector(const Parallel::Communicator & comm,const ParallelType ptype)250 LaspackVector<T>::LaspackVector (const Parallel::Communicator & comm,
251 const ParallelType ptype)
252 : NumericVector<T>(comm, ptype)
253 {
254 this->_type = ptype;
255 }
256
257
258
259 template <typename T>
260 inline
LaspackVector(const Parallel::Communicator & comm,const numeric_index_type n,const ParallelType ptype)261 LaspackVector<T>::LaspackVector (const Parallel::Communicator & comm,
262 const numeric_index_type n,
263 const ParallelType ptype)
264 : NumericVector<T>(comm, ptype)
265 {
266 this->init(n, n, false, ptype);
267 }
268
269
270
271 template <typename T>
272 inline
LaspackVector(const Parallel::Communicator & comm,const numeric_index_type n,const numeric_index_type n_local,const ParallelType ptype)273 LaspackVector<T>::LaspackVector (const Parallel::Communicator & comm,
274 const numeric_index_type n,
275 const numeric_index_type n_local,
276 const ParallelType ptype)
277 : NumericVector<T>(comm, ptype)
278 {
279 this->init(n, n_local, false, ptype);
280 }
281
282
283
284 template <typename T>
285 inline
LaspackVector(const Parallel::Communicator & comm,const numeric_index_type N,const numeric_index_type n_local,const std::vector<numeric_index_type> & ghost,const ParallelType ptype)286 LaspackVector<T>::LaspackVector (const Parallel::Communicator & comm,
287 const numeric_index_type N,
288 const numeric_index_type n_local,
289 const std::vector<numeric_index_type> & ghost,
290 const ParallelType ptype)
291 : NumericVector<T>(comm, ptype)
292 {
293 this->init(N, n_local, ghost, false, ptype);
294 }
295
296
297
298 template <typename T>
299 inline
~LaspackVector()300 LaspackVector<T>::~LaspackVector ()
301 {
302 this->clear ();
303 }
304
305
306
307 template <typename T>
308 inline
init(const numeric_index_type n,const numeric_index_type libmesh_dbg_var (n_local),const bool fast,const ParallelType)309 void LaspackVector<T>::init (const numeric_index_type n,
310 const numeric_index_type libmesh_dbg_var(n_local),
311 const bool fast,
312 const ParallelType)
313 {
314 // Laspack vectors only for serial cases,
315 // but can provide a "parallel" vector on one processor.
316 libmesh_assert_equal_to (n, n_local);
317
318 this->_type = SERIAL;
319
320 // Clear initialized vectors
321 if (this->initialized())
322 this->clear();
323
324 // create a sequential vector
325
326 static int cnt = 0;
327 char foo[80];
328 std::sprintf(foo, "Vec-%d", cnt++);
329
330 V_Constr(&_vec, const_cast<char *>(foo), n, Normal, _LPTrue);
331
332 this->_is_initialized = true;
333 #ifndef NDEBUG
334 this->_is_closed = true;
335 #endif
336
337 // Optionally zero out all components
338 if (fast == false)
339 this->zero ();
340
341 return;
342 }
343
344
345
346 template <typename T>
347 inline
init(const numeric_index_type n,const bool fast,const ParallelType ptype)348 void LaspackVector<T>::init (const numeric_index_type n,
349 const bool fast,
350 const ParallelType ptype)
351 {
352 this->init(n,n,fast,ptype);
353 }
354
355
356 template <typename T>
357 inline
init(const numeric_index_type n,const numeric_index_type n_local,const std::vector<numeric_index_type> & libmesh_dbg_var (ghost),const bool fast,const ParallelType ptype)358 void LaspackVector<T>::init (const numeric_index_type n,
359 const numeric_index_type n_local,
360 const std::vector<numeric_index_type> & libmesh_dbg_var(ghost),
361 const bool fast,
362 const ParallelType ptype)
363 {
364 libmesh_assert(ghost.empty());
365 this->init(n,n_local,fast,ptype);
366 }
367
368
369
370 /* Default implementation for solver packages for which ghosted
371 vectors are not yet implemented. */
372 template <class T>
init(const NumericVector<T> & other,const bool fast)373 void LaspackVector<T>::init (const NumericVector<T> & other,
374 const bool fast)
375 {
376 this->init(other.size(),other.local_size(),fast,other.type());
377 }
378
379
380
381 template <typename T>
382 inline
close()383 void LaspackVector<T>::close ()
384 {
385 libmesh_assert (this->initialized());
386
387 #ifndef NDEBUG
388 this->_is_closed = true;
389 #endif
390 }
391
392
393
394 template <typename T>
395 inline
clear()396 void LaspackVector<T>::clear ()
397 {
398 if (this->initialized())
399 {
400 V_Destr (&_vec);
401 }
402
403 this->_is_initialized = false;
404 #ifndef NDEBUG
405 this->_is_closed = false;
406 #endif
407 }
408
409
410
411 template <typename T> inline
zero()412 void LaspackVector<T>::zero ()
413 {
414 libmesh_assert (this->initialized());
415 libmesh_assert (this->closed());
416
417 V_SetAllCmp (&_vec, 0.);
418 }
419
420
421
422 template <typename T>
423 inline
zero_clone()424 std::unique_ptr<NumericVector<T>> LaspackVector<T>::zero_clone () const
425 {
426 NumericVector<T> * cloned_vector = new LaspackVector<T>(this->comm());
427
428 cloned_vector->init(*this);
429
430 return std::unique_ptr<NumericVector<T>>(cloned_vector);
431 }
432
433
434
435 template <typename T>
436 inline
clone()437 std::unique_ptr<NumericVector<T>> LaspackVector<T>::clone () const
438 {
439 NumericVector<T> * cloned_vector = new LaspackVector<T>(this->comm());
440
441 cloned_vector->init(*this, true);
442
443 *cloned_vector = *this;
444
445 return std::unique_ptr<NumericVector<T>>(cloned_vector);
446 }
447
448
449
450 template <typename T>
451 inline
size()452 numeric_index_type LaspackVector<T>::size () const
453 {
454 libmesh_assert (this->initialized());
455
456 return static_cast<numeric_index_type>(V_GetDim(const_cast<QVector*>(&_vec)));
457 }
458
459
460
461 template <typename T>
462 inline
local_size()463 numeric_index_type LaspackVector<T>::local_size () const
464 {
465 libmesh_assert (this->initialized());
466
467 return this->size();
468 }
469
470
471
472 template <typename T>
473 inline
first_local_index()474 numeric_index_type LaspackVector<T>::first_local_index () const
475 {
476 libmesh_assert (this->initialized());
477
478 return 0;
479 }
480
481
482
483 template <typename T>
484 inline
last_local_index()485 numeric_index_type LaspackVector<T>::last_local_index () const
486 {
487 libmesh_assert (this->initialized());
488
489 return this->size();
490 }
491
492
493
494 template <typename T>
495 inline
set(const numeric_index_type i,const T value)496 void LaspackVector<T>::set (const numeric_index_type i, const T value)
497 {
498 libmesh_assert (this->initialized());
499 libmesh_assert_less (i, this->size());
500
501 V_SetCmp (&_vec, i+1, value);
502
503 #ifndef NDEBUG
504 this->_is_closed = false;
505 #endif
506 }
507
508
509
510 template <typename T>
511 inline
add(const numeric_index_type i,const T value)512 void LaspackVector<T>::add (const numeric_index_type i, const T value)
513 {
514 libmesh_assert (this->initialized());
515 libmesh_assert_less (i, this->size());
516
517 V_AddCmp (&_vec, i+1, value);
518
519 #ifndef NDEBUG
520 this->_is_closed = false;
521 #endif
522 }
523
524
525
526 template <typename T>
527 inline
operator()528 T LaspackVector<T>::operator() (const numeric_index_type i) const
529 {
530 libmesh_assert (this->initialized());
531 libmesh_assert ( ((i >= this->first_local_index()) &&
532 (i < this->last_local_index())) );
533
534
535 return static_cast<T>(V_GetCmp(const_cast<QVector*>(&_vec), i+1));
536 }
537
538
539
540 template <typename T>
541 inline
swap(NumericVector<T> & other)542 void LaspackVector<T>::swap (NumericVector<T> & other)
543 {
544 LaspackVector<T> & v = cast_ref<LaspackVector<T> &>(other);
545
546 // This is all grossly dependent on Laspack version...
547
548 std::swap(_vec.Name, v._vec.Name);
549 std::swap(_vec.Dim, v._vec.Dim);
550 std::swap(_vec.Instance, v._vec.Instance);
551 std::swap(_vec.LockLevel, v._vec.LockLevel);
552 std::swap(_vec.Multipl, v._vec.Multipl);
553 std::swap(_vec.OwnData, v._vec.OwnData);
554
555 // This should still be O(1), since _vec.Cmp is just a pointer to
556 // data on the heap
557
558 std::swap(_vec.Cmp, v._vec.Cmp);
559 }
560
561
562 } // namespace libMesh
563
564
565 #endif // #ifdef LIBMESH_HAVE_LASPACK
566 #endif // LIBMESH_LASPACK_VECTOR_H
567