NEURON
nvector_nrnparallel_ld.cpp
Go to the documentation of this file.
1 /*
2  * -----------------------------------------------------------------
3  * $Revision: 855 $
4  * $Date: 2005-02-10 00:15:46 +0100 (Thu, 10 Feb 2005) $
5  * -----------------------------------------------------------------
6  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
7  * and Aaron Collier @ LLNL
8  * -----------------------------------------------------------------
9  * Copyright (c) 2002, The Regents of the University of California.
10  * Produced at the Lawrence Livermore National Laboratory.
11  * All rights reserved.
12  * For details, see sundials/shared/LICENSE.
13  * -----------------------------------------------------------------
14  * This is the implementation file for a parallel MPI implementation
15  * of the NVECTOR package.
16  * -----------------------------------------------------------------
17  */
18 
19 #define USELONGDOUBLE 1
20 
21 #include <../../nrnconf.h>
22 #include <hocassrt.h>
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 
27 /* for NRNMPI_DYNAMICLOAD */
28 #include <nrnmpiuse.h>
29 #if NRNMPI_DYNAMICLOAD
30 extern "C" void nrnmpi_dbl_allreduce_vec(double* src, double* dest, int cnt, int type);
31 extern "C" void nrnmpi_longdbl_allreduce_vec(long double* src, long double* dest, int cnt, int type);
32 extern "C" void nrnmpi_long_allreduce_vec(long* src, long* dest, int cnt, int type);
33 extern int nrnmpi_numprocs;
34 #endif
35 
36 #include "nvector_nrnparallel_ld.h"
37 #if NRNMPI_DYNAMICLOAD
38 #else
39 extern MPI_Comm nrnmpi_comm;
40 #endif
41 #include "sundialsmath.h"
42 #include "sundialstypes.h"
43 
44 #define ZERO RCONST(0.0)
45 #define HALF RCONST(0.5)
46 #define ONE RCONST(1.0)
47 #define ONEPT5 RCONST(1.5)
48 
49 #if USELONGDOUBLE
50 #define ldrealtype long double
51 #else
52 #define ldrealtype realtype
53 #endif
54 
55 
56 /* Error Message */
57 
58 #define BAD_N1 "N_VNew_NrnParallelLD -- Sum of local vector lengths differs from "
59 #define BAD_N2 "input global length. \n\n"
60 #define BAD_N BAD_N1 BAD_N2
61 
62 /* Private function prototypes */
63 
64 /* Reduction operations add/max/min over the processor group */
65 static realtype VAllReduce_NrnParallelLD(realtype d, int op, MPI_Comm comm);
66 #if USELONGDOUBLE
67 /* only for sum */
68 static ldrealtype VAllReduce_long_NrnParallelLD(ldrealtype d, int op, MPI_Comm comm);
69 #else
70 #define VAllReduce_long_NrnParallelLD VAllReduce_NrnParallelLD
71 #endif
72 /* z=x */
73 static void VCopy_NrnParallelLD(N_Vector x, N_Vector z);
74 /* z=x+y */
75 static void VSum_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z);
76 /* z=x-y */
77 static void VDiff_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z);
78 /* z=-x */
79 static void VNeg_NrnParallelLD(N_Vector x, N_Vector z);
80 /* z=c(x+y) */
81 static void VScaleSum_NrnParallelLD(realtype c, N_Vector x, N_Vector y, N_Vector z);
82 /* z=c(x-y) */
83 static void VScaleDiff_NrnParallelLD(realtype c, N_Vector x, N_Vector y, N_Vector z);
84 /* z=ax+y */
85 static void VLin1_NrnParallelLD(realtype a, N_Vector x, N_Vector y, N_Vector z);
86 /* z=ax-y */
87 static void VLin2_NrnParallelLD(realtype a, N_Vector x, N_Vector y, N_Vector z);
88 /* y <- ax+y */
89 static void Vaxpy_NrnParallelLD(realtype a, N_Vector x, N_Vector y);
90 /* x <- ax */
91 static void VScaleBy_NrnParallelLD(realtype a, N_Vector x);
92 
93 /*
94  * -----------------------------------------------------------------
95  * exported functions
96  * -----------------------------------------------------------------
97  */
98 
99 /* ----------------------------------------------------------------
100  * Function to create a new parallel vector with empty data array
101  */
102 
103 N_Vector N_VNewEmpty_NrnParallelLD(MPI_Comm comm,
104  long int local_length,
105  long int global_length)
106 {
107  N_Vector v;
108  N_Vector_Ops ops;
110  long int n, Nsum;
111 
112  /* Compute global length as sum of local lengths */
113  n = local_length;
114 #if NRNMPI_DYNAMICLOAD
115  nrnmpi_long_allreduce_vec(&n, &Nsum, 1, 1);
116 #else
117  comm = nrnmpi_comm;
118  MPI_Allreduce(&n, &Nsum, 1, PVEC_INTEGER_MPI_TYPE, MPI_SUM, comm);
119 #endif
120  if (Nsum != global_length) {
121  printf(BAD_N);
122  return(NULL);
123  }
124 
125  /* Create vector */
126  v = (N_Vector) malloc(sizeof *v);
127  if (v == NULL) return(NULL);
128 
129  /* Create vector operation structure */
130  ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops));
131  if (ops == NULL) { free(v); return(NULL); }
132 
133  ops->nvclone = N_VClone_NrnParallelLD;
134  ops->nvdestroy = N_VDestroy_NrnParallelLD;
135  ops->nvspace = N_VSpace_NrnParallelLD;
136  ops->nvgetarraypointer = N_VGetArrayPointer_NrnParallelLD;
137  ops->nvsetarraypointer = N_VSetArrayPointer_NrnParallelLD;
138  ops->nvlinearsum = N_VLinearSum_NrnParallelLD;
139  ops->nvconst = N_VConst_NrnParallelLD;
140  ops->nvprod = N_VProd_NrnParallelLD;
141  ops->nvdiv = N_VDiv_NrnParallelLD;
142  ops->nvscale = N_VScale_NrnParallelLD;
143  ops->nvabs = N_VAbs_NrnParallelLD;
144  ops->nvinv = N_VInv_NrnParallelLD;
145  ops->nvaddconst = N_VAddConst_NrnParallelLD;
146  ops->nvdotprod = N_VDotProd_NrnParallelLD;
147  ops->nvmaxnorm = N_VMaxNorm_NrnParallelLD;
148  ops->nvwrmsnormmask = N_VWrmsNormMask_NrnParallelLD;
149  ops->nvwrmsnorm = N_VWrmsNorm_NrnParallelLD;
150  ops->nvmin = N_VMin_NrnParallelLD;
151  ops->nvwl2norm = N_VWL2Norm_NrnParallelLD;
152  ops->nvl1norm = N_VL1Norm_NrnParallelLD;
153  ops->nvcompare = N_VCompare_NrnParallelLD;
154  ops->nvinvtest = N_VInvTest_NrnParallelLD;
155  ops->nvconstrmask = N_VConstrMask_NrnParallelLD;
156  ops->nvminquotient = N_VMinQuotient_NrnParallelLD;
157 
158  /* Create content */
159  content = (N_VectorContent_NrnParallelLD) malloc(sizeof(struct _N_VectorContent_NrnParallelLD));
160  if (content == NULL) { free(ops); free(v); return(NULL); }
161 
162  /* Attach lengths and communicator */
163  content->local_length = local_length;
164  content->global_length = global_length;
165  content->comm = comm;
166  content->own_data = FALSE;
167  content->data = NULL;
168 
169  /* Attach content and ops */
170  v->content = content;
171  v->ops = ops;
172 
173  return(v);
174 }
175 
176 /* ----------------------------------------------------------------
177  * Function to create a new parallel vector
178  */
179 
180 extern "C" N_Vector N_VNew_NrnParallelLD(MPI_Comm comm,
181  long int local_length,
182  long int global_length)
183 {
184  N_Vector v;
185  realtype *data;
186 
187  v = N_VNewEmpty_NrnParallelLD(comm, local_length, global_length);
188  if (v == NULL) return(NULL);
189 
190  /* Create data */
191  if(local_length > 0) {
192 
193  /* Allocate memory */
194  data = (realtype *) malloc(local_length * sizeof(realtype));
195  if(data == NULL) {N_VDestroy_NrnParallelLD(v);return(NULL);}
196 
197  /* Attach data */
198  NV_OWN_DATA_P_LD(v) = TRUE;
199  NV_DATA_P_LD(v) = data;
200 
201  }
202 
203  return(v);
204 }
205 
206 /* ----------------------------------------------------------------------------
207  * Function to clone from a template a new vector with empty (NULL) data array
208  */
209 
210 N_Vector N_VCloneEmpty_NrnParallelLD(N_Vector w)
211 {
212  N_Vector v;
213  N_Vector_Ops ops;
215 
216  if (w == NULL) return(NULL);
217 
218  /* Create vector */
219  v = (N_Vector) malloc(sizeof *v);
220  if (v == NULL) return(NULL);
221 
222  /* Create vector operation structure */
223  ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops));
224  if (ops == NULL) { free(v); return(NULL); }
225 
226  ops->nvclone = w->ops->nvclone;
227  ops->nvdestroy = w->ops->nvdestroy;
228  ops->nvspace = w->ops->nvspace;
229  ops->nvgetarraypointer = w->ops->nvgetarraypointer;
230  ops->nvsetarraypointer = w->ops->nvsetarraypointer;
231  ops->nvlinearsum = w->ops->nvlinearsum;
232  ops->nvconst = w->ops->nvconst;
233  ops->nvprod = w->ops->nvprod;
234  ops->nvdiv = w->ops->nvdiv;
235  ops->nvscale = w->ops->nvscale;
236  ops->nvabs = w->ops->nvabs;
237  ops->nvinv = w->ops->nvinv;
238  ops->nvaddconst = w->ops->nvaddconst;
239  ops->nvdotprod = w->ops->nvdotprod;
240  ops->nvmaxnorm = w->ops->nvmaxnorm;
241  ops->nvwrmsnormmask = w->ops->nvwrmsnormmask;
242  ops->nvwrmsnorm = w->ops->nvwrmsnorm;
243  ops->nvmin = w->ops->nvmin;
244  ops->nvwl2norm = w->ops->nvwl2norm;
245  ops->nvl1norm = w->ops->nvl1norm;
246  ops->nvcompare = w->ops->nvcompare;
247  ops->nvinvtest = w->ops->nvinvtest;
248  ops->nvconstrmask = w->ops->nvconstrmask;
249  ops->nvminquotient = w->ops->nvminquotient;
250 
251  /* Create content */
252  content = (N_VectorContent_NrnParallelLD) malloc(sizeof(struct _N_VectorContent_NrnParallelLD));
253  if (content == NULL) { free(ops); free(v); return(NULL); }
254 
255  /* Attach lengths and communicator */
256  content->local_length = NV_LOCLENGTH_P_LD(w);
257  content->global_length = NV_GLOBLENGTH_P_LD(w);
258  content->comm = NV_COMM_P_LD(w);
259  content->own_data = FALSE;
260  content->data = NULL;
261 
262  /* Attach content and ops */
263  v->content = content;
264  v->ops = ops;
265 
266  return(v);
267 }
268 
269 /* ----------------------------------------------------------------
270  * Function to create a parallel N_Vector with user data component
271  */
272 
273 N_Vector N_VMake_NrnParallelLD(MPI_Comm comm,
274  long int local_length,
275  long int global_length,
276  realtype *v_data)
277 {
278  N_Vector v;
279 
280  v = N_VNewEmpty_NrnParallelLD(comm, local_length, global_length);
281  if (v == NULL) return(NULL);
282 
283  if (local_length > 0) {
284  /* Attach data */
285  NV_OWN_DATA_P_LD(v) = FALSE;
286  NV_DATA_P_LD(v) = v_data;
287  }
288 
289  return(v);
290 }
291 
292 /* ----------------------------------------------------------------
293  * Function to create an array of new parallel vectors.
294  */
295 
296 N_Vector *N_VNewVectorArray_NrnParallelLD(int count,
297  MPI_Comm comm,
298  long int local_length,
299  long int global_length)
300 {
301  N_Vector *vs;
302  int j;
303 
304  if (count <= 0) return(NULL);
305 
306  vs = (N_Vector *) malloc(count * sizeof(N_Vector));
307  if(vs == NULL) return(NULL);
308 
309  for (j=0; j<count; j++) {
310  vs[j] = N_VNew_NrnParallelLD(comm, local_length, global_length);
311  if (vs[j] == NULL) {
313  return(NULL);
314  }
315  }
316 
317  return(vs);
318 }
319 
320 /* ----------------------------------------------------------------
321  * Function to create an array of new parallel vectors with empty
322  * (NULL) data array.
323  */
324 
326  MPI_Comm comm,
327  long int local_length,
328  long int global_length)
329 {
330  N_Vector *vs;
331  int j;
332 
333  if (count <= 0) return(NULL);
334 
335  vs = (N_Vector *) malloc(count * sizeof(N_Vector));
336  if(vs == NULL) return(NULL);
337 
338  for (j=0; j<count; j++) {
339  vs[j] = N_VNewEmpty_NrnParallelLD(comm, local_length, global_length);
340  if (vs[j] == NULL) {
342  return(NULL);
343  }
344  }
345 
346  return(vs);
347 }
348 
349 /* ----------------------------------------------------------------
350  * Function to free an array created with N_VNewVectorArray_NrnParallelLD
351  */
352 
353 void N_VDestroyVectorArray_NrnParallelLD(N_Vector *vs, int count)
354 {
355  int j;
356 
357  for (j = 0; j < count; j++) N_VDestroy_NrnParallelLD(vs[j]);
358 
359  free(vs);
360 }
361 
362 /* ----------------------------------------------------------------
363  * Function to print a parallel vector
364  */
365 
366 void N_VPrint_NrnParallelLD(N_Vector x)
367 {
368  long int i, N;
369  realtype *xd;
370 
371  N = NV_LOCLENGTH_P_LD(x);
372  xd = NV_DATA_P_LD(x);
373 
374  for (i=0; i < N; i++) {
375 #if defined(SUNDIALS_EXTENDED_PRECISION)
376  printf("%Lg\n", *xd++);
377 #elif defined(SUNDIALS_DOUBLE_PRECISION)
378  printf("%lg\n", *xd++);
379 #else
380  printf("%g\n", *xd++);
381 #endif
382  }
383  printf("\n");
384 }
385 
386 /*
387  * -----------------------------------------------------------------
388  * implementation of vector operations
389  * -----------------------------------------------------------------
390  */
391 
392 N_Vector N_VClone_NrnParallelLD(N_Vector w)
393 {
394  N_Vector v;
395  realtype *data;
396  long int local_length;
397 
399  if (v == NULL) return(NULL);
400 
401  local_length = NV_LOCLENGTH_P_LD(w);
402 
403  /* Create data */
404  if(local_length > 0) {
405 
406  /* Allocate memory */
407  data = (realtype *) malloc(local_length * sizeof(realtype));
408  if(data == NULL) {N_VDestroy_NrnParallelLD(v);return(NULL);}
409 
410  /* Attach data */
411  NV_OWN_DATA_P_LD(v) = TRUE;
412  NV_DATA_P_LD(v) = data;
413  }
414 
415  return(v);
416 }
417 
419 {
420  if ( (NV_OWN_DATA_P_LD(v) == TRUE) && (NV_DATA_P_LD(v) != NULL) )
421  free(NV_DATA_P_LD(v));
422  free(v->content);
423  free(v->ops);
424  free(v);
425 }
426 
427 void N_VSpace_NrnParallelLD(N_Vector v, long int *lrw, long int *liw)
428 {
429  MPI_Comm comm;
430  int npes;
431 
432  comm = NV_COMM_P_LD(v);
433 #if NRNMPI_DYNAMICLOAD
434  npes = nrnmpi_numprocs;
435 #else
436  MPI_Comm_size(comm, &npes);
437 #endif
438 
439  *lrw = NV_GLOBLENGTH_P_LD(v);
440  *liw = 2 * npes;
441 }
442 
444 {
445  realtype *v_data;
446 
447  v_data = NV_DATA_P_LD(v);
448 
449  return(v_data);
450 }
451 
452 void N_VSetArrayPointer_NrnParallelLD(realtype *v_data, N_Vector v)
453 {
454  if (NV_LOCLENGTH_P_LD(v) > 0) NV_DATA_P_LD(v) = v_data;
455 }
456 
457 void N_VLinearSum_NrnParallelLD(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
458 {
459  long int i, N;
460  realtype c, *xd, *yd, *zd;
461  N_Vector v1, v2;
462  booleantype test;
463 
464  if ((b == ONE) && (z == y)) { /* BLAS usage: axpy y <- ax+y */
465  Vaxpy_NrnParallelLD(a,x,y);
466  return;
467  }
468 
469  if ((a == ONE) && (z == x)) { /* BLAS usage: axpy x <- by+x */
470  Vaxpy_NrnParallelLD(b,y,x);
471  return;
472  }
473 
474  /* Case: a == b == 1.0 */
475 
476  if ((a == ONE) && (b == ONE)) {
477  VSum_NrnParallelLD(x, y, z);
478  return;
479  }
480 
481  /* Cases: (1) a == 1.0, b = -1.0, (2) a == -1.0, b == 1.0 */
482 
483  if ((test = ((a == ONE) && (b == -ONE))) || ((a == -ONE) && (b == ONE))) {
484  v1 = test ? y : x;
485  v2 = test ? x : y;
486  VDiff_NrnParallelLD(v2, v1, z);
487  return;
488  }
489 
490  /* Cases: (1) a == 1.0, b == other or 0.0, (2) a == other or 0.0, b == 1.0 */
491  /* if a or b is 0.0, then user should have called N_VScale */
492 
493  if ((test = (a == ONE)) || (b == ONE)) {
494  c = test ? b : a;
495  v1 = test ? y : x;
496  v2 = test ? x : y;
497  VLin1_NrnParallelLD(c, v1, v2, z);
498  return;
499  }
500 
501  /* Cases: (1) a == -1.0, b != 1.0, (2) a != 1.0, b == -1.0 */
502 
503  if ((test = (a == -ONE)) || (b == -ONE)) {
504  c = test ? b : a;
505  v1 = test ? y : x;
506  v2 = test ? x : y;
507  VLin2_NrnParallelLD(c, v1, v2, z);
508  return;
509  }
510 
511  /* Case: a == b */
512  /* catches case both a and b are 0.0 - user should have called N_VConst */
513 
514  if (a == b) {
515  VScaleSum_NrnParallelLD(a, x, y, z);
516  return;
517  }
518 
519  /* Case: a == -b */
520 
521  if (a == -b) {
522  VScaleDiff_NrnParallelLD(a, x, y, z);
523  return;
524  }
525 
526  /* Do all cases not handled above:
527  (1) a == other, b == 0.0 - user should have called N_VScale
528  (2) a == 0.0, b == other - user should have called N_VScale
529  (3) a,b == other, a !=b, a != -b */
530 
531  N = NV_LOCLENGTH_P_LD(x);
532  xd = NV_DATA_P_LD(x);
533  yd = NV_DATA_P_LD(y);
534  zd = NV_DATA_P_LD(z);
535 
536  for (i=0; i < N; i++)
537  *zd++ = a * (*xd++) + b * (*yd++);
538 }
539 
540 void N_VConst_NrnParallelLD(realtype c, N_Vector z)
541 {
542  long int i, N;
543  realtype *zd;
544 
545  N = NV_LOCLENGTH_P_LD(z);
546  zd = NV_DATA_P_LD(z);
547 
548  for (i=0; i < N; i++)
549  *zd++ = c;
550 }
551 
552 void N_VProd_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z)
553 {
554  long int i, N;
555  realtype *xd, *yd, *zd;
556 
557  N = NV_LOCLENGTH_P_LD(x);
558  xd = NV_DATA_P_LD(x);
559  yd = NV_DATA_P_LD(y);
560  zd = NV_DATA_P_LD(z);
561 
562  for (i=0; i < N; i++)
563  *zd++ = (*xd++) * (*yd++);
564 }
565 
566 void N_VDiv_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z)
567 {
568  long int i, N;
569  realtype *xd, *yd, *zd;
570 
571  N = NV_LOCLENGTH_P_LD(x);
572  xd = NV_DATA_P_LD(x);
573  yd = NV_DATA_P_LD(y);
574  zd = NV_DATA_P_LD(z);
575 
576  for (i=0; i < N; i++)
577  *zd++ = (*xd++) / (*yd++);
578 }
579 
580 void N_VScale_NrnParallelLD(realtype c, N_Vector x, N_Vector z)
581 {
582  long int i, N;
583  realtype *xd, *zd;
584 
585  if (z == x) { /* BLAS usage: scale x <- cx */
587  return;
588  }
589 
590  if (c == ONE) {
591  VCopy_NrnParallelLD(x, z);
592  } else if (c == -ONE) {
593  VNeg_NrnParallelLD(x, z);
594  } else {
595  N = NV_LOCLENGTH_P_LD(x);
596  xd = NV_DATA_P_LD(x);
597  zd = NV_DATA_P_LD(z);
598  for (i=0; i < N; i++)
599  *zd++ = c * (*xd++);
600  }
601 }
602 
603 void N_VAbs_NrnParallelLD(N_Vector x, N_Vector z)
604 {
605  long int i, N;
606  realtype *xd, *zd;
607 
608  N = NV_LOCLENGTH_P_LD(x);
609  xd = NV_DATA_P_LD(x);
610  zd = NV_DATA_P_LD(z);
611 
612  for (i=0; i < N; i++, xd++, zd++)
613  *zd = ABS(*xd);
614 }
615 
616 void N_VInv_NrnParallelLD(N_Vector x, N_Vector z)
617 {
618  long int i, N;
619  realtype *xd, *zd;
620 
621  N = NV_LOCLENGTH_P_LD(x);
622  xd = NV_DATA_P_LD(x);
623  zd = NV_DATA_P_LD(z);
624 
625  for (i=0; i < N; i++)
626  *zd++ = ONE / (*xd++);
627 }
628 
629 void N_VAddConst_NrnParallelLD(N_Vector x, realtype b, N_Vector z)
630 {
631  long int i, N;
632  realtype *xd, *zd;
633 
634  N = NV_LOCLENGTH_P_LD(x);
635  xd = NV_DATA_P_LD(x);
636  zd = NV_DATA_P_LD(z);
637 
638  for (i=0; i < N; i++) *zd++ = (*xd++) + b;
639 }
640 
641 realtype N_VDotProd_NrnParallelLD(N_Vector x, N_Vector y)
642 {
643  long int i, N;
644  realtype sum = ZERO, *xd, *yd, gsum;
645  MPI_Comm comm;
646 
647  N = NV_LOCLENGTH_P_LD(x);
648  xd = NV_DATA_P_LD(x);
649  yd = NV_DATA_P_LD(y);
650  comm = NV_COMM_P_LD(x);
651 
652  for (i=0; i < N; i++) sum += xd[i] * yd[i];
653 
654  gsum = VAllReduce_long_NrnParallelLD(sum, 1, comm);
655  return(gsum);
656 }
657 
658 realtype N_VMaxNorm_NrnParallelLD(N_Vector x)
659 {
660  long int i, N;
661  realtype max, *xd, gmax;
662  MPI_Comm comm;
663 
664  N = NV_LOCLENGTH_P_LD(x);
665  xd = NV_DATA_P_LD(x);
666  comm = NV_COMM_P_LD(x);
667 
668  max = ZERO;
669 
670  for (i=0; i < N; i++, xd++) {
671  if (ABS(*xd) > max) max = ABS(*xd);
672  }
673 
674  gmax = VAllReduce_NrnParallelLD(max, 2, comm);
675  return(gmax);
676 }
677 
678 realtype N_VWrmsNorm_NrnParallelLD(N_Vector x, N_Vector w)
679 {
680  long int i, N, N_global;
681  realtype prodi, *xd, *wd;
682  ldrealtype sum = ZERO, gsum;
683  MPI_Comm comm;
684 
685  N = NV_LOCLENGTH_P_LD(x);
686  N_global = NV_GLOBLENGTH_P_LD(x);
687  xd = NV_DATA_P_LD(x);
688  wd = NV_DATA_P_LD(w);
689  comm = NV_COMM_P_LD(x);
690 
691  for (i=0; i < N; i++) {
692  prodi = (*xd++) * (*wd++);
693  sum += prodi * prodi;
694  }
695 
696  gsum = VAllReduce_long_NrnParallelLD(sum, 1, comm);
697  return(RSqrt((realtype)gsum / N_global));
698 }
699 
700 realtype N_VWrmsNormMask_NrnParallelLD(N_Vector x, N_Vector w, N_Vector id)
701 {
702  long int i, N, N_global;
703  realtype prodi, *xd, *wd, *idd;
704  ldrealtype sum = ZERO, gsum;
705  MPI_Comm comm;
706 
707  N = NV_LOCLENGTH_P_LD(x);
708  N_global = NV_GLOBLENGTH_P_LD(x);
709  xd = NV_DATA_P_LD(x);
710  wd = NV_DATA_P_LD(w);
711  idd = NV_DATA_P_LD(id);
712  comm = NV_COMM_P_LD(x);
713 
714  for (i=0; i < N; i++) {
715  if (idd[i] > ZERO) {
716  prodi = xd[i] * wd[i];
717  sum += prodi * prodi;
718  }
719  }
720 
721  gsum = VAllReduce_long_NrnParallelLD(sum, 1, comm);
722  return(RSqrt((realtype)gsum / N_global));
723 }
724 
725 realtype N_VMin_NrnParallelLD(N_Vector x)
726 {
727  long int i, N;
728  realtype min, *xd, gmin;
729  MPI_Comm comm;
730 
731  N = NV_LOCLENGTH_P_LD(x);
732  comm = NV_COMM_P_LD(x);
733 
734  min = BIG_REAL;
735 
736  if (N > 0) {
737 
738  xd = NV_DATA_P_LD(x);
739 
740  min = xd[0];
741 
742  xd++;
743  for (i=1; i < N; i++, xd++) {
744  if ((*xd) < min) min = *xd;
745  }
746 
747  }
748 
749  gmin = VAllReduce_NrnParallelLD(min, 3, comm);
750  return(gmin);
751 }
752 
753 realtype N_VWL2Norm_NrnParallelLD(N_Vector x, N_Vector w)
754 {
755  long int i, N;
756  realtype prodi, *xd, *wd;
757  ldrealtype sum = ZERO, gsum;
758  MPI_Comm comm;
759 
760  N = NV_LOCLENGTH_P_LD(x);
761  xd = NV_DATA_P_LD(x);
762  wd = NV_DATA_P_LD(w);
763  comm = NV_COMM_P_LD(x);
764 
765  for (i=0; i < N; i++) {
766  prodi = (*xd++) * (*wd++);
767  sum += prodi * prodi;
768  }
769 
770  gsum = VAllReduce_long_NrnParallelLD(sum, 1, comm);
771  return(RSqrt((realtype)gsum));
772 }
773 
774 realtype N_VL1Norm_NrnParallelLD(N_Vector x)
775 {
776  long int i, N;
777  realtype *xd;
778  ldrealtype sum = ZERO, gsum;
779  MPI_Comm comm;
780 
781  N = NV_LOCLENGTH_P_LD(x);
782  xd = NV_DATA_P_LD(x);
783  comm = NV_COMM_P_LD(x);
784 
785  for (i=0; i<N; i++,xd++)
786  sum += ABS(*xd);
787 
788  gsum = VAllReduce_long_NrnParallelLD((realtype)sum, 1, comm);
789  return(gsum);
790 }
791 
792 void N_VCompare_NrnParallelLD(realtype c, N_Vector x, N_Vector z)
793 {
794  long int i, N;
795  realtype *xd, *zd;
796 
797  N = NV_LOCLENGTH_P_LD(x);
798  xd = NV_DATA_P_LD(x);
799  zd = NV_DATA_P_LD(z);
800 
801  for (i=0; i < N; i++, xd++, zd++) {
802  *zd = (ABS(*xd) >= c) ? ONE : ZERO;
803  }
804 }
805 
806 booleantype N_VInvTest_NrnParallelLD(N_Vector x, N_Vector z)
807 {
808  long int i, N;
809  realtype *xd, *zd, val, gval;
810  MPI_Comm comm;
811 
812  N = NV_LOCLENGTH_P_LD(x);
813  xd = NV_DATA_P_LD(x);
814  zd = NV_DATA_P_LD(z);
815  comm = NV_COMM_P_LD(x);
816 
817  val = ONE;
818  for (i=0; i < N; i++) {
819  if (*xd == ZERO)
820  val = ZERO;
821  else
822  *zd++ = ONE / (*xd++);
823  }
824 
825  gval = VAllReduce_NrnParallelLD(val, 3, comm);
826  if (gval == ZERO)
827  return(FALSE);
828  else
829  return(TRUE);
830 }
831 
832 booleantype N_VConstrMask_NrnParallelLD(N_Vector c, N_Vector x, N_Vector m)
833 {
834  long int i, N;
835  booleantype test;
836  realtype *cd, *xd, *md;
837  MPI_Comm comm;
838 
839  N = NV_LOCLENGTH_P_LD(x);
840  xd = NV_DATA_P_LD(x);
841  cd = NV_DATA_P_LD(c);
842  md = NV_DATA_P_LD(m);
843  comm = NV_COMM_P_LD(x);
844 
845  test = TRUE;
846 
847  for (i=0; i<N; i++, cd++, xd++, md++) {
848  *md = ZERO;
849  if (*cd == ZERO) continue;
850  if (*cd > ONEPT5 || (*cd) < -ONEPT5) {
851  if ( (*xd)*(*cd) <= ZERO) {test = FALSE; *md = ONE; }
852  continue;
853  }
854  if ( (*cd) > HALF || (*cd) < -HALF) {
855  if ( (*xd)*(*cd) < ZERO ) {test = FALSE; *md = ONE; }
856  }
857  }
858 
859  return((booleantype)VAllReduce_long_NrnParallelLD((realtype)test, 3, comm));
860 }
861 
862 realtype N_VMinQuotient_NrnParallelLD(N_Vector num, N_Vector denom)
863 {
864  booleantype notEvenOnce;
865  long int i, N;
866  realtype *nd, *dd, min=0.0;
867  MPI_Comm comm;
868 
869  N = NV_LOCLENGTH_P_LD(num);
870  nd = NV_DATA_P_LD(num);
871  dd = NV_DATA_P_LD(denom);
872  comm = NV_COMM_P_LD(num);
873 
874  notEvenOnce = TRUE;
875 
876  for (i = 0; i < N; i++, nd++, dd++) {
877  if (*dd == ZERO) continue;
878  else {
879  if (notEvenOnce) {
880  min = *nd / *dd ;
881  notEvenOnce = FALSE;
882  }
883  else min = MIN(min, (*nd) / (*dd));
884  }
885  }
886 
887  if (notEvenOnce || (N == 0)) min = BIG_REAL;
888 
889  return(VAllReduce_NrnParallelLD(min, 3, comm));
890 }
891 
892 /*
893  * -----------------------------------------------------------------
894  * private functions
895  * -----------------------------------------------------------------
896  */
897 
898 static realtype VAllReduce_NrnParallelLD(realtype d, int op, MPI_Comm comm)
899 {
900  /*
901  * This function does a global reduction. The operation is
902  * sum if op = 1,
903  * max if op = 2,
904  * min if op = 3.
905  * The operation is over all processors in the communicator
906  */
907 
908  realtype out;
909 
910 #if NRNMPI_DYNAMICLOAD
911  nrnmpi_dbl_allreduce_vec(&d, &out, 1, op);
912 #else
913  switch (op) {
914  case 1: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_SUM, comm);
915  break;
916 
917  case 2: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_MAX, comm);
918  break;
919 
920  case 3: MPI_Allreduce(&d, &out, 1, PVEC_REAL_MPI_TYPE, MPI_MIN, comm);
921  break;
922 
923  default: break;
924  }
925 #endif
926 
927  return(out);
928 }
929 
930 #if USELONGDOUBLE
931 static ldrealtype VAllReduce_long_NrnParallelLD(ldrealtype d, int op, MPI_Comm comm)
932 {
933  /*
934  * This function does a global reduction. The operation is
935  * sum if op = 1,
936  * max if op = 2,
937  * min if op = 3.
938  * The operation is over all processors in the communicator
939  */
940 
941  ldrealtype out;
942 
943  assert(op == 1);
944 #if NRNMPI_DYNAMICLOAD
945  nrnmpi_longdbl_allreduce_vec(&d, &out, 1, op);
946 #else
947  MPI_Allreduce(&d, &out, 1, MPI_LONG_DOUBLE, MPI_SUM, comm);
948 #endif
949 
950  return(out);
951 }
952 #endif
953 
954 static void VCopy_NrnParallelLD(N_Vector x, N_Vector z)
955 {
956  long int i, N;
957  realtype *xd, *zd;
958 
959  N = NV_LOCLENGTH_P_LD(x);
960  xd = NV_DATA_P_LD(x);
961  zd = NV_DATA_P_LD(z);
962 
963  for (i=0; i < N; i++)
964  *zd++ = *xd++;
965 }
966 
967 static void VSum_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z)
968 {
969  long int i, N;
970  realtype *xd, *yd, *zd;
971 
972  N = NV_LOCLENGTH_P_LD(x);
973  xd = NV_DATA_P_LD(x);
974  yd = NV_DATA_P_LD(y);
975  zd = NV_DATA_P_LD(z);
976 
977  for (i=0; i < N; i++)
978  *zd++ = (*xd++) + (*yd++);
979 }
980 
981 static void VDiff_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z)
982 {
983  long int i, N;
984  realtype *xd, *yd, *zd;
985 
986  N = NV_LOCLENGTH_P_LD(x);
987  xd = NV_DATA_P_LD(x);
988  yd = NV_DATA_P_LD(y);
989  zd = NV_DATA_P_LD(z);
990 
991  for (i=0; i < N; i++)
992  *zd++ = (*xd++) - (*yd++);
993 }
994 
995 static void VNeg_NrnParallelLD(N_Vector x, N_Vector z)
996 {
997  long int i, N;
998  realtype *xd, *zd;
999 
1000  N = NV_LOCLENGTH_P_LD(x);
1001  xd = NV_DATA_P_LD(x);
1002  zd = NV_DATA_P_LD(z);
1003 
1004  for (i=0; i < N; i++)
1005  *zd++ = -(*xd++);
1006 }
1007 
1008 static void VScaleSum_NrnParallelLD(realtype c, N_Vector x, N_Vector y, N_Vector z)
1009 {
1010  long int i, N;
1011  realtype *xd, *yd, *zd;
1012 
1013  N = NV_LOCLENGTH_P_LD(x);
1014  xd = NV_DATA_P_LD(x);
1015  yd = NV_DATA_P_LD(y);
1016  zd = NV_DATA_P_LD(z);
1017 
1018  for (i=0; i < N; i++)
1019  *zd++ = c * ((*xd++) + (*yd++));
1020 }
1021 
1022 static void VScaleDiff_NrnParallelLD(realtype c, N_Vector x, N_Vector y, N_Vector z)
1023 {
1024  long int i, N;
1025  realtype *xd, *yd, *zd;
1026 
1027  N = NV_LOCLENGTH_P_LD(x);
1028  xd = NV_DATA_P_LD(x);
1029  yd = NV_DATA_P_LD(y);
1030  zd = NV_DATA_P_LD(z);
1031 
1032  for (i=0; i < N; i++)
1033  *zd++ = c * ((*xd++) - (*yd++));
1034 }
1035 
1036 static void VLin1_NrnParallelLD(realtype a, N_Vector x, N_Vector y, N_Vector z)
1037 {
1038  long int i, N;
1039  realtype *xd, *yd, *zd;
1040 
1041  N = NV_LOCLENGTH_P_LD(x);
1042  xd = NV_DATA_P_LD(x);
1043  yd = NV_DATA_P_LD(y);
1044  zd = NV_DATA_P_LD(z);
1045 
1046  for (i=0; i < N; i++)
1047  *zd++ = a * (*xd++) + (*yd++);
1048 }
1049 
1050 static void VLin2_NrnParallelLD(realtype a, N_Vector x, N_Vector y, N_Vector z)
1051 {
1052  long int i, N;
1053  realtype *xd, *yd, *zd;
1054 
1055  N = NV_LOCLENGTH_P_LD(x);
1056  xd = NV_DATA_P_LD(x);
1057  yd = NV_DATA_P_LD(y);
1058  zd = NV_DATA_P_LD(z);
1059 
1060  for (i=0; i < N; i++)
1061  *zd++ = a * (*xd++) - (*yd++);
1062 }
1063 
1064 static void Vaxpy_NrnParallelLD(realtype a, N_Vector x, N_Vector y)
1065 {
1066  long int i, N;
1067  realtype *xd, *yd;
1068 
1069  N = NV_LOCLENGTH_P_LD(x);
1070  xd = NV_DATA_P_LD(x);
1071  yd = NV_DATA_P_LD(y);
1072 
1073  if (a == ONE) {
1074  for (i=0; i < N; i++)
1075  *yd++ += (*xd++);
1076  return;
1077  }
1078 
1079  if (a == -ONE) {
1080  for (i=0; i < N; i++)
1081  *yd++ -= (*xd++);
1082  return;
1083  }
1084 
1085  for (i=0; i < N; i++)
1086  *yd++ += a * (*xd++);
1087 }
1088 
1089 static void VScaleBy_NrnParallelLD(realtype a, N_Vector x)
1090 {
1091  long int i, N;
1092  realtype *xd;
1093 
1094  N = NV_LOCLENGTH_P_LD(x);
1095  xd = NV_DATA_P_LD(x);
1096 
1097  for (i=0; i < N; i++)
1098  *xd++ *= a;
1099 }
#define data
Definition: rbtqueue.cpp:49
void N_VAbs_NrnParallelLD(N_Vector x, N_Vector z)
static ldrealtype VAllReduce_long_NrnParallelLD(ldrealtype d, int op, MPI_Comm comm)
void N_VDiv_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z)
double max(double a, double b)
Definition: geometry3d.cpp:22
#define assert(ex)
Definition: hocassrt.h:26
short type
Definition: cabvars.h:10
N_Vector N_VMake_NrnParallelLD(MPI_Comm comm, long int local_length, long int global_length, realtype *v_data)
static void VScaleBy_NrnParallelLD(realtype a, N_Vector x)
void N_VDestroyVectorArray_NrnParallelLD(N_Vector *vs, int count)
void N_VCompare_NrnParallelLD(realtype c, N_Vector x, N_Vector z)
N_Vector N_VNewEmpty_NrnParallelLD(MPI_Comm comm, long int local_length, long int global_length)
void N_VPrint_NrnParallelLD(N_Vector x)
#define min(a, b)
Definition: matrix.h:157
realtype N_VMaxNorm_NrnParallelLD(N_Vector x)
#define TRUE
Definition: err.c:57
MPI_Comm nrnmpi_comm
void N_VProd_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z)
nd
Definition: treeset.cpp:893
realtype N_VL1Norm_NrnParallelLD(N_Vector x)
#define v
Definition: md1redef.h:4
void N_VScale_NrnParallelLD(realtype c, N_Vector x, N_Vector z)
void N_VAddConst_NrnParallelLD(N_Vector x, realtype b, N_Vector z)
N_Vector N_VClone_NrnParallelLD(N_Vector w)
void N_VSetArrayPointer_NrnParallelLD(realtype *v_data, N_Vector v)
realtype N_VWrmsNormMask_NrnParallelLD(N_Vector x, N_Vector w, N_Vector id)
realtype N_VWL2Norm_NrnParallelLD(N_Vector x, N_Vector w)
booleantype N_VInvTest_NrnParallelLD(N_Vector x, N_Vector z)
#define ABS(x)
Definition: extras.c:201
#define BAD_N
void N_VLinearSum_NrnParallelLD(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
void N_VInv_NrnParallelLD(N_Vector x, N_Vector z)
#define ZERO
static realtype VAllReduce_NrnParallelLD(realtype d, int op, MPI_Comm comm)
#define PVEC_INTEGER_MPI_TYPE
#define ONEPT5
struct _N_VectorContent_NrnParallelLD * N_VectorContent_NrnParallelLD
static void Vaxpy_NrnParallelLD(realtype a, N_Vector x, N_Vector y)
int const size_t const size_t n
Definition: nrngsl.h:12
static void VScaleDiff_NrnParallelLD(realtype c, N_Vector x, N_Vector y, N_Vector z)
N_Vector * N_VNewVectorArrayEmpty_NrnParallelLD(int count, MPI_Comm comm, long int local_length, long int global_length)
int nrnmpi_numprocs
int val
Definition: dll.cpp:167
N_Vector N_VCloneEmpty_NrnParallelLD(N_Vector w)
#define printf
Definition: mwprefix.h:26
static void VCopy_NrnParallelLD(N_Vector x, N_Vector z)
static void VLin2_NrnParallelLD(realtype a, N_Vector x, N_Vector y, N_Vector z)
#define cnt
Definition: spt2queue.cpp:19
void N_VConst_NrnParallelLD(realtype c, N_Vector z)
size_t j
static void VNeg_NrnParallelLD(N_Vector x, N_Vector z)
#define MIN(a, b)
Definition: grids.h:32
static void VScaleSum_NrnParallelLD(realtype c, N_Vector x, N_Vector y, N_Vector z)
static void VLin1_NrnParallelLD(realtype a, N_Vector x, N_Vector y, N_Vector z)
void N_VDestroy_NrnParallelLD(N_Vector v)
#define NV_OWN_DATA_P_LD(v)
#define FALSE
Definition: err.c:56
#define i
Definition: md1redef.h:12
#define NV_LOCLENGTH_P_LD(v)
#define c
realtype N_VMin_NrnParallelLD(N_Vector x)
#define HALF
void N_VSpace_NrnParallelLD(N_Vector v, long int *lrw, long int *liw)
booleantype N_VConstrMask_NrnParallelLD(N_Vector c, N_Vector x, N_Vector m)
#define ONE
N_Vector N_VNew_NrnParallelLD(MPI_Comm comm, long int local_length, long int global_length)
#define ldrealtype
#define NV_COMM_P_LD(v)
#define NV_DATA_P_LD(v)
static void VSum_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z)
#define NV_GLOBLENGTH_P_LD(v)
realtype * N_VGetArrayPointer_NrnParallelLD(N_Vector v)
N_Vector * N_VNewVectorArray_NrnParallelLD(int count, MPI_Comm comm, long int local_length, long int global_length)
return NULL
Definition: cabcode.cpp:461
static void VDiff_NrnParallelLD(N_Vector x, N_Vector y, N_Vector z)
realtype N_VDotProd_NrnParallelLD(N_Vector x, N_Vector y)
realtype N_VWrmsNorm_NrnParallelLD(N_Vector x, N_Vector w)
realtype N_VMinQuotient_NrnParallelLD(N_Vector num, N_Vector denom)