1 /* -----------------------------------------------------------------
2  * Programmer(s): Radu Serban and Aaron Collier @ LLNL
3  * -----------------------------------------------------------------
4  * SUNDIALS Copyright Start
5  * Copyright (c) 2002-2019, Lawrence Livermore National Security
6  * and Southern Methodist University.
7  * All rights reserved.
8  *
9  * See the top-level LICENSE and NOTICE files for details.
10  *
11  * SPDX-License-Identifier: BSD-3-Clause
12  * SUNDIALS Copyright End
13  * -----------------------------------------------------------------
14  * This is the implementation file for a generic NVECTOR package.
15  * It contains the implementation of the N_Vector operations listed
16  * in nvector.h.
17  * -----------------------------------------------------------------*/
18 
19 #include <stdlib.h>
20 
21 #include <sundials/sundials_nvector.h>
22 
23 /*
24  * -----------------------------------------------------------------
25  * Functions in the 'ops' structure
26  * -----------------------------------------------------------------
27  */
28 
N_VGetVectorID(N_Vector w)29 N_Vector_ID N_VGetVectorID(N_Vector w)
30 {
31   N_Vector_ID id;
32   id = w->ops->nvgetvectorid(w);
33   return(id);
34 }
35 
N_VClone(N_Vector w)36 N_Vector N_VClone(N_Vector w)
37 {
38   N_Vector v = NULL;
39   v = w->ops->nvclone(w);
40   return(v);
41 }
42 
N_VCloneEmpty(N_Vector w)43 N_Vector N_VCloneEmpty(N_Vector w)
44 {
45   N_Vector v = NULL;
46   v = w->ops->nvcloneempty(w);
47   return(v);
48 }
49 
N_VDestroy(N_Vector v)50 void N_VDestroy(N_Vector v)
51 {
52   if (v==NULL) return;
53   v->ops->nvdestroy(v);
54   return;
55 }
56 
N_VSpace(N_Vector v,sunindextype * lrw,sunindextype * liw)57 void N_VSpace(N_Vector v, sunindextype *lrw, sunindextype *liw)
58 {
59   v->ops->nvspace(v, lrw, liw);
60   return;
61 }
62 
N_VGetArrayPointer(N_Vector v)63 realtype *N_VGetArrayPointer(N_Vector v)
64 {
65   return((realtype *) v->ops->nvgetarraypointer(v));
66 }
67 
N_VSetArrayPointer(realtype * v_data,N_Vector v)68 void N_VSetArrayPointer(realtype *v_data, N_Vector v)
69 {
70   v->ops->nvsetarraypointer(v_data, v);
71   return;
72 }
73 
74 /* -----------------------------------------------------------------
75  * standard vector operations
76  * ----------------------------------------------------------------- */
77 
N_VLinearSum(realtype a,N_Vector x,realtype b,N_Vector y,N_Vector z)78 void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
79 {
80   z->ops->nvlinearsum(a, x, b, y, z);
81   return;
82 }
83 
N_VConst(realtype c,N_Vector z)84 void N_VConst(realtype c, N_Vector z)
85 {
86   z->ops->nvconst(c, z);
87   return;
88 }
89 
N_VProd(N_Vector x,N_Vector y,N_Vector z)90 void N_VProd(N_Vector x, N_Vector y, N_Vector z)
91 {
92   z->ops->nvprod(x, y, z);
93   return;
94 }
95 
N_VDiv(N_Vector x,N_Vector y,N_Vector z)96 void N_VDiv(N_Vector x, N_Vector y, N_Vector z)
97 {
98   z->ops->nvdiv(x, y, z);
99   return;
100 }
101 
N_VScale(realtype c,N_Vector x,N_Vector z)102 void N_VScale(realtype c, N_Vector x, N_Vector z)
103 {
104   z->ops->nvscale(c, x, z);
105   return;
106 }
107 
N_VAbs(N_Vector x,N_Vector z)108 void N_VAbs(N_Vector x, N_Vector z)
109 {
110   z->ops->nvabs(x, z);
111   return;
112 }
113 
N_VInv(N_Vector x,N_Vector z)114 void N_VInv(N_Vector x, N_Vector z)
115 {
116   z->ops->nvinv(x, z);
117   return;
118 }
119 
N_VAddConst(N_Vector x,realtype b,N_Vector z)120 void N_VAddConst(N_Vector x, realtype b, N_Vector z)
121 {
122   z->ops->nvaddconst(x, b, z);
123   return;
124 }
125 
N_VDotProd(N_Vector x,N_Vector y)126 realtype N_VDotProd(N_Vector x, N_Vector y)
127 {
128   return((realtype) y->ops->nvdotprod(x, y));
129 }
130 
N_VMaxNorm(N_Vector x)131 realtype N_VMaxNorm(N_Vector x)
132 {
133   return((realtype) x->ops->nvmaxnorm(x));
134 }
135 
N_VWrmsNorm(N_Vector x,N_Vector w)136 realtype N_VWrmsNorm(N_Vector x, N_Vector w)
137 {
138   return((realtype) x->ops->nvwrmsnorm(x, w));
139 }
140 
N_VWrmsNormMask(N_Vector x,N_Vector w,N_Vector id)141 realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id)
142 {
143   return((realtype) x->ops->nvwrmsnormmask(x, w, id));
144 }
145 
N_VMin(N_Vector x)146 realtype N_VMin(N_Vector x)
147 {
148   return((realtype) x->ops->nvmin(x));
149 }
150 
N_VWL2Norm(N_Vector x,N_Vector w)151 realtype N_VWL2Norm(N_Vector x, N_Vector w)
152 {
153   return((realtype) x->ops->nvwl2norm(x, w));
154 }
155 
N_VL1Norm(N_Vector x)156 realtype N_VL1Norm(N_Vector x)
157 {
158   return((realtype) x->ops->nvl1norm(x));
159 }
160 
N_VCompare(realtype c,N_Vector x,N_Vector z)161 void N_VCompare(realtype c, N_Vector x, N_Vector z)
162 {
163   z->ops->nvcompare(c, x, z);
164   return;
165 }
166 
N_VInvTest(N_Vector x,N_Vector z)167 booleantype N_VInvTest(N_Vector x, N_Vector z)
168 {
169   return((booleantype) z->ops->nvinvtest(x, z));
170 }
171 
N_VConstrMask(N_Vector c,N_Vector x,N_Vector m)172 booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m)
173 {
174   return((booleantype) x->ops->nvconstrmask(c, x, m));
175 }
176 
N_VMinQuotient(N_Vector num,N_Vector denom)177 realtype N_VMinQuotient(N_Vector num, N_Vector denom)
178 {
179   return((realtype) num->ops->nvminquotient(num, denom));
180 }
181 
182 /* -----------------------------------------------------------------
183  * fused vector operations
184  * ----------------------------------------------------------------- */
185 
N_VLinearCombination(int nvec,realtype * c,N_Vector * X,N_Vector z)186 int N_VLinearCombination(int nvec, realtype* c, N_Vector* X, N_Vector z)
187 {
188   int i;
189   realtype ONE=RCONST(1.0);
190 
191   if (z->ops->nvlinearcombination != NULL) {
192 
193     return(z->ops->nvlinearcombination(nvec, c, X, z));
194 
195   } else {
196 
197     z->ops->nvscale(c[0], X[0], z);
198     for (i=1; i<nvec; i++) {
199       z->ops->nvlinearsum(c[i], X[i], ONE, z, z);
200     }
201     return(0);
202 
203   }
204 }
205 
N_VScaleAddMulti(int nvec,realtype * a,N_Vector x,N_Vector * Y,N_Vector * Z)206 int N_VScaleAddMulti(int nvec, realtype* a, N_Vector x, N_Vector* Y, N_Vector* Z)
207 {
208   int i;
209   realtype ONE=RCONST(1.0);
210 
211   if (x->ops->nvscaleaddmulti != NULL) {
212 
213     return(x->ops->nvscaleaddmulti(nvec, a, x, Y, Z));
214 
215   } else {
216 
217     for (i=0; i<nvec; i++) {
218       x->ops->nvlinearsum(a[i], x, ONE, Y[i], Z[i]);
219     }
220     return(0);
221 
222   }
223 }
224 
N_VDotProdMulti(int nvec,N_Vector x,N_Vector * Y,realtype * dotprods)225 int N_VDotProdMulti(int nvec, N_Vector x, N_Vector* Y, realtype* dotprods)
226 {
227   int i;
228 
229   if (x->ops->nvdotprodmulti != NULL) {
230 
231     return(x->ops->nvdotprodmulti(nvec, x, Y, dotprods));
232 
233   } else {
234 
235     for (i=0; i<nvec; i++) {
236       dotprods[i] = x->ops->nvdotprod(x, Y[i]);
237     }
238     return(0);
239 
240   }
241 }
242 
243 /* -----------------------------------------------------------------
244  * vector array operations
245  * ----------------------------------------------------------------- */
246 
N_VLinearSumVectorArray(int nvec,realtype a,N_Vector * X,realtype b,N_Vector * Y,N_Vector * Z)247 int N_VLinearSumVectorArray(int nvec, realtype a, N_Vector* X,
248                             realtype b, N_Vector* Y, N_Vector* Z)
249 {
250   int i;
251 
252   if (Z[0]->ops->nvlinearsumvectorarray != NULL) {
253 
254     return(Z[0]->ops->nvlinearsumvectorarray(nvec, a, X, b, Y, Z));
255 
256   } else {
257 
258     for (i=0; i<nvec; i++) {
259       Z[0]->ops->nvlinearsum(a, X[i], b, Y[i], Z[i]);
260     }
261     return(0);
262 
263   }
264 }
265 
N_VScaleVectorArray(int nvec,realtype * c,N_Vector * X,N_Vector * Z)266 int N_VScaleVectorArray(int nvec, realtype* c, N_Vector* X, N_Vector* Z)
267 {
268   int i;
269 
270   if (Z[0]->ops->nvscalevectorarray != NULL) {
271 
272     return(Z[0]->ops->nvscalevectorarray(nvec, c, X, Z));
273 
274   } else {
275 
276     for (i=0; i<nvec; i++) {
277       Z[0]->ops->nvscale(c[i], X[i], Z[i]);
278     }
279     return(0);
280 
281   }
282 }
283 
N_VConstVectorArray(int nvec,realtype c,N_Vector * Z)284 int N_VConstVectorArray(int nvec, realtype c, N_Vector* Z)
285 {
286   int i, ier;
287 
288   if (Z[0]->ops->nvconstvectorarray != NULL) {
289 
290     ier = Z[0]->ops->nvconstvectorarray(nvec, c, Z);
291     return(ier);
292 
293   } else {
294 
295     for (i=0; i<nvec; i++) {
296       Z[0]->ops->nvconst(c, Z[i]);
297     }
298     return(0);
299 
300   }
301 }
302 
N_VWrmsNormVectorArray(int nvec,N_Vector * X,N_Vector * W,realtype * nrm)303 int N_VWrmsNormVectorArray(int nvec, N_Vector* X, N_Vector* W, realtype* nrm)
304 {
305   int i, ier;
306 
307   if (X[0]->ops->nvwrmsnormvectorarray != NULL) {
308 
309     ier = X[0]->ops->nvwrmsnormvectorarray(nvec, X, W, nrm);
310     return(ier);
311 
312   } else {
313 
314     for (i=0; i<nvec; i++) {
315       nrm[i] = X[0]->ops->nvwrmsnorm(X[i], W[i]);
316     }
317     return(0);
318 
319   }
320 }
321 
N_VWrmsNormMaskVectorArray(int nvec,N_Vector * X,N_Vector * W,N_Vector id,realtype * nrm)322 int N_VWrmsNormMaskVectorArray(int nvec, N_Vector* X, N_Vector* W, N_Vector id,
323                                realtype* nrm)
324 {
325   int i, ier;
326 
327   if (id->ops->nvwrmsnormmaskvectorarray != NULL) {
328 
329     ier = id->ops->nvwrmsnormmaskvectorarray(nvec, X, W, id, nrm);
330     return(ier);
331 
332   } else {
333 
334     for (i=0; i<nvec; i++) {
335       nrm[i] = id->ops->nvwrmsnormmask(X[i], W[i], id);
336     }
337     return(0);
338 
339   }
340 }
341 
N_VScaleAddMultiVectorArray(int nvec,int nsum,realtype * a,N_Vector * X,N_Vector ** Y,N_Vector ** Z)342 int N_VScaleAddMultiVectorArray(int nvec, int nsum, realtype* a, N_Vector* X,
343                                  N_Vector** Y, N_Vector** Z)
344 {
345   int       i, j, ier;
346   realtype  ONE=RCONST(1.0);
347   N_Vector* YY=NULL;
348   N_Vector* ZZ=NULL;
349 
350   if (X[0]->ops->nvscaleaddmultivectorarray != NULL) {
351 
352     ier = X[0]->ops->nvscaleaddmultivectorarray(nvec, nsum, a, X, Y, Z);
353     return(ier);
354 
355   } else if (X[0]->ops->nvscaleaddmulti != NULL ) {
356 
357     /* allocate arrays of vectors */
358     YY = (N_Vector *) malloc(nsum * sizeof(N_Vector));
359     ZZ = (N_Vector *) malloc(nsum * sizeof(N_Vector));
360 
361     for (i=0; i<nvec; i++) {
362 
363       for (j=0; j<nsum; j++) {
364         YY[j] = Y[j][i];
365         ZZ[j] = Z[j][i];
366       }
367 
368       ier = X[0]->ops->nvscaleaddmulti(nsum, a, X[i], YY, ZZ);
369       if (ier != 0) break;
370     }
371 
372     /* free array of vectors */
373     free(YY);
374     free(ZZ);
375 
376     return(ier);
377 
378   } else {
379 
380     for (i=0; i<nvec; i++) {
381       for (j=0; j<nsum; j++) {
382         X[0]->ops->nvlinearsum(a[j], X[i], ONE, Y[j][i], Z[j][i]);
383       }
384     }
385     return(0);
386   }
387 }
388 
N_VLinearCombinationVectorArray(int nvec,int nsum,realtype * c,N_Vector ** X,N_Vector * Z)389 int N_VLinearCombinationVectorArray(int nvec, int nsum, realtype* c, N_Vector** X,
390                                     N_Vector* Z)
391 {
392   int       i, j, ier;
393   realtype  ONE=RCONST(1.0);
394   N_Vector* Y=NULL;
395 
396   if (Z[0]->ops->nvlinearcombinationvectorarray != NULL) {
397 
398     ier = Z[0]->ops->nvlinearcombinationvectorarray(nvec, nsum, c, X, Z);
399     return(ier);
400 
401   } else if (Z[0]->ops->nvlinearcombination != NULL ) {
402 
403     /* allocate array of vectors */
404     Y = (N_Vector *) malloc(nsum * sizeof(N_Vector));
405 
406     for (i=0; i<nvec; i++) {
407 
408       for (j=0; j<nsum; j++) {
409         Y[j] = X[j][i];
410       }
411 
412       ier = Z[0]->ops->nvlinearcombination(nsum, c, Y, Z[i]);
413       if (ier != 0) break;
414     }
415 
416     /* free array of vectors */
417     free(Y);
418 
419     return(ier);
420 
421   } else {
422 
423     for (i=0; i<nvec; i++) {
424       Z[0]->ops->nvscale(c[0], X[0][i], Z[i]);
425       for (j=1; j<nsum; j++) {
426         Z[0]->ops->nvlinearsum(c[j], X[j][i], ONE, Z[i], Z[i]);
427       }
428     }
429     return(0);
430   }
431 }
432 
433 /*
434  * -----------------------------------------------------------------
435  * Additional functions exported by the generic NVECTOR:
436  *   N_VCloneEmptyVectorArray
437  *   N_VCloneVectorArray
438  *   N_VDestroyVectorArray
439  * -----------------------------------------------------------------
440  */
441 
N_VCloneEmptyVectorArray(int count,N_Vector w)442 N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w)
443 {
444   N_Vector *vs = NULL;
445   int j;
446 
447   if (count <= 0) return(NULL);
448 
449   vs = (N_Vector *) malloc(count * sizeof(N_Vector));
450   if(vs == NULL) return(NULL);
451 
452   for (j = 0; j < count; j++) {
453     vs[j] = N_VCloneEmpty(w);
454     if (vs[j] == NULL) {
455       N_VDestroyVectorArray(vs, j-1);
456       return(NULL);
457     }
458   }
459 
460   return(vs);
461 }
462 
N_VCloneVectorArray(int count,N_Vector w)463 N_Vector *N_VCloneVectorArray(int count, N_Vector w)
464 {
465   N_Vector *vs = NULL;
466   int j;
467 
468   if (count <= 0) return(NULL);
469 
470   vs = (N_Vector *) malloc(count * sizeof(N_Vector));
471   if(vs == NULL) return(NULL);
472 
473   for (j = 0; j < count; j++) {
474     vs[j] = N_VClone(w);
475     if (vs[j] == NULL) {
476       N_VDestroyVectorArray(vs, j-1);
477       return(NULL);
478     }
479   }
480 
481   return(vs);
482 }
483 
N_VDestroyVectorArray(N_Vector * vs,int count)484 void N_VDestroyVectorArray(N_Vector *vs, int count)
485 {
486   int j;
487 
488   if (vs==NULL) return;
489 
490   for (j = 0; j < count; j++) N_VDestroy(vs[j]);
491 
492   free(vs); vs = NULL;
493 
494   return;
495 }
496