SpM Handbook 1.2.4
Loading...
Searching...
No Matches
c_spm_expand.c
Go to the documentation of this file.
1/**
2 *
3 * @file c_spm_expand.c
4 *
5 * SParse Matrix package random multi-dof spm generator.
6 *
7 * @copyright 2016-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
8 * Univ. Bordeaux. All rights reserved.
9 *
10 * @version 1.2.4
11 * @author Mathieu Faverge
12 * @author Alban Bellot
13 * @author Matias Hastaran
14 * @author Tony Delarue
15 * @author Alycia Lisito
16 * @date 2024-06-25
17 *
18 * @generated from /builds/2mk6rsew/0/fpruvost/spm/src/z_spm_expand.c, normal z -> c, Fri Nov 29 11:34:28 2024
19 **/
20#include "common.h"
21
22/**
23 *******************************************************************************
24 *
25 * @ingroup spm_dev_dof
26 *
27 * @brief Create the associated loc2glob of an expanded matrix.
28 *
29 *******************************************************************************
30 *
31 * @param[in] spm_in
32 * The original non expanded matrix.
33 *
34 * @param[in] spm_out
35 * The output expanded matrix for which the loc2glob array must be
36 * expanded.
37 *
38 *******************************************************************************/
39static inline void
41 spmatrix_t *spm_out )
42{
43 spm_int_t i, j, ig, jg, baseval, ndof;
44
45 spm_int_t *l2g_in = spm_in->loc2glob;
46 spm_int_t *l2g_out = spm_out->loc2glob;
47
48 baseval = spm_in->baseval;
49
50 /* Constant dof */
51 if ( spm_in->dof > 0 ) {
52 ndof = spm_in->dof;
53 for ( i=0; i<spm_in->n; i++, l2g_in++ ) {
54 ig = *l2g_in - baseval;
55 jg = ig * ndof + baseval;
56 for ( j=0; j<ndof; j++, l2g_out++ ) {
57 *l2g_out = jg + j;
58 }
59 }
60 }
61 /* Variadic dof */
62 else {
63 spm_int_t *dofs = spm_in->dofs - baseval;
64 for ( i=0; i<spm_in->n; i++, l2g_in++ ) {
65 ig = *l2g_in;
66 ndof = dofs[ig+1] - dofs[ig];
67 jg = dofs[ig];
68
69 for (j=0; j<ndof; j++, l2g_out++) {
70 *l2g_out = jg + j;
71 }
72 }
73 }
74
75 assert( (l2g_out - spm_out->loc2glob) == spm_out->n );
76}
77
78/**
79 *******************************************************************************
80 *
81 * @ingroup spm_dev_dof
82 *
83 * @brief Expand a single dof CSC to a multi-dofs CSC.
84 *
85 * Each element matrix is fully initialized with the same element as the
86 * original one.
87 *
88 *******************************************************************************
89 *
90 * @param[in] spm_in
91 * The original non expanded matrix in CSC format used as the template
92 * for the muti-dof matrix.
93 *
94 * @param[inout] spm_out
95 * The output expanded matrix generated from the template.
96 *
97 *******************************************************************************/
98static void
100 spmatrix_t *spm_out )
101{
102 spm_int_t j, k, ii, jj, ig, jg;
103 spm_int_t dofi, dofj, col, row, baseval, lda;
104 spm_int_t diag, height;
105 spm_int_t *newcol, *newrow, *oldcol, *oldrow, *dofs;
106#if !defined(PRECISION_p)
107 spm_complex32_t *newval = NULL;
108#endif
109 spm_complex32_t *oldval2, *oldval = NULL;
110
111 assert( spm_in->fmttype == SpmCSC );
112
113 baseval = spm_in->baseval;
114 oldcol = spm_in->colptr;
115 oldrow = spm_in->rowptr;
116 dofs = spm_in->dofs;
117#if !defined(PRECISION_p)
118 oldval = oldval2 = (spm_complex32_t *)( spm_in->values );
119#endif
120
121 spm_out->colptr = newcol = malloc( sizeof( spm_int_t ) * ( spm_out->n + 1 ) );
122
123 /**
124 * First loop to compute the new colptr
125 */
126 *newcol = baseval;
127 for ( j=0; j<spm_in->n; j++, oldcol++ ) {
128 diag = 0;
129 jg = spm_in->replicated ? j : spm_in->loc2glob[j] - baseval;
130 dofj = ( spm_in->dof > 0 ) ? spm_in->dof : dofs[jg+1] - dofs[jg];
131
132 /* Sum the heights of the elements in the column */
133 newcol[1] = newcol[0];
134 for ( k=oldcol[0]; k<oldcol[1]; k++, oldrow++ ) {
135 ig = *oldrow - baseval;
136 dofi = ( spm_in->dof > 0 ) ? spm_in->dof : dofs[ig+1] - dofs[ig];
137 newcol[1] += dofi;
138
139 diag = ( diag || ( ig == jg ) );
140 }
141
142 diag = ( diag & ( spm_in->mtxtype != SpmGeneral ) );
143 height = newcol[1] - newcol[0];
144 newcol++;
145
146 /* Add extra columns */
147 for ( jj=1; jj<dofj; jj++, newcol++ ) {
148 newcol[1] = newcol[0] + height;
149
150 if ( diag ) {
151 newcol[1] -= jj;
152 }
153 }
154 }
155 assert( ((spm_in->mtxtype == SpmGeneral) && ((newcol[0]-baseval) == spm_in->nnzexp)) ||
156 ((spm_in->mtxtype != SpmGeneral) && ((newcol[0]-baseval) <= spm_in->nnzexp)) );
157
158 spm_out->nnz = newcol[0] - baseval;
159 spm_out->rowptr = newrow = malloc( sizeof(spm_int_t) * spm_out->nnz );
160#if !defined( PRECISION_p )
161 spm_out->values = newval = malloc( sizeof(spm_complex32_t) * spm_out->nnz );
162#endif
163
164 /**
165 * Second loop to compute the new rowptr and valptr
166 */
167 oldcol = spm_in->colptr;
168 oldrow = spm_in->rowptr;
169 newcol = spm_out->colptr;
170 for ( j=0, col=0; j<spm_in->n; j++, oldcol++ ) {
171 /**
172 * Backup current position in oldval because we will pick
173 * interleaved data inside the buffer
174 */
175 lda = newcol[1] - newcol[0];
176 oldval2 = oldval;
177 jg = spm_in->replicated ? j : spm_in->loc2glob[j] - baseval;
178
179 if ( spm_in->dof > 0 ) {
180 dofj = spm_in->dof;
181 assert( col == spm_in->dof * j );
182 }
183 else {
184 dofj = dofs[jg+1] - dofs[jg];
185 }
186
187 for ( jj=0; jj<dofj; jj++, col++, newcol++ ) {
188 assert( ((spm_in->mtxtype == SpmGeneral) && (lda == (newcol[1] - newcol[0]))) ||
189 ((spm_in->mtxtype != SpmGeneral) && (lda >= (newcol[1] - newcol[0]))) );
190
191 /* Move to the top of the column jj in coming element (i,j) */
192 oldval = oldval2;
193
194 for ( k=oldcol[0]; k<oldcol[1]; k++ ) {
195 ig = oldrow[k-baseval] - baseval;
196
197 if ( spm_in->dof > 0 ) {
198 dofi = spm_in->dof;
199 row = spm_in->dof * ig;
200 }
201 else {
202 dofi = dofs[ig+1] - dofs[ig];
203 row = dofs[ig] - baseval;
204 }
205
206 /* Move to the top of the jj column in the current element */
207 oldval += dofi * jj;
208
209 for ( ii=0; ii<dofi; ii++, row++ ) {
210 if ( (spm_in->mtxtype == SpmGeneral) ||
211 (ig != jg) ||
212 ((ig == jg) && (row >= col)) )
213 {
214 (*newrow) = row + baseval;
215 newrow++;
216#if !defined(PRECISION_p)
217 (*newval) = *oldval;
218 newval++;
219#endif
220 }
221 oldval++;
222 }
223 /* Move to the top of the next element */
224 oldval += dofi * (dofj-jj-1);
225 }
226 }
227 }
228
229 (void)lda;
230 return;
231}
232
233/**
234 *******************************************************************************
235 *
236 * @ingroup spm_dev_dof
237 *
238 * @brief Expand a single dof CSR to a multi-dofs CSR.
239 *
240 * Each element matrix is fully initialized with the same element as the
241 * original one.
242 *
243 *******************************************************************************
244 *
245 * @param[in] spm_in
246 * The original non expanded matrix in CSR format used as the template
247 * for the muti-dof matrix.
248 *
249 * @param[inout] spm_out
250 * The output expanded matrix generated from the template.
251 *
252 *******************************************************************************/
253static void
255 spmatrix_t *spm_out )
256{
257 spm_int_t i, k, ii, jj, ig, jg;
258 spm_int_t dofi, dofj, col, row, baseval, lda;
259 spm_int_t diag, height;
260 spm_int_t *newcol, *newrow, *oldcol, *oldrow, *dofs;
261#if !defined(PRECISION_p)
262 spm_complex32_t *newval = NULL;
263#endif
264 spm_complex32_t *oldval2, *oldval = NULL;
265
266 assert( spm_in->fmttype == SpmCSR );
267
268 baseval = spm_in->baseval;
269 oldcol = spm_in->colptr;
270 oldrow = spm_in->rowptr;
271 dofs = spm_in->dofs;
272#if !defined(PRECISION_p)
273 oldval = oldval2 = (spm_complex32_t*)(spm_in->values);
274#endif
275
276 spm_out->rowptr = newrow = malloc( sizeof(spm_int_t) * (spm_out->n+1) );
277
278 /**
279 * First loop to compute the new rowptr
280 */
281 *newrow = baseval;
282 for ( i=0; i<spm_in->n; i++, oldrow++ ) {
283 diag = 0;
284 ig = spm_in->replicated ? i : spm_in->loc2glob[i] - baseval;
285 dofi = ( spm_in->dof > 0 ) ? spm_in->dof : dofs[ig+1] - dofs[ig];
286
287 /* Sum the width of the elements in the row */
288 newrow[1] = newrow[0];
289 for ( k=oldrow[0]; k<oldrow[1]; k++, oldcol++ ) {
290 jg = *oldcol - baseval;
291 dofj = (spm_in->dof > 0 ) ? spm_in->dof : dofs[jg+1] - dofs[jg];
292 newrow[1] += dofj;
293
294 diag = ( diag || ( ig == jg ) );
295 }
296
297 diag = ( diag & ( spm_in->mtxtype != SpmGeneral ) );
298 height = newrow[1] - newrow[0];
299 newrow++;
300
301 /* Add extra rows */
302 for ( ii=1; ii<dofi; ii++, newrow++ ) {
303 newrow[1] = newrow[0] + height;
304
305 if ( diag ) {
306 newrow[1] -= ii;
307 }
308 }
309 }
310 assert( ((spm_in->mtxtype == SpmGeneral) && ((newrow[0]-baseval) == spm_in->nnzexp)) ||
311 ((spm_in->mtxtype != SpmGeneral) && ((newrow[0]-baseval) <= spm_in->nnzexp)) );
312
313 spm_out->nnz = newrow[0] - baseval;
314 spm_out->colptr = newcol = malloc( sizeof(spm_int_t) * spm_out->nnz );
315#if !defined(PRECISION_p)
316 spm_out->values = newval = malloc( sizeof(spm_complex32_t) * spm_out->nnz );
317#endif
318
319 /**
320 * Second loop to compute the new colptr and valptr
321 */
322 oldcol = spm_in->colptr;
323 oldrow = spm_in->rowptr;
324 newrow = spm_out->rowptr;
325 for ( i=0, row=0; i<spm_in->n; i++, oldrow++ ) {
326 /**
327 * Backup current position in oldval because we will pick
328 * interleaved data inside the buffer
329 */
330 lda = newrow[1] - newrow[0];
331 oldval2 = oldval;
332 ig = spm_in->replicated ? i : spm_in->loc2glob[i] - baseval;
333
334 if ( spm_in->dof > 0 ) {
335 dofi = spm_in->dof;
336 assert( row == spm_in->dof * i );
337 }
338 else {
339 dofi = dofs[ig+1] - dofs[ig];
340 }
341
342 for ( ii=0; ii<dofi; ii++, row++, newrow++ ) {
343 assert( ( ( spm_in->mtxtype == SpmGeneral ) && ( lda == ( newrow[1] - newrow[0] ) ) ) ||
344 ( ( spm_in->mtxtype != SpmGeneral ) && ( lda >= ( newrow[1] - newrow[0] ) ) ) );
345
346 /* Move to the beginning of the row ii in coming element (i,j) */
347 oldval = oldval2 + ii;
348
349 for ( k=oldrow[0]; k<oldrow[1]; k++ ) {
350 jg = oldcol[k-baseval] - baseval;
351
352 if ( spm_in->dof > 0 ) {
353 dofj = spm_in->dof;
354 col = spm_in->dof * jg;
355 }
356 else {
357 dofj = dofs[jg+1] - dofs[jg];
358 col = dofs[jg] - baseval;
359 }
360
361 for ( jj=0; jj<dofj; jj++, col++ ) {
362 if ( ( spm_in->mtxtype == SpmGeneral ) || ( ig != jg ) ||
363 ( ( ig == jg ) && ( row <= col ) ) )
364 {
365 (*newcol) = col + baseval;
366 newcol++;
367#if !defined(PRECISION_p)
368 (*newval) = *oldval;
369 newval++;
370#endif
371 }
372 /* Move to next value in row ii */
373 oldval += dofi;
374 }
375 }
376 }
377 /* Move to the begining of the next row of elements */
378 oldval -= (dofi-1);
379 }
380
381 (void)lda;
382 return;
383}
384
385/**
386 *******************************************************************************
387 *
388 * @ingroup spm_dev_dof
389 *
390 * @brief Expand a single dof IJV to a multi-dofs IJV.
391 *
392 * Each element matrix is fully initialized with the same element as the
393 * original one.
394 *
395 *******************************************************************************
396 *
397 * @param[in] spm_in
398 * The original non expanded matrix in IJV format used as the template
399 * for the muti-dof matrix.
400 *
401 * @param[inout] spm_out
402 * The output expanded matrix generated from the template.
403 *
404 *******************************************************************************/
405static void
407 spmatrix_t *spm_out )
408{
409 spm_int_t i, j, k, ii, jj, dofi, dofj, col, row, baseval;
410 spm_int_t *newcol, *newrow, *oldcol, *oldrow, *dofs;
411#if !defined(PRECISION_p)
412 spm_complex32_t *newval = NULL;
413#endif
414 spm_complex32_t *oldval = NULL;
415
416 assert( spm_in->fmttype == SpmIJV );
417
418 baseval = spm_in->baseval;
419 oldcol = spm_in->colptr;
420 oldrow = spm_in->rowptr;
421 dofs = spm_in->dofs;
422#if !defined( PRECISION_p )
423 oldval = (spm_complex32_t *)(spm_in->values);
424#endif
425
426 /**
427 * First loop to compute the size of the vectors
428 */
429 if ( spm_in->mtxtype == SpmGeneral ) {
430 spm_out->nnz = spm_in->nnzexp;
431 }
432 else {
433 spm_out->nnz = 0;
434 for ( k=0; k<spm_in->nnz; k++, oldrow++, oldcol++ ) {
435 i = *oldrow - baseval;
436 j = *oldcol - baseval;
437
438 if ( spm_in->dof > 0 ) {
439 dofi = spm_in->dof;
440 dofj = spm_in->dof;
441 }
442 else {
443 dofi = dofs[i+1] - dofs[i];
444 dofj = dofs[j+1] - dofs[j];
445 }
446
447 if ( i != j ) {
448 spm_out->nnz += dofi * dofj;
449 }
450 else {
451 assert( dofi == dofj );
452 spm_out->nnz += (dofi * (dofi+1)) / 2;
453 }
454 }
455 assert( spm_out->nnz <= spm_in->nnzexp );
456 }
457
458 spm_out->rowptr = newrow = malloc( sizeof(spm_int_t) * spm_out->nnz );
459 spm_out->colptr = newcol = malloc( sizeof(spm_int_t) * spm_out->nnz );
460#if !defined(PRECISION_p)
461 spm_out->values = newval = malloc( sizeof(spm_complex32_t) * spm_out->nnz );
462#endif
463
464 /**
465 * Second loop to compute the new rowptr, colptr and valptr
466 */
467 oldrow = spm_in->rowptr;
468 oldcol = spm_in->colptr;
469 for ( k=0; k<spm_in->nnz; k++, oldrow++, oldcol++ ) {
470 i = *oldrow - baseval;
471 j = *oldcol - baseval;
472
473 if ( spm_in->dof > 0 ) {
474 dofi = spm_in->dof;
475 row = spm_in->dof * i;
476 dofj = spm_in->dof;
477 col = spm_in->dof * j;
478 }
479 else {
480 dofi = dofs[i+1] - dofs[i];
481 row = dofs[i] - baseval;
482 dofj = dofs[j+1] - dofs[j];
483 col = dofs[j] - baseval;
484 }
485
486 if ( spm_in->layout == SpmColMajor ) {
487 for ( jj=0; jj<dofj; jj++ ) {
488 for ( ii=0; ii<dofi; ii++, oldval+=1 ) {
489 if ( ( spm_in->mtxtype == SpmGeneral ) || ( i != j ) ||
490 ( ( i == j ) && ( row + ii >= col + jj ) ) )
491 {
492 assert( row + ii < spm_out->gNexp );
493 assert( col + jj < spm_out->gNexp );
494 (*newrow) = row + ii + baseval;
495 (*newcol) = col + jj + baseval;
496 newrow++;
497 newcol++;
498#if !defined(PRECISION_p)
499 (*newval) = *oldval;
500 newval++;
501#endif
502 }
503 }
504 }
505 }
506 else {
507 for ( ii=0; ii<dofi; ii++ ) {
508 for ( jj=0; jj<dofj; jj++, oldval+=1 ) {
509 if ( ( spm_in->mtxtype == SpmGeneral ) || ( i != j ) ||
510 ( ( i == j ) && ( row + ii >= col + jj ) ) )
511 {
512 assert( row + ii < spm_out->gNexp );
513 assert( col + jj < spm_out->gNexp );
514 (*newrow) = row + ii + baseval;
515 (*newcol) = col + jj + baseval;
516 newrow++;
517 newcol++;
518#if !defined(PRECISION_p)
519 (*newval) = *oldval;
520 newval++;
521#endif
522 }
523 }
524 }
525 }
526 }
527 assert( newcol - spm_out->colptr == spm_out->nnz );
528 assert( newrow - spm_out->rowptr == spm_out->nnz );
529
530 return;
531}
532
533/**
534 *******************************************************************************
535 *
536 * @ingroup spm_dev_dof
537 *
538 * @brief Expand a single dof sparse matrix to a multi-dofs sparse matrix.
539 *
540 * The original value of the element is replicated through the entire element
541 * matrix that is generated in this routine.
542 *
543 * @warning This function should never be called directly, except by spmExpand().
544 *
545 *******************************************************************************
546 *
547 * @param[in] spm_in
548 * The original input matrix with dof = 1.
549 *
550 * @param[in,out] spm_out
551 * The expanded matrix with the same pattern as spm_in, but with
552 * multiple dofs per element.
553 *
554 *******************************************************************************/
555void
556c_spmExpand( const spmatrix_t *spm_in,
557 spmatrix_t *spm_out )
558{
559 assert( spm_in != NULL );
560 assert( spm_out != NULL );
561 assert( spm_in->flttype == SpmComplex32 );
562
563 if ( spm_in->dof == 1 ) {
564 if ( spm_in != spm_out ) {
565 spmCopy( spm_in, spm_out );
566 }
567 return;
568 }
569
570 if ( spm_in->layout != SpmColMajor ) {
571 fprintf( stderr, "Unsupported layout\n" );
572 exit( 1 );
573 return;
574 }
575
576 memcpy( spm_out, spm_in, sizeof(spmatrix_t) );
577 spm_out->n = spm_in->nexp;
578
579 if ( !spm_in->replicated && (spm_out->n > 0) ) {
580 spm_out->loc2glob = malloc( spm_out->n * sizeof(spm_int_t) );
581 c_spm_expand_loc2glob( spm_in, spm_out );
582 }
583
584 switch ( spm_in->fmttype ) {
585 case SpmCSC:
586 c_spmCSCExpand( spm_in, spm_out );
587 break;
588 case SpmCSR:
589 c_spmCSRExpand( spm_in, spm_out );
590 break;
591 case SpmIJV:
592 c_spmIJVExpand( spm_in, spm_out );
593 break;
594 }
595
596 spm_out->dof = 1;
597 spm_out->layout = SpmColMajor;
598 spm_out->dofs = NULL;
599 spm_out->glob2loc = NULL;
600
601 spmUpdateComputedFields( spm_out );
602
603 return;
604}
float _Complex spm_complex32_t
Definition datatypes.h:161
@ SpmColMajor
Definition const.h:148
@ SpmComplex32
Definition const.h:65
@ SpmGeneral
Definition const.h:165
@ SpmCSC
Definition const.h:73
@ SpmCSR
Definition const.h:74
@ SpmIJV
Definition const.h:75
static void c_spmCSCExpand(const spmatrix_t *spm_in, spmatrix_t *spm_out)
Expand a single dof CSC to a multi-dofs CSC.
static void c_spmCSRExpand(const spmatrix_t *spm_in, spmatrix_t *spm_out)
Expand a single dof CSR to a multi-dofs CSR.
static void c_spm_expand_loc2glob(const spmatrix_t *spm_in, spmatrix_t *spm_out)
Create the associated loc2glob of an expanded matrix.
void c_spmExpand(const spmatrix_t *spm_in, spmatrix_t *spm_out)
Expand a single dof sparse matrix to a multi-dofs sparse matrix.
static void c_spmIJVExpand(const spmatrix_t *spm_in, spmatrix_t *spm_out)
Expand a single dof IJV to a multi-dofs IJV.
spm_coeftype_t flttype
Definition spm.h:67
spm_int_t * dofs
Definition spm.h:85
spm_int_t nexp
Definition spm.h:78
void * values
Definition spm.h:92
spm_int_t nnz
Definition spm.h:75
spm_int_t nnzexp
Definition spm.h:80
spm_int_t * rowptr
Definition spm.h:90
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_layout_t layout
Definition spm.h:87
spm_int_t baseval
Definition spm.h:71
spm_int_t * glob2loc
Definition spm.h:94
spm_int_t * colptr
Definition spm.h:89
int replicated
Definition spm.h:98
void spmUpdateComputedFields(spmatrix_t *spm)
Update all the computed fields based on the static values stored.
int spm_int_t
The main integer datatype used in spm arrays.
Definition datatypes.h:70
void spmCopy(const spmatrix_t *spm_in, spmatrix_t *spm_out)
Create a copy of the spm.
Definition spm.c:969
The sparse matrix data structure.
Definition spm.h:64