SpM Handbook 1.2.4
Loading...
Searching...
No Matches
z_spm_laplacian.c
Go to the documentation of this file.
1/**
2 * @file z_spm_laplacian.c
3 *
4 * SParse Matrix package laplacian generator routines.
5 *
6 * @copyright 2016-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
7 * Univ. Bordeaux. All rights reserved.
8 *
9 * @version 1.2.4
10 * @author Mathieu Faverge
11 * @author Tony Delarue
12 * @author Gregoire Pichon
13 * @author Alycia Lisito
14 * @date 2024-06-25
15 * @generated from /builds/2mk6rsew/0/fpruvost/spm/src/z_spm_laplacian.c, normal z -> z, Fri Nov 29 11:34:31 2024
16 *
17 **/
18#include "common.h"
19#include "drivers/laplacian.h"
20
21/**
22 *******************************************************************************
23 *
24 * @ingroup spm_dev_driver
25 *
26 * @def laplacian_add_one_edge( _colptr_, _rowptr_, _valptr_, _dest_, _value_ )
27 * @brief Add an edge to the spm matrix
28 *
29 *******************************************************************************
30 *
31 * @param[inout] \_colptr\_
32 * Increment the colptr by 1.
33 *
34 * @param[inout] \_rowptr\_
35 * Store the edge value and shift to the next array element
36 *
37 * @param[inout] \_valptr\_
38 * Store the edge value and shift to the next array element
39 *
40 * @param[in] \_dest\_
41 * The destination of the edge
42 *
43 * @param[in] \_value\_
44 * The value of the edge
45 *
46 *******************************************************************************/
47#if defined(PRECISION_p)
48#define laplacian_add_one_edge( _colptr_, _rowptr_, _valptr_, _dest_, _value_ ) \
49 { \
50 *(_rowptr_) = _dest_; \
51 (_rowptr_)++; \
52 (_colptr_)[1]++; \
53 }
54#else
55#define laplacian_add_one_edge( _colptr_, _rowptr_, _valptr_, _dest_, _value_ ) \
56 { \
57 *(_rowptr_) = _dest_; \
58 *(_valptr_) = _value_; \
59 (_rowptr_)++; \
60 (_valptr_)++; \
61 (_colptr_)[1]++; \
62 }
63#endif
64
65/**
66 *******************************************************************************
67 *
68 * @ingroup spm_dev_driver
69 *
70 * @brief Add three edges of the 27 pts stencil. the direct one, and its two
71 * diagonal neighboor ones.
72 *
73 *******************************************************************************
74 *
75 * @param[inout] \_colptr\_
76 * Increment the colptr by 1.
77 *
78 * @param[inout] \_rowptr\_
79 * Store the edge value and shift to the next array element
80 *
81 * @param[inout] \_valptr\_
82 * Store the edge value and shift to the next array element
83 *
84 * @param[in] \_dest\_
85 * The center destination of the three edges
86 *
87 * @param[in] \_fcond\_
88 * The condition to add the first diagonal
89 *
90 * @param[in] \_lcond\_
91 * The condition to add the last diagonal
92 *
93 * @param[in] \_valone\_
94 * The value on the central edge
95 *
96 * @param[in] \_valtwo\_
97 * The value on the diagonal edges
98 *
99 *******************************************************************************/
100#define laplacian_add_three_edges( _colptr_, _rowptr_, _valptr_, _dest_, _fcond_, _lcond_, _valone_, _valtwo_ ) \
101 { \
102 if ( _fcond_ ) \
103 { \
104 laplacian_add_one_edge( (_colptr_), (_rowptr_), (_valptr_), (_dest_) - 1, (_valtwo_) ); \
105 } \
106 laplacian_add_one_edge( (_colptr_), (_rowptr_), (_valptr_), (_dest_), (_valone_) ); \
107 if ( _lcond_ ) \
108 { \
109 laplacian_add_one_edge( (_colptr_), (_rowptr_), (_valptr_), (_dest_) + 1, (_valtwo_) ); \
110 } \
111 }
112
113
114/**
115 *******************************************************************************
116 *
117 * @ingroup spm_dev_driver
118 *
119 * @brief Return the number of edges in a laplacian of size MxNxK
120 *
121 *******************************************************************************
122 *
123 * @param[in] M
124 * The main dimension (the one split among the processes if any)
125 *
126 * @param[in] N
127 * The second dimension (Not split)
128 *
129 * @param[in] K
130 * The third dimension (Not split)
131 *
132 * @param[in] level
133 * The level of the edges to add
134 * - 0: No edges but the diagonal elements
135 * - 1: 0 + The edges along the squares if the stencil
136 * - 2: 1 + The edges on the diagonals of the squares
137 * - 3: 2 + The edges on the diagonals of the cubes
138 *
139 * @param[in] connexion
140 * If connexion is true, the edges to connect to another domain along
141 * the first dimension (M) are added to the computation.
142 * If false, nothing is added.
143 *
144 *******************************************************************************
145 *
146 * @return The number of edges in the final symmetric graph
147 *
148 *******************************************************************************/
149static inline spm_int_t
151 spm_int_t N,
152 spm_int_t K,
153 int level,
154 int connexion )
155{
156 spm_int_t nnz;
157
158 /*
159 * Let's compute the number of nnz for a M x N x K stencil
160 */
161 nnz = M * N * K; /* Diagonal elements */
162
163 /* No element in the matrix, so no edges */
164 if ( nnz == 0 ) {
165 return 0;
166 }
167
168 /* Beta edges - Sides of the squares */
169 if ( level > 0 ) {
170 nnz += (M - 1) * N * K;
171 nnz += (N - 1) * M * K;
172 nnz += (K - 1) * M * N;
173 }
174
175 /* Gamma edges - Diagonal of the squares */
176 if ( level > 1 ) {
177 nnz += 2 * M * (N - 1) * (K - 1);
178 nnz += 2 * N * (M - 1) * (K - 1);
179 nnz += 2 * K * (M - 1) * (N - 1);
180 }
181
182 /* Delta edges - Diagonal of the cubes */
183 if ( level > 2 ) {
184 nnz += 4 * (M - 1) * (N - 1) * (K - 1);
185 }
186
187 /* Connexion layer between nodes */
188 if ( connexion ) {
189 /* Missing beta edges */
190 if ( level > 0 ) {
191 nnz += N * K;
192 }
193
194 /* Missing gamma edges */
195 if ( level > 1 ) {
196 nnz += 2 * N * (K - 1);
197 nnz += 2 * K * (N - 1);
198 }
199
200 /* Missing delta edges */
201 if ( level > 2 ) {
202 nnz += 4 * (N - 1) * (K - 1);
203 }
204 }
205 return nnz;
206}
207
208/**
209 *******************************************************************************
210 *
211 * @ingroup spm_dev_driver
212 *
213 * @brief Generate a laplacian matrix for a 3D 7-points stencil.
214 *
215 * The generated laplacian matrix is \f[ M = \alpha * D - \beta * A \f] with
216 * D the doagonal matrix of the degrees and A the adjacency matrix with
217 * coefficients of 1. for each connexion.
218 *
219 * *-------*-------*
220 * /| /| /|
221 * *-------B-------* |
222 * /| | /| | /| |
223 * *-------*-|-----* | |
224 * | | *---|-|-B---|-|-*
225 * | |/| | |/ | |/|
226 * | B-----|-A-----|-B |
227 * |/| | |/| |/| |
228 * *-------B-------* | |
229 * | | *---|-|-*---|-|-*
230 * | |/ | |/ | |/
231 * | *-----|-B-----|-*
232 * |/ |/ |/
233 * *-------*-------*
234 *
235 * Each element A is only connected to its neigbours B in the stencil.
236 *
237 * Example:
238 * > 3 -1 -1 0 -1 0 0 0
239 * > -1 3 0 -1 0 -1 0 0
240 * > -1 0 3 -1 0 0 -1 0
241 * > 0 -1 -1 3 0 0 0 -1
242 * > -1 0 0 0 3 -1 -1 0
243 * > 0 -1 0 0 -1 3 0 -1
244 * > 0 0 -1 0 -1 0 3 -1
245 * > 0 0 0 -1 0 -1 -1 3
246 *
247 * @remark: In complex, the Laplacian is set to hermitian. See
248 * z_spmLaplacian_27points() to get a symmetric Laplacian, or change the
249 * mtxtype field by hand.
250 *
251 *******************************************************************************
252 *
253 * @param[inout] spm
254 * At start, an allocated spm structure.
255 * Contains the size of the laplacian in spm->n.
256 * At exit, contains the matrix in csc format.
257 *
258 * @param[in] dim1
259 * contains the first dimension of the grid of the laplacian.
260 *
261 * @param[in] dim2
262 * contains the second dimension of the grid of the laplacian.
263 *
264 * @param[in] dim3
265 * contains the third dimension of the grid of the laplacian.
266 *
267 * @param[in] alpha
268 * The alpha coefficient for the degree matrix
269 *
270 * @param[in] beta
271 * The beta coefficient for the adjacency matrix
272 *
273 *******************************************************************************/
274void
276 spm_int_t dim1,
277 spm_int_t dim2,
278 spm_int_t dim3,
279 spm_fixdbl_t alpha,
280 spm_fixdbl_t beta )
281{
282#if !defined(PRECISION_p)
283 spm_complex64_t *valptr;
284 spm_complex64_t lalpha = (spm_complex64_t)alpha;
285 spm_complex64_t lbeta = (spm_complex64_t)beta;
286#endif
287 spm_int_t *colptr, *rowptr;
288 spm_int_t i, j, k, l, degree = 0;
289 spm_int_t ldim1, fk, lk;
290 int level = 1; /* To store only the square side of the stencil */
291
292 spm->mtxtype = SpmHermitian;
293 spm->flttype = SpmComplex64;
294 spm->fmttype = SpmCSC;
295 spm->baseval = 0;
296 spm->dof = 1;
297 spm->gnnz = z_spmLaplacian_getnnz( dim1, dim2, dim3, level, 0 );
298 assert( spm->gN == dim1 * dim2 * dim3 );
299
300 /* Let's split along first dimension */
301 ldim1 = dim1 / spm->clustnbr;
302 fk = ldim1 * spm->clustnum + spm_imin( spm->clustnum, dim1 % spm->clustnbr );
303 lk = ldim1 * (spm->clustnum+1) + spm_imin( spm->clustnum+1, dim1 % spm->clustnbr );
304 ldim1 = lk - fk;
305
306 /* Let's compute the local number of nnz */
307 spm->replicated = (spm->clustnbr == 1); /* Set to 0 if multiple node, 1 otherwise */
308 spm->n = ldim1 * dim2 * dim3;
309 spm->nnz = z_spmLaplacian_getnnz( ldim1, dim2, dim3, level, lk < dim1 );
310 /* if ( spm->n == 0 ) { */
311 /* if ( spm->clustnbr > 1 ) { */
312 /* /\* Fake malloc to make it part of the collective comunications *\/ */
313 /* spm->loc2glob = malloc(sizeof(int)); */
314 /* } */
315 /* return; */
316 /* } */
317
318 /* Allocating */
319 spm->colptr = malloc((spm->n+1)*sizeof(spm_int_t));
320 spm->rowptr = malloc(spm->nnz *sizeof(spm_int_t));
321 assert( spm->colptr );
322 assert( spm->rowptr );
323
324#if !defined(PRECISION_p)
325 spm->values = malloc(spm->nnz *sizeof(spm_complex64_t));
326 assert( spm->values );
327 valptr = (spm_complex64_t*)(spm->values);
328#endif
329
330 /* Building ia, ja and values*/
331 colptr = spm->colptr;
332 rowptr = spm->rowptr;
333
334 /* Building ia, ja and values*/
335 *colptr = 0;
336
337 /* Start with one for each dimension (top corner) */
338 degree = 3;
339 for(i=0; i<dim3; i++)
340 {
341 int di = 0;
342
343 /* +1 after the first layer */
344 if ( i > 0 ) {
345 di++;
346 }
347 /* -1 on the last layer */
348 if ( i < (dim3-1) ) {
349 di++;
350 }
351
352 for(j=0; j<dim2; j++)
353 {
354 int dj = 0;
355
356 /* +1 after the first layer */
357 if ( j > 0 ) {
358 dj++;
359 }
360 /* -1 on the last layer */
361 if ( j < (dim2-1) ) {
362 dj++;
363 }
364
365 /* Column index in the matrix (i * dim1 * dim2 + j * dim1 + k) */
366 l = i * dim1 * dim2 + j * dim1 + fk;
367 for(k=fk; k<lk; k++)
368 {
369
370 int dk = 0;
371 /* +1 after the first layer */
372 if ( k > 0 ) {
373 dk++;
374 }
375 /* -1 on the last layer */
376 if ( k < (dim1-1) ) {
377 dk++;
378 }
379 degree = di + dj + dk;
380
381 colptr[1] = colptr[0];
382
383 /* Diagonal value */
384 laplacian_add_one_edge( colptr, rowptr, valptr,
385 l, (spm_complex64_t)degree * lalpha );
386
387 /* Connexion along dimension 1 */
388 if (k < (dim1-1)) {
389 laplacian_add_one_edge( colptr, rowptr, valptr,
390 l + 1, lbeta );
391 }
392
393 /* Connexion along dimension 2 */
394 if (j < (dim2-1)) {
395 laplacian_add_one_edge( colptr, rowptr, valptr,
396 l + dim1, lbeta );
397 }
398
399 /* Connexion along dimension 3 */
400 if ( i < (dim3 - 1) ) {
401 laplacian_add_one_edge( colptr, rowptr, valptr,
402 l + dim1 * dim2, lbeta );
403 }
404
405 colptr++;
406 l++;
407 }
408
409 /* Reduce the degree to make sure it's ok on all nodes */
410 if ( k == (dim1-1) ) {
411 degree--;
412 }
413 }
414 }
415
416 assert( (spm->colptr[ spm->n ] - spm->colptr[0]) == spm->nnz );
417
418 /* Initialize the loc2glob array */
419 if ( (spm->clustnbr > 1) && (spm->n > 0) ) {
420 spm_int_t *loc2glob;
421 spm->loc2glob = malloc( spm->n * sizeof(spm_int_t) );
422
423 loc2glob = spm->loc2glob;
424 for(i=0; i<dim3; i++) {
425 for(j=0; j<dim2; j++) {
426 l = i * dim1 * dim2 + j * dim1 + fk;
427 for(k=fk; k<lk; k++, l++, loc2glob++ ) {
428 *loc2glob = l;
429 }
430 }
431 }
432 }
433
434 (void)alpha;
435 (void)beta;
436 (void)degree;
437}
438
439/**
440 *******************************************************************************
441 *
442 * @ingroup spm_dev_driver
443 *
444 * @brief Generate an extended laplacian matrix for a 3D 27-points stencil
445 *
446 * The generated laplacian is a the matrix \f[ M = \alpha * D - \beta * A \f],
447 * where D is the matrix of degrees, and A the matrix of adjacency.
448 * In the exemple below for each vertex A, the value of the connexions in the
449 * adjacency matrix are:
450 * - 1 for the connexions with the B vertices
451 * - 1 / sqrt(2) for the connexions with the X vertices (face diagonal)
452 * - 1 / sqrt(3) for the connexions with the D vertices (cube diagonal)
453 *
454 * D-------X-------D
455 * /| /| /|
456 * X-------B-------X |
457 * /| | /| | /| |
458 * D-------X-|-----D | |
459 * | | X---|-|-B---|-|-X
460 * | |/| | |/ | |/|
461 * | B-----|-A-----|-B |
462 * |/| | |/| |/| |
463 * X-------B-------X | |
464 * | | D---|-|-X---|-|-D
465 * | |/ | |/ | |/
466 * | X-----|-B-----|-X
467 * |/ |/ |/
468 * D-------X-------D
469 *
470 * @remark: In complex, the Laplacian is set to symmetric. See
471 * z_spmLaplacian_7points() to get an hermitian Laplacian, or change the
472 * mtxtype field by hand.
473 *
474 *******************************************************************************
475 *
476 * @param[inout] spm
477 * At start, an allocated spm structure.
478 * Contains the size of the laplacian in spm->n.
479 * At exit, contains the matrix in csc format.
480 *
481 * @param[in] dim1
482 * contains the first dimension of the grid of the laplacian.
483 *
484 * @param[in] dim2
485 * contains the second dimension of the grid of the laplacian.
486 *
487 * @param[in] dim3
488 * contains the third dimension of the grid of the laplacian.
489 *
490 * @param[in] alpha
491 * The alpha coefficient for the degree matrix
492 *
493 * @param[in] beta
494 * The beta coefficient for the adjacency matrix
495 *
496 *******************************************************************************/
497void
499 spm_int_t dim1,
500 spm_int_t dim2,
501 spm_int_t dim3,
502 spm_fixdbl_t alpha,
503 spm_fixdbl_t beta )
504{
505 /*
506 * See https://crd.lbl.gov/assets/pubs_presos/iwapt09-27pt.pdf for the
507 * meaning of alpha, beta, gamma, and delta.
508 * "Auto-tuning the 27-point Stencil for Multicore", K. Datta, S. Williams,
509 * V. Volkov, J. Carter, L. Oliker, J. Shalf, and K. Yelick
510 */
511#if !defined(PRECISION_p)
512 spm_complex64_t *valptr;
513 spm_complex64_t lalpha = (spm_complex64_t)alpha;
514 spm_complex64_t lbeta = (spm_complex64_t)beta;
515 spm_complex64_t lgamma = (spm_complex64_t)beta / sqrt(2.);
516 spm_complex64_t ldelta = (spm_complex64_t)beta / sqrt(3.);
517#endif
518 spm_int_t *colptr, *rowptr;
519 spm_int_t i, j, k, l, row, degree;
520 spm_int_t ldim1, fk, lk;
521 int level = 3; /* To store all edges */
522
523 spm->mtxtype = SpmSymmetric;
524 spm->flttype = SpmComplex64;
525 spm->fmttype = SpmCSC;
526 spm->baseval = 0;
527 spm->dof = 1;
528 spm->gnnz = z_spmLaplacian_getnnz( dim1, dim2, dim3, level, 0 );
529 assert( spm->gN == dim1 * dim2 * dim3 );
530
531 /* Let's split along first dimension */
532 ldim1 = dim1 / spm->clustnbr;
533 fk = ldim1 * spm->clustnum + spm_imin( spm->clustnum, dim1 % spm->clustnbr );
534 lk = ldim1 * (spm->clustnum+1) + spm_imin( spm->clustnum+1, dim1 % spm->clustnbr );
535 ldim1 = lk - fk;
536
537 /* Let's compute the local number of nnz */
538 spm->replicated = (spm->clustnbr == 1); /* Set to 0 if multiple node, 1 otherwise */
539 spm->n = ldim1 * dim2 * dim3;
540 spm->nnz = z_spmLaplacian_getnnz( ldim1, dim2, dim3, level, (lk < dim1) );
541 /* if ( spm->n == 0 ) { */
542 /* if ( spm->clustnbr > 1 ) { */
543 /* /\* Fake malloc to make it part of the collective comunications *\/ */
544 /* spm->loc2glob = malloc(sizeof(int)); */
545 /* } */
546 /* return; */
547 /* } */
548
549 /* Allocating */
550 spm->colptr = malloc( (spm->n+1) * sizeof(spm_int_t) );
551 spm->rowptr = malloc( spm->nnz * sizeof(spm_int_t) );
552 assert( spm->colptr );
553 assert( spm->rowptr );
554
555#if !defined(PRECISION_p)
556 spm->values = malloc( spm->nnz * sizeof(spm_complex64_t) );
557 assert( spm->values );
558 valptr = (spm_complex64_t*)(spm->values);
559#endif
560
561 /* Building ia, ja and values*/
562 colptr = spm->colptr;
563 rowptr = spm->rowptr;
564
565 /* Building ia, ja and values*/
566 *colptr = 0;
567
568 l = dim2 * dim3 * fk;
569 for( k=fk; k<lk; k++ )
570 {
571 int dk = 1;
572 if ( k > 0 ) {
573 dk++;
574 }
575 if ( k < (dim1-1) ) {
576 dk++;
577 }
578
579 for( i=0; i<dim2; i++ )
580 {
581 int di = 1;
582 if ( i > 1 ) {
583 di++;
584 }
585 if ( i < (dim2-1) ) {
586 di++;
587 }
588
589 for( j=0; j<dim3; j++, l++ )
590 {
591 int dj = 1;
592 if ( j > 1 ) {
593 dj++;
594 }
595 if ( j < (dim3-1) ) {
596 dj++;
597 }
598
599 colptr[1] = colptr[0];
600
601 /* Diagonal value */
602 degree = dk * di * dj - 1;
603 laplacian_add_one_edge( colptr, rowptr, valptr, l, (spm_complex64_t)degree * lalpha );
604
605 /*
606 * There are 3 possible beta edges:
607 * + 1
608 * + dim3
609 * + dim3 * dim2
610 *
611 * There are 6 possible gamma edges:
612 * + dim3 +/- 1
613 * + dim3 * dim2 +/- 1
614 * + dim3 * dim2 +/- dim3
615 *
616 * There are 4 possible delta edges:
617 * + dim3 * dim2 +/- dim3 +/- 1
618 *
619 * If we sort them:
620 * + 1
621 *
622 * + dim3 - 1
623 * + dim3
624 * + dim3 + 1
625 *
626 * + dim3 * dim2 - dim3 - 1
627 * + dim3 * dim2 - dim3
628 * + dim3 * dim2 - dim3 + 1
629 * + dim3 * dim2 - 1
630 * + dim3 * dim2
631 * + dim3 * dim2 + 1
632 * + dim3 * dim2 + dim3 - 1
633 * + dim3 * dim2 + dim3
634 * + dim3 * dim2 + dim3 + 1
635 */
636
637 /* Connexion along dimension 3 */
638 if ( j < (dim3 - 1) ) {
639 laplacian_add_one_edge( colptr, rowptr, valptr, l + 1, lbeta );
640 }
641
642 /* Connexion along dimension 2 */
643 if ( i < (dim2-1) )
644 {
645 row = l + dim3;
646 laplacian_add_three_edges( colptr, rowptr, valptr,
647 row, (j > 0), (j < (dim3-1)),
648 lbeta, lgamma );
649 }
650
651 /* Connexion along dimension 1 */
652 if ( k < (dim1 - 1) ) {
653 if( i > 0 )
654 {
655 row = l + dim3 * dim2 - dim3;
656 laplacian_add_three_edges( colptr, rowptr, valptr,
657 row, (j > 0), (j < (dim3-1)),
658 lgamma, ldelta );
659 }
660
661 row = l + dim3 * dim2;
662 laplacian_add_three_edges( colptr, rowptr, valptr,
663 row, (j > 0), (j < (dim3-1)),
664 lbeta, lgamma );
665
666 if( i < (dim2 - 1) )
667 {
668 row = l + dim3 * dim2 + dim3;
669 laplacian_add_three_edges( colptr, rowptr, valptr,
670 row, (j > 0), (j < (dim3-1)),
671 lgamma, ldelta );
672 }
673 }
674
675 colptr++;
676 }
677 }
678 }
679
680 assert( (spm->colptr[ spm->n ] - spm->colptr[0]) == spm->nnz );
681
682 /* Initialize the loc2glob array */
683 if (( spm->clustnbr > 1 ) && (spm->n > 0) ) {
684 spm_int_t *loc2glob;
685 spm->loc2glob = malloc( spm->n * sizeof(spm_int_t) );
686
687 loc2glob = spm->loc2glob;
688 l = dim2 * dim3 * fk;
689 for(k=0; k<spm->n; k++, l++, loc2glob++ ) {
690 *loc2glob = l;
691 }
692 }
693
694 (void)alpha;
695 (void)beta;
696 (void)degree;
697}
double spm_fixdbl_t
Double datatype that is not converted through precision generator functions.
Definition datatypes.h:150
static spm_int_t spm_imin(spm_int_t a, spm_int_t b)
Internal function to compute min(a,b)
Definition datatypes.h:97
@ SpmComplex64
Definition const.h:66
@ SpmSymmetric
Definition const.h:166
@ SpmHermitian
Definition const.h:167
@ SpmCSC
Definition const.h:73
spm_coeftype_t flttype
Definition spm.h:67
void * values
Definition spm.h:92
int clustnbr
Definition spm.h:96
spm_int_t nnz
Definition spm.h:75
spm_int_t * rowptr
Definition spm.h:90
spm_int_t gnnz
Definition spm.h:74
spm_fmttype_t fmttype
Definition spm.h:69
spm_int_t dof
Definition spm.h:82
spm_int_t n
Definition spm.h:73
spm_mtxtype_t mtxtype
Definition spm.h:65
spm_int_t * loc2glob
Definition spm.h:91
spm_int_t baseval
Definition spm.h:71
spm_int_t * colptr
Definition spm.h:89
int clustnum
Definition spm.h:95
spm_int_t gN
Definition spm.h:72
int replicated
Definition spm.h:98
int spm_int_t
The main integer datatype used in spm arrays.
Definition datatypes.h:70
The sparse matrix data structure.
Definition spm.h:64
void z_spmLaplacian_7points(spmatrix_t *spm, spm_int_t dim1, spm_int_t dim2, spm_int_t dim3, spm_fixdbl_t alpha, spm_fixdbl_t beta)
Generate a laplacian matrix for a 3D 7-points stencil.
void z_spmLaplacian_27points(spmatrix_t *spm, spm_int_t dim1, spm_int_t dim2, spm_int_t dim3, spm_fixdbl_t alpha, spm_fixdbl_t beta)
Generate an extended laplacian matrix for a 3D 27-points stencil.
#define laplacian_add_three_edges(_colptr_, _rowptr_, _valptr_, _dest_, _fcond_, _lcond_, _valone_, _valtwo_)
Add three edges of the 27 pts stencil. the direct one, and its two diagonal neighboor ones.
#define laplacian_add_one_edge(_colptr_, _rowptr_, _valptr_, _dest_, _value_)
Add an edge to the spm matrix.
static spm_int_t z_spmLaplacian_getnnz(spm_int_t M, spm_int_t N, spm_int_t K, int level, int connexion)
Return the number of edges in a laplacian of size MxNxK.