1 /* -----------------------------------------------------------------
2  * Programmer(s): Radu Serban, Aaron Collier, and
3  *                David J. Gardner @ LLNL
4  *                Daniel R. Reynolds @ SMU
5  * -----------------------------------------------------------------
6  * SUNDIALS Copyright Start
7  * Copyright (c) 2002-2020, Lawrence Livermore National Security
8  * and Southern Methodist University.
9  * All rights reserved.
10  *
11  * See the top-level LICENSE and NOTICE files for details.
12  *
13  * SPDX-License-Identifier: BSD-3-Clause
14  * SUNDIALS Copyright End
15  * -----------------------------------------------------------------
16  * This is the implementation file for a generic NVECTOR package.
17  * It contains the implementation of the N_Vector operations listed
18  * in nvector.h.
19  * -----------------------------------------------------------------*/
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include <sundials/sundials_nvector.h>
25 
26 /* -----------------------------------------------------------------
27  * Create an empty NVector object
28  * -----------------------------------------------------------------*/
29 
N_VNewEmpty()30 N_Vector N_VNewEmpty()
31 {
32   N_Vector     v;
33   N_Vector_Ops ops;
34 
35   /* create vector object */
36   v = NULL;
37   v = (N_Vector) malloc(sizeof *v);
38   if (v == NULL) return(NULL);
39 
40   /* create vector ops structure */
41   ops = NULL;
42   ops = (N_Vector_Ops) malloc(sizeof *ops);
43   if (ops == NULL) { free(v); return(NULL); }
44 
45   /* initialize operations to NULL */
46 
47   /* constructors, destructors, and utility operations */
48   ops->nvgetvectorid     = NULL;
49   ops->nvclone           = NULL;
50   ops->nvcloneempty      = NULL;
51   ops->nvdestroy         = NULL;
52   ops->nvspace           = NULL;
53   ops->nvgetarraypointer = NULL;
54   ops->nvsetarraypointer = NULL;
55   ops->nvgetcommunicator = NULL;
56   ops->nvgetlength       = NULL;
57 
58   /* standard vector operations */
59   ops->nvlinearsum    = NULL;
60   ops->nvconst        = NULL;
61   ops->nvprod         = NULL;
62   ops->nvdiv          = NULL;
63   ops->nvscale        = NULL;
64   ops->nvabs          = NULL;
65   ops->nvinv          = NULL;
66   ops->nvaddconst     = NULL;
67   ops->nvdotprod      = NULL;
68   ops->nvmaxnorm      = NULL;
69   ops->nvwrmsnormmask = NULL;
70   ops->nvwrmsnorm     = NULL;
71   ops->nvmin          = NULL;
72   ops->nvwl2norm      = NULL;
73   ops->nvl1norm       = NULL;
74   ops->nvcompare      = NULL;
75   ops->nvinvtest      = NULL;
76   ops->nvconstrmask   = NULL;
77   ops->nvminquotient  = NULL;
78 
79   /* fused vector operations (optional) */
80   ops->nvlinearcombination = NULL;
81   ops->nvscaleaddmulti     = NULL;
82   ops->nvdotprodmulti      = NULL;
83 
84   /* vector array operations (optional) */
85   ops->nvlinearsumvectorarray         = NULL;
86   ops->nvscalevectorarray             = NULL;
87   ops->nvconstvectorarray             = NULL;
88   ops->nvwrmsnormvectorarray          = NULL;
89   ops->nvwrmsnormmaskvectorarray      = NULL;
90   ops->nvscaleaddmultivectorarray     = NULL;
91   ops->nvlinearcombinationvectorarray = NULL;
92 
93   /* local reduction operations (optional) */
94   ops->nvdotprodlocal     = NULL;
95   ops->nvmaxnormlocal     = NULL;
96   ops->nvminlocal         = NULL;
97   ops->nvl1normlocal      = NULL;
98   ops->nvinvtestlocal     = NULL;
99   ops->nvconstrmasklocal  = NULL;
100   ops->nvminquotientlocal = NULL;
101   ops->nvwsqrsumlocal     = NULL;
102   ops->nvwsqrsummasklocal = NULL;
103 
104   /* debugging functions (called when SUNDIALS_DEBUG_PRINTVEC is defined) */
105   ops->nvprint     = NULL;
106   ops->nvprintfile = NULL;
107 
108   /* attach ops and initialize content to NULL */
109   v->ops     = ops;
110   v->content = NULL;
111 
112   return(v);
113 }
114 
115 
116 /* -----------------------------------------------------------------
117  * Free a generic N_Vector (assumes content is already empty)
118  * -----------------------------------------------------------------*/
119 
N_VFreeEmpty(N_Vector v)120 void N_VFreeEmpty(N_Vector v)
121 {
122   if (v == NULL)  return;
123 
124   /* free non-NULL ops structure */
125   if (v->ops)  free(v->ops);
126   v->ops = NULL;
127 
128   /* free overall N_Vector object and return */
129   free(v);
130   return;
131 }
132 
133 
134 /* -----------------------------------------------------------------
135  * Copy a vector 'ops' structure
136  * -----------------------------------------------------------------*/
137 
N_VCopyOps(N_Vector w,N_Vector v)138 int N_VCopyOps(N_Vector w, N_Vector v)
139 {
140   /* Check that ops structures exist */
141   if (w == NULL || v == NULL) return(-1);
142   if (w->ops == NULL || v->ops == NULL) return(-1);
143 
144   /* Copy ops from w to v */
145 
146   /* constructors, destructors, and utility operations */
147   v->ops->nvgetvectorid     = w->ops->nvgetvectorid;
148   v->ops->nvclone           = w->ops->nvclone;
149   v->ops->nvcloneempty      = w->ops->nvcloneempty;
150   v->ops->nvdestroy         = w->ops->nvdestroy;
151   v->ops->nvspace           = w->ops->nvspace;
152   v->ops->nvgetarraypointer = w->ops->nvgetarraypointer;
153   v->ops->nvsetarraypointer = w->ops->nvsetarraypointer;
154   v->ops->nvgetcommunicator = w->ops->nvgetcommunicator;
155   v->ops->nvgetlength       = w->ops->nvgetlength;
156 
157   /* standard vector operations */
158   v->ops->nvlinearsum    = w->ops->nvlinearsum;
159   v->ops->nvconst        = w->ops->nvconst;
160   v->ops->nvprod         = w->ops->nvprod;
161   v->ops->nvdiv          = w->ops->nvdiv;
162   v->ops->nvscale        = w->ops->nvscale;
163   v->ops->nvabs          = w->ops->nvabs;
164   v->ops->nvinv          = w->ops->nvinv;
165   v->ops->nvaddconst     = w->ops->nvaddconst;
166   v->ops->nvdotprod      = w->ops->nvdotprod;
167   v->ops->nvmaxnorm      = w->ops->nvmaxnorm;
168   v->ops->nvwrmsnormmask = w->ops->nvwrmsnormmask;
169   v->ops->nvwrmsnorm     = w->ops->nvwrmsnorm;
170   v->ops->nvmin          = w->ops->nvmin;
171   v->ops->nvwl2norm      = w->ops->nvwl2norm;
172   v->ops->nvl1norm       = w->ops->nvl1norm;
173   v->ops->nvcompare      = w->ops->nvcompare;
174   v->ops->nvinvtest      = w->ops->nvinvtest;
175   v->ops->nvconstrmask   = w->ops->nvconstrmask;
176   v->ops->nvminquotient  = w->ops->nvminquotient;
177 
178   /* fused vector operations */
179   v->ops->nvlinearcombination = w->ops->nvlinearcombination;
180   v->ops->nvscaleaddmulti     = w->ops->nvscaleaddmulti;
181   v->ops->nvdotprodmulti      = w->ops->nvdotprodmulti;
182 
183   /* vector array operations */
184   v->ops->nvlinearsumvectorarray         = w->ops->nvlinearsumvectorarray;
185   v->ops->nvscalevectorarray             = w->ops->nvscalevectorarray;
186   v->ops->nvconstvectorarray             = w->ops->nvconstvectorarray;
187   v->ops->nvwrmsnormvectorarray          = w->ops->nvwrmsnormvectorarray;
188   v->ops->nvwrmsnormmaskvectorarray      = w->ops->nvwrmsnormmaskvectorarray;
189   v->ops->nvscaleaddmultivectorarray     = w->ops->nvscaleaddmultivectorarray;
190   v->ops->nvlinearcombinationvectorarray = w->ops->nvlinearcombinationvectorarray;
191 
192   /* local reduction operations */
193   v->ops->nvdotprodlocal     = w->ops->nvdotprodlocal;
194   v->ops->nvmaxnormlocal     = w->ops->nvmaxnormlocal;
195   v->ops->nvminlocal         = w->ops->nvminlocal;
196   v->ops->nvl1normlocal      = w->ops->nvl1normlocal;
197   v->ops->nvinvtestlocal     = w->ops->nvinvtestlocal;
198   v->ops->nvconstrmasklocal  = w->ops->nvconstrmasklocal;
199   v->ops->nvminquotientlocal = w->ops->nvminquotientlocal;
200   v->ops->nvwsqrsumlocal     = w->ops->nvwsqrsumlocal;
201   v->ops->nvwsqrsummasklocal = w->ops->nvwsqrsummasklocal;
202 
203   /* debugging functions (called when SUNDIALS_DEBUG_PRINTVEC is defined) */
204   v->ops->nvprint     = w->ops->nvprint;
205   v->ops->nvprintfile = w->ops->nvprintfile;
206 
207   return(0);
208 }
209 
210 /* -----------------------------------------------------------------
211  * Functions in the 'ops' structure
212  * -----------------------------------------------------------------*/
213 
N_VGetVectorID(N_Vector w)214 N_Vector_ID N_VGetVectorID(N_Vector w)
215 {
216   return(w->ops->nvgetvectorid(w));
217 }
218 
N_VClone(N_Vector w)219 N_Vector N_VClone(N_Vector w)
220 {
221   return(w->ops->nvclone(w));
222 }
223 
N_VCloneEmpty(N_Vector w)224 N_Vector N_VCloneEmpty(N_Vector w)
225 {
226   return(w->ops->nvcloneempty(w));
227 }
228 
N_VDestroy(N_Vector v)229 void N_VDestroy(N_Vector v)
230 {
231   if (v == NULL) return;
232 
233   /* if the destroy operation exists use it */
234   if (v->ops)
235     if (v->ops->nvdestroy) { v->ops->nvdestroy(v); return; }
236 
237   /* if we reach this point, either ops == NULL or nvdestroy == NULL,
238      try to cleanup by freeing the content, ops, and vector */
239   if (v->content) { free(v->content); v->content = NULL; }
240   if (v->ops) { free(v->ops); v->ops = NULL; }
241   free(v); v = NULL;
242 
243   return;
244 }
245 
N_VSpace(N_Vector v,sunindextype * lrw,sunindextype * liw)246 void N_VSpace(N_Vector v, sunindextype *lrw, sunindextype *liw)
247 {
248   v->ops->nvspace(v, lrw, liw);
249   return;
250 }
251 
N_VGetArrayPointer(N_Vector v)252 realtype *N_VGetArrayPointer(N_Vector v)
253 {
254   return((realtype *) v->ops->nvgetarraypointer(v));
255 }
256 
N_VSetArrayPointer(realtype * v_data,N_Vector v)257 void N_VSetArrayPointer(realtype *v_data, N_Vector v)
258 {
259   v->ops->nvsetarraypointer(v_data, v);
260   return;
261 }
262 
N_VGetCommunicator(N_Vector v)263 void *N_VGetCommunicator(N_Vector v)
264 {
265   if (v->ops->nvgetcommunicator)
266     return(v->ops->nvgetcommunicator(v));
267   else
268     return(NULL);
269 }
270 
N_VGetLength(N_Vector v)271 sunindextype N_VGetLength(N_Vector v)
272 {
273   return((sunindextype) v->ops->nvgetlength(v));
274 }
275 
276 /* -----------------------------------------------------------------
277  * standard vector operations
278  * -----------------------------------------------------------------*/
279 
N_VLinearSum(realtype a,N_Vector x,realtype b,N_Vector y,N_Vector z)280 void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
281 {
282   z->ops->nvlinearsum(a, x, b, y, z);
283   return;
284 }
285 
N_VConst(realtype c,N_Vector z)286 void N_VConst(realtype c, N_Vector z)
287 {
288   z->ops->nvconst(c, z);
289   return;
290 }
291 
N_VProd(N_Vector x,N_Vector y,N_Vector z)292 void N_VProd(N_Vector x, N_Vector y, N_Vector z)
293 {
294   z->ops->nvprod(x, y, z);
295   return;
296 }
297 
N_VDiv(N_Vector x,N_Vector y,N_Vector z)298 void N_VDiv(N_Vector x, N_Vector y, N_Vector z)
299 {
300   z->ops->nvdiv(x, y, z);
301   return;
302 }
303 
N_VScale(realtype c,N_Vector x,N_Vector z)304 void N_VScale(realtype c, N_Vector x, N_Vector z)
305 {
306   z->ops->nvscale(c, x, z);
307   return;
308 }
309 
N_VAbs(N_Vector x,N_Vector z)310 void N_VAbs(N_Vector x, N_Vector z)
311 {
312   z->ops->nvabs(x, z);
313   return;
314 }
315 
N_VInv(N_Vector x,N_Vector z)316 void N_VInv(N_Vector x, N_Vector z)
317 {
318   z->ops->nvinv(x, z);
319   return;
320 }
321 
N_VAddConst(N_Vector x,realtype b,N_Vector z)322 void N_VAddConst(N_Vector x, realtype b, N_Vector z)
323 {
324   z->ops->nvaddconst(x, b, z);
325   return;
326 }
327 
N_VDotProd(N_Vector x,N_Vector y)328 realtype N_VDotProd(N_Vector x, N_Vector y)
329 {
330   return((realtype) y->ops->nvdotprod(x, y));
331 }
332 
N_VMaxNorm(N_Vector x)333 realtype N_VMaxNorm(N_Vector x)
334 {
335   return((realtype) x->ops->nvmaxnorm(x));
336 }
337 
N_VWrmsNorm(N_Vector x,N_Vector w)338 realtype N_VWrmsNorm(N_Vector x, N_Vector w)
339 {
340   return((realtype) x->ops->nvwrmsnorm(x, w));
341 }
342 
N_VWrmsNormMask(N_Vector x,N_Vector w,N_Vector id)343 realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id)
344 {
345   return((realtype) x->ops->nvwrmsnormmask(x, w, id));
346 }
347 
N_VMin(N_Vector x)348 realtype N_VMin(N_Vector x)
349 {
350   return((realtype) x->ops->nvmin(x));
351 }
352 
N_VWL2Norm(N_Vector x,N_Vector w)353 realtype N_VWL2Norm(N_Vector x, N_Vector w)
354 {
355   return((realtype) x->ops->nvwl2norm(x, w));
356 }
357 
N_VL1Norm(N_Vector x)358 realtype N_VL1Norm(N_Vector x)
359 {
360   return((realtype) x->ops->nvl1norm(x));
361 }
362 
N_VCompare(realtype c,N_Vector x,N_Vector z)363 void N_VCompare(realtype c, N_Vector x, N_Vector z)
364 {
365   z->ops->nvcompare(c, x, z);
366   return;
367 }
368 
N_VInvTest(N_Vector x,N_Vector z)369 booleantype N_VInvTest(N_Vector x, N_Vector z)
370 {
371   return((booleantype) z->ops->nvinvtest(x, z));
372 }
373 
N_VConstrMask(N_Vector c,N_Vector x,N_Vector m)374 booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m)
375 {
376   return((booleantype) x->ops->nvconstrmask(c, x, m));
377 }
378 
N_VMinQuotient(N_Vector num,N_Vector denom)379 realtype N_VMinQuotient(N_Vector num, N_Vector denom)
380 {
381   return((realtype) num->ops->nvminquotient(num, denom));
382 }
383 
384 /* -----------------------------------------------------------------
385  * OPTIONAL fused vector operations
386  * -----------------------------------------------------------------*/
387 
N_VLinearCombination(int nvec,realtype * c,N_Vector * X,N_Vector z)388 int N_VLinearCombination(int nvec, realtype* c, N_Vector* X, N_Vector z)
389 {
390   int i;
391   realtype ONE=RCONST(1.0);
392 
393   if (z->ops->nvlinearcombination != NULL) {
394 
395     return(z->ops->nvlinearcombination(nvec, c, X, z));
396 
397   } else {
398 
399     z->ops->nvscale(c[0], X[0], z);
400     for (i=1; i<nvec; i++) {
401       z->ops->nvlinearsum(c[i], X[i], ONE, z, z);
402     }
403     return(0);
404 
405   }
406 }
407 
N_VScaleAddMulti(int nvec,realtype * a,N_Vector x,N_Vector * Y,N_Vector * Z)408 int N_VScaleAddMulti(int nvec, realtype* a, N_Vector x, N_Vector* Y, N_Vector* Z)
409 {
410   int i;
411   realtype ONE=RCONST(1.0);
412 
413   if (x->ops->nvscaleaddmulti != NULL) {
414 
415     return(x->ops->nvscaleaddmulti(nvec, a, x, Y, Z));
416 
417   } else {
418 
419     for (i=0; i<nvec; i++) {
420       x->ops->nvlinearsum(a[i], x, ONE, Y[i], Z[i]);
421     }
422     return(0);
423 
424   }
425 }
426 
N_VDotProdMulti(int nvec,N_Vector x,N_Vector * Y,realtype * dotprods)427 int N_VDotProdMulti(int nvec, N_Vector x, N_Vector* Y, realtype* dotprods)
428 {
429   int i;
430 
431   if (x->ops->nvdotprodmulti != NULL) {
432 
433     return(x->ops->nvdotprodmulti(nvec, x, Y, dotprods));
434 
435   } else {
436 
437     for (i=0; i<nvec; i++) {
438       dotprods[i] = x->ops->nvdotprod(x, Y[i]);
439     }
440     return(0);
441 
442   }
443 }
444 
445 /* -----------------------------------------------------------------
446  * OPTIONAL vector array operations
447  * -----------------------------------------------------------------*/
448 
N_VLinearSumVectorArray(int nvec,realtype a,N_Vector * X,realtype b,N_Vector * Y,N_Vector * Z)449 int N_VLinearSumVectorArray(int nvec, realtype a, N_Vector* X,
450                             realtype b, N_Vector* Y, N_Vector* Z)
451 {
452   int i;
453 
454   if (Z[0]->ops->nvlinearsumvectorarray != NULL) {
455 
456     return(Z[0]->ops->nvlinearsumvectorarray(nvec, a, X, b, Y, Z));
457 
458   } else {
459 
460     for (i=0; i<nvec; i++) {
461       Z[0]->ops->nvlinearsum(a, X[i], b, Y[i], Z[i]);
462     }
463     return(0);
464 
465   }
466 }
467 
N_VScaleVectorArray(int nvec,realtype * c,N_Vector * X,N_Vector * Z)468 int N_VScaleVectorArray(int nvec, realtype* c, N_Vector* X, N_Vector* Z)
469 {
470   int i;
471 
472   if (Z[0]->ops->nvscalevectorarray != NULL) {
473 
474     return(Z[0]->ops->nvscalevectorarray(nvec, c, X, Z));
475 
476   } else {
477 
478     for (i=0; i<nvec; i++) {
479       Z[0]->ops->nvscale(c[i], X[i], Z[i]);
480     }
481     return(0);
482 
483   }
484 }
485 
N_VConstVectorArray(int nvec,realtype c,N_Vector * Z)486 int N_VConstVectorArray(int nvec, realtype c, N_Vector* Z)
487 {
488   int i, ier;
489 
490   if (Z[0]->ops->nvconstvectorarray != NULL) {
491 
492     ier = Z[0]->ops->nvconstvectorarray(nvec, c, Z);
493     return(ier);
494 
495   } else {
496 
497     for (i=0; i<nvec; i++) {
498       Z[0]->ops->nvconst(c, Z[i]);
499     }
500     return(0);
501 
502   }
503 }
504 
N_VWrmsNormVectorArray(int nvec,N_Vector * X,N_Vector * W,realtype * nrm)505 int N_VWrmsNormVectorArray(int nvec, N_Vector* X, N_Vector* W, realtype* nrm)
506 {
507   int i, ier;
508 
509   if (X[0]->ops->nvwrmsnormvectorarray != NULL) {
510 
511     ier = X[0]->ops->nvwrmsnormvectorarray(nvec, X, W, nrm);
512     return(ier);
513 
514   } else {
515 
516     for (i=0; i<nvec; i++) {
517       nrm[i] = X[0]->ops->nvwrmsnorm(X[i], W[i]);
518     }
519     return(0);
520 
521   }
522 }
523 
N_VWrmsNormMaskVectorArray(int nvec,N_Vector * X,N_Vector * W,N_Vector id,realtype * nrm)524 int N_VWrmsNormMaskVectorArray(int nvec, N_Vector* X, N_Vector* W, N_Vector id,
525                                realtype* nrm)
526 {
527   int i, ier;
528 
529   if (id->ops->nvwrmsnormmaskvectorarray != NULL) {
530 
531     ier = id->ops->nvwrmsnormmaskvectorarray(nvec, X, W, id, nrm);
532     return(ier);
533 
534   } else {
535 
536     for (i=0; i<nvec; i++) {
537       nrm[i] = id->ops->nvwrmsnormmask(X[i], W[i], id);
538     }
539     return(0);
540 
541   }
542 }
543 
N_VScaleAddMultiVectorArray(int nvec,int nsum,realtype * a,N_Vector * X,N_Vector ** Y,N_Vector ** Z)544 int N_VScaleAddMultiVectorArray(int nvec, int nsum, realtype* a, N_Vector* X,
545                                  N_Vector** Y, N_Vector** Z)
546 {
547   int        i, j;
548   int        ier=0;
549   realtype   ONE=RCONST(1.0);
550   N_Vector* YY=NULL;
551   N_Vector* ZZ=NULL;
552 
553   if (X[0]->ops->nvscaleaddmultivectorarray != NULL) {
554 
555     ier = X[0]->ops->nvscaleaddmultivectorarray(nvec, nsum, a, X, Y, Z);
556     return(ier);
557 
558   } else if (X[0]->ops->nvscaleaddmulti != NULL ) {
559 
560     /* allocate arrays of vectors */
561     YY = (N_Vector*) malloc(nsum * sizeof(N_Vector));
562     ZZ = (N_Vector*) malloc(nsum * sizeof(N_Vector));
563 
564     for (i=0; i<nvec; i++) {
565 
566       for (j=0; j<nsum; j++) {
567         YY[j] = Y[j][i];
568         ZZ[j] = Z[j][i];
569       }
570 
571       ier = X[0]->ops->nvscaleaddmulti(nsum, a, X[i], YY, ZZ);
572       if (ier != 0) break;
573     }
574 
575     /* free array of vectors */
576     free(YY);
577     free(ZZ);
578 
579     return(ier);
580 
581   } else {
582 
583     for (i=0; i<nvec; i++) {
584       for (j=0; j<nsum; j++) {
585         X[0]->ops->nvlinearsum(a[j], X[i], ONE, Y[j][i], Z[j][i]);
586       }
587     }
588     return(0);
589   }
590 }
591 
N_VLinearCombinationVectorArray(int nvec,int nsum,realtype * c,N_Vector ** X,N_Vector * Z)592 int N_VLinearCombinationVectorArray(int nvec, int nsum, realtype* c,
593                                     N_Vector** X, N_Vector* Z)
594 {
595   int        i, j;
596   int        ier=0;
597   realtype   ONE=RCONST(1.0);
598   N_Vector* Y=NULL;
599 
600   if (Z[0]->ops->nvlinearcombinationvectorarray != NULL) {
601 
602     ier = Z[0]->ops->nvlinearcombinationvectorarray(nvec, nsum, c, X, Z);
603     return(ier);
604 
605   } else if (Z[0]->ops->nvlinearcombination != NULL ) {
606 
607     /* allocate array of vectors */
608     Y = (N_Vector* ) malloc(nsum * sizeof(N_Vector));
609 
610     for (i=0; i<nvec; i++) {
611 
612       for (j=0; j<nsum; j++) {
613         Y[j] = X[j][i];
614       }
615 
616       ier = Z[0]->ops->nvlinearcombination(nsum, c, Y, Z[i]);
617       if (ier != 0) break;
618     }
619 
620     /* free array of vectors */
621     free(Y);
622 
623     return(ier);
624 
625   } else {
626 
627     for (i=0; i<nvec; i++) {
628       Z[0]->ops->nvscale(c[0], X[0][i], Z[i]);
629       for (j=1; j<nsum; j++) {
630         Z[0]->ops->nvlinearsum(c[j], X[j][i], ONE, Z[i], Z[i]);
631       }
632     }
633     return(0);
634   }
635 }
636 
637 /* -----------------------------------------------------------------
638  * OPTIONAL local reduction kernels (no parallel communication)
639  * -----------------------------------------------------------------*/
640 
N_VDotProdLocal(N_Vector x,N_Vector y)641 realtype N_VDotProdLocal(N_Vector x, N_Vector y)
642 {
643   return((realtype) y->ops->nvdotprodlocal(x, y));
644 }
645 
N_VMaxNormLocal(N_Vector x)646 realtype N_VMaxNormLocal(N_Vector x)
647 {
648   return((realtype) x->ops->nvmaxnormlocal(x));
649 }
650 
N_VMinLocal(N_Vector x)651 realtype N_VMinLocal(N_Vector x)
652 {
653   return((realtype) x->ops->nvminlocal(x));
654 }
655 
N_VL1NormLocal(N_Vector x)656 realtype N_VL1NormLocal(N_Vector x)
657 {
658   return((realtype) x->ops->nvl1normlocal(x));
659 }
660 
N_VWSqrSumLocal(N_Vector x,N_Vector w)661 realtype N_VWSqrSumLocal(N_Vector x, N_Vector w)
662 {
663   return((realtype) x->ops->nvwsqrsumlocal(x,w));
664 }
665 
N_VWSqrSumMaskLocal(N_Vector x,N_Vector w,N_Vector id)666 realtype N_VWSqrSumMaskLocal(N_Vector x, N_Vector w, N_Vector id)
667 {
668   return((realtype) x->ops->nvwsqrsummasklocal(x,w,id));
669 }
670 
N_VInvTestLocal(N_Vector x,N_Vector z)671 booleantype N_VInvTestLocal(N_Vector x, N_Vector z)
672 {
673   return((booleantype) z->ops->nvinvtestlocal(x,z));
674 }
675 
N_VConstrMaskLocal(N_Vector c,N_Vector x,N_Vector m)676 booleantype N_VConstrMaskLocal(N_Vector c, N_Vector x, N_Vector m)
677 {
678   return((booleantype) x->ops->nvconstrmasklocal(c,x,m));
679 }
680 
N_VMinQuotientLocal(N_Vector num,N_Vector denom)681 realtype N_VMinQuotientLocal(N_Vector num, N_Vector denom)
682 {
683   return((realtype) num->ops->nvminquotientlocal(num,denom));
684 }
685 
686 /* -----------------------------------------------------------------
687  * Additional functions exported by the generic NVECTOR:
688  *   N_VNewVectorArray
689  *   N_VCloneEmptyVectorArray
690  *   N_VCloneVectorArray
691  *   N_VDestroyVectorArray
692  * -----------------------------------------------------------------*/
N_VNewVectorArray(int count)693 N_Vector* N_VNewVectorArray(int count)
694 {
695   N_Vector* vs = NULL;
696 
697   if (count <= 0) return(NULL);
698 
699   vs = (N_Vector* ) malloc(count * sizeof(N_Vector));
700   if(vs == NULL) return(NULL);
701 
702   return(vs);
703 }
704 
N_VCloneEmptyVectorArray(int count,N_Vector w)705 N_Vector* N_VCloneEmptyVectorArray(int count, N_Vector w)
706 {
707   N_Vector* vs = NULL;
708   int j;
709 
710   if (count <= 0) return(NULL);
711 
712   vs = (N_Vector* ) malloc(count * sizeof(N_Vector));
713   if(vs == NULL) return(NULL);
714 
715   for (j = 0; j < count; j++) {
716     vs[j] = N_VCloneEmpty(w);
717     if (vs[j] == NULL) {
718       N_VDestroyVectorArray(vs, j-1);
719       return(NULL);
720     }
721   }
722 
723   return(vs);
724 }
725 
N_VCloneVectorArray(int count,N_Vector w)726 N_Vector* N_VCloneVectorArray(int count, N_Vector w)
727 {
728   N_Vector* vs = NULL;
729   int j;
730 
731   if (count <= 0) return(NULL);
732 
733   vs = (N_Vector* ) malloc(count * sizeof(N_Vector));
734   if(vs == NULL) return(NULL);
735 
736   for (j = 0; j < count; j++) {
737     vs[j] = N_VClone(w);
738     if (vs[j] == NULL) {
739       N_VDestroyVectorArray(vs, j-1);
740       return(NULL);
741     }
742   }
743 
744   return(vs);
745 }
746 
N_VDestroyVectorArray(N_Vector * vs,int count)747 void N_VDestroyVectorArray(N_Vector* vs, int count)
748 {
749   int j;
750 
751   if (vs==NULL) return;
752 
753   for (j = 0; j < count; j++) N_VDestroy(vs[j]);
754 
755   free(vs); vs = NULL;
756 
757   return;
758 }
759 
760 /* These function are really only for users of the Fortran interface */
N_VGetVecAtIndexVectorArray(N_Vector * vs,int index)761 N_Vector N_VGetVecAtIndexVectorArray(N_Vector* vs, int index)
762 {
763   if (vs==NULL)       return NULL;
764   else if (index < 0) return NULL;
765   else                return vs[index];
766 }
767 
N_VSetVecAtIndexVectorArray(N_Vector * vs,int index,N_Vector w)768 void N_VSetVecAtIndexVectorArray(N_Vector* vs, int index, N_Vector w)
769 {
770   if (vs==NULL)       return;
771   else if (index < 0) return;
772   else                vs[index] = w;
773 }
774 
775 
776 /* -----------------------------------------------------------------
777  * Debugging functions
778  * ----------------------------------------------------------------- */
779 
N_VPrint(N_Vector v)780 void N_VPrint(N_Vector v)
781 {
782   if (v == NULL) {
783     printf("NULL Vector\n");
784     return;
785   }
786   if (v->ops->nvprint == NULL) {
787     printf("NULL Print Op\n");
788     return;
789   }
790   v->ops->nvprint(v);
791   return;
792 }
793 
794 
N_VPrintFile(N_Vector v,FILE * outfile)795 void N_VPrintFile(N_Vector v, FILE* outfile)
796 {
797   if (v == NULL) {
798     fprintf(outfile, "NULL Vector\n");
799     return;
800   }
801   if (v->ops->nvprintfile == NULL) {
802     fprintf(outfile, "NULL PrintFile Op\n");
803     return;
804   }
805   v->ops->nvprintfile(v, outfile);
806   return;
807 }
808