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