SpM Handbook 1.2.4
Loading...
Searching...
No Matches
laplacian.c
Go to the documentation of this file.
1/**
2 *
3 * @file laplacian.c
4 *
5 * @copyright 2011-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
6 * Univ. Bordeaux. All rights reserved.
7 *
8 * @version 1.2.4
9 * @author Mathieu Faverge
10 * @author Pierre Ramet
11 * @author Tony Delarue
12 * @author Gregoire Pichon
13 * @date 2024-05-29
14 *
15 **/
16#include "common.h"
17#include "spm_drivers.h"
18#include "drivers/laplacian.h"
19
20/**
21 *
22 * @ingroup spm_dev_driver
23 *
24 * @brief Print the usage information to generate correct Laplacian matrices.
25 */
26static inline void
28{
29 fprintf(stderr,
30 "Usage: genLaplacian( \"[<type>:]<dim1>[:<dim2>[:<dim3>[:<alpha>[:<beta>[:<dof>]]]]]\" )\n"
31 " Generate a Laplacian matrix M, of the form alpha * D - beta * A,\n"
32 " where D is the degree matrix, and A the adjacency matrix.\n"
33 " <type> p = pattern only\n"
34 " s = real simple\n"
35 " d = real double [default]\n"
36 " c = complex simple\n"
37 " z = complex double\n"
38 " <dim1> size of the first dimension of the laplacian\n"
39 " <dim2> size of the second dimension of the laplacian\n"
40 " <dim3> size of the third dimension of the laplacian\n"
41 " <dof> size of the dof parameter to generate multi-dof matrices laplacian\n"
42 " Example:\n"
43 " genLaplacian( \"z:10:20\" ) generates a 2D complex double laplacian matrix of size 200.\n"
44 " genLaplacian( \"10:1:10:2.:0.5\" ) generates a 2D real double laplacian matrix of size 100 where M = 2. * D - 0.5 * A.\n"
45 " genLaplacian( \"s:10\" ) generates a 1D real single laplacian matrix of size 10.\n"
46 );
47}
48
49/**
50 *******************************************************************************
51 *
52 * @ingroup spm
53 *
54 * @brief Parse information given through the filename string to configure the
55 * laplacian matrix to generate.
56 *
57 * The laplacian will be of size dim1 * dim2 * dim3, and will be equal to
58 * \f$ M = \alpha * D - \beta * A \f$
59 *
60 * where D is the degree matrix, and A the adjacency matrix.
61 *
62 *******************************************************************************
63 *
64 * @param[in] filename
65 * Configuration string of the Laplacian. See laplacian_usage() for
66 * more information.
67 *
68 * @param[out] flttype
69 * The floating type of the elements in the matrix.
70 *
71 * @param[out] dim1
72 * The first dimension of the laplacian
73 *
74 * @param[out] dim2
75 * The second dimension of the laplacian
76 *
77 * @param[out] dim3
78 * The third dimension of the laplacian
79 *
80 * @param[out] alpha
81 * The alpha coefficient for the degree matrix
82 *
83 * @param[out] beta
84 * The beta coefficient for the adjacency matrix
85 *
86 * @param[out] dof
87 * The degree of freedom of each unknown
88 *
89 *******************************************************************************
90 *
91 * @retval SPM_SUCCESS if the matrix has been generated successfully
92 * @retval SPM_ERR_BADPARAMETER if the configuration string is incorrect
93 *
94 *******************************************************************************/
95int
96spmParseLaplacianInfo( const char *filename,
97 spm_coeftype_t *flttype,
98 spm_int_t *dim1,
99 spm_int_t *dim2,
100 spm_int_t *dim3,
101 double *alpha,
102 double *beta,
103 spm_int_t *dof )
104{
105 double val1, val2;
106 long tmp1, tmp2, tmp3, tmp4;
107
108 *alpha = 1.;
109 *beta = 1.;
110 *dof = 1;
111
112 /* Look for the datatype */
113 {
114 size_t nfilename = strlen( filename );
115 char flt, *tmpf;
116 tmpf = calloc( spm_imax( nfilename, 256 ), sizeof(char) );
117
118 if ( sscanf( filename, "%c:%255s", &flt, tmpf ) == 2 ) {
119 filename += 2;
120 switch( flt ){
121 case 'Z':
122 case 'z':
123 *flttype = SpmComplex64;
124 break;
125
126 case 'C':
127 case 'c':
128 *flttype = SpmComplex32;
129 break;
130
131 case 'D':
132 case 'd':
133 *flttype = SpmDouble;
134 break;
135
136 case 'S':
137 case 's':
138 *flttype = SpmFloat;
139 break;
140
141 case 'P':
142 case 'p':
143 *flttype = SpmPattern;
144 break;
145
146 case '1':
147 case '2':
148 case '3':
149 case '4':
150 case '5':
151 case '6':
152 case '7':
153 case '8':
154 case '9':
155 *flttype = SpmDouble;
156 /*
157 * The first dimension is only one character long so we come
158 * back to the beginning of the string
159 */
160 filename -= 2;
161 break;
162
163 default:
165 free(tmpf);
167 }
168 }
169 else {
170 *flttype = SpmDouble;
171 }
172
173 free(tmpf);
174 }
175
176 /* Scan the dimensions */
177 *dim1 = *dim2 = *dim3 = 1;
178
179 if ( sscanf( filename, "%ld:%ld:%ld:%lf:%lf:%ld",
180 &tmp1, &tmp2, &tmp3, &val1, &val2, &tmp4 ) == 6 ) {
181 *dim1 = (spm_int_t)tmp1;
182 *dim2 = (spm_int_t)tmp2;
183 *dim3 = (spm_int_t)tmp3;
184 *alpha = val1;
185 *beta = val2;
186 *dof = (spm_int_t)tmp4;
187 }
188 else if ( sscanf( filename, "%ld:%ld:%ld:%lf:%lf", &tmp1, &tmp2, &tmp3, &val1, &val2 ) == 5 ) {
189 *dim1 = (spm_int_t)tmp1;
190 *dim2 = (spm_int_t)tmp2;
191 *dim3 = (spm_int_t)tmp3;
192 *alpha = val1;
193 *beta = val2;
194 }
195 else if ( sscanf( filename, "%ld:%ld:%ld:%lf", &tmp1, &tmp2, &tmp3, &val1 ) == 4 ) {
196 *dim1 = (spm_int_t)tmp1;
197 *dim2 = (spm_int_t)tmp2;
198 *dim3 = (spm_int_t)tmp3;
199 *alpha = val1;
200 }
201 else if ( sscanf( filename, "%ld:%ld:%ld", &tmp1, &tmp2, &tmp3 ) == 3 ) {
202 *dim1 = (spm_int_t)tmp1;
203 *dim2 = (spm_int_t)tmp2;
204 *dim3 = (spm_int_t)tmp3;
205 }
206 else if ( sscanf( filename, "%ld:%ld", &tmp1, &tmp2 ) == 2 ) {
207 *dim1 = (spm_int_t)tmp1;
208 *dim2 = (spm_int_t)tmp2;
209 }
210 else if ( sscanf( filename, "%ld", &tmp1 ) == 1 ) {
211 *dim1 = (spm_int_t)tmp1;
212 }
213 else {
216 }
217
218 assert( *dof != 0 );
219
220 /* One of the dimension was set to 0 */
221 if ( (*dim1 == 0) || (*dim2 == 0) || (*dim3 == 0) ) {
224 }
225
226 return SPM_SUCCESS;
227}
228
229/**
230 * @ingroup spm_dev_driver
231 *
232 * @brief Pointers to the 7 points Laplacian generator functions
233 */
243
244/**
245 * @ingroup spm_dev_driver
246 *
247 * @brief Pointers to the 27 points Laplacian generator functions
248 */
258
259/**
260 *******************************************************************************
261 *
262 * @ingroup spm_dev_driver
263 *
264 * @brief Generate a Laplacian of size spm->n
265 *
266 *******************************************************************************
267 *
268 * @param[in] filename
269 * Configuration string of the Laplacian.
270 * [type:]dim1[:dim2[:dim3]]
271 * type p = pattern only\n"
272 * s = real simple\n"
273 * d = real double [default]\n"
274 * c = complex simple\n"
275 * z = complex double\n"
276 * dim1 size of the first dimension of the 1D|2D|3D laplacian\n"
277 * dim2 size of the second dimension of the 2D|3D laplacian\n"
278 * dim3 size of the third dimension of the 3D laplacian\n"
279 *
280 * @param[inout] spm
281 * At start, an allocated spm structure.
282 * At exit, contains a laplacian matrix in the spm format.
283 *
284 *******************************************************************************
285 *
286 * @retval SPM_SUCCESS if the matrix has been generated successfully
287 * @retval SPM_ERR_BADPARAMETER if the configuration string is incorrect
288 *
289 *******************************************************************************/
290int
291genLaplacian( const char *filename,
292 spmatrix_t *spm )
293{
294 spm_coeftype_t flttype;
295 spm_int_t dim1, dim2, dim3, dof;
296 double alpha = 1.;
297 double beta = 1.;
298 int rc;
299
300 rc = spmParseLaplacianInfo( filename, &flttype, &dim1, &dim2, &dim3, &alpha, &beta, &dof );
301 if (rc != SPM_SUCCESS)
302 return rc;
303
304 /* Build global SPM */
305 spm->flttype = flttype;
306 spm->gN = dim1 * dim2 * dim3;
307 spm->dof = 1;
308 laplacian_7points[spm->flttype]( spm, dim1, dim2, dim3, alpha, beta );
309
310 /* Update the final values */
312
313 /* Extend the spm values if necessary */
314 if ( dof != 1 ) {
315 spmatrix_t spmtmp;
316 int rc;
317 if ( dof < 1 ) {
318 rc = spmDofExtend( spm, 1, -dof, &spmtmp );
319 }
320 else {
321 rc = spmDofExtend( spm, 0, dof, &spmtmp );
322 }
323 if ( rc != SPM_SUCCESS ) {
324 fprintf( stderr, "Issue while extending the matrix to multi-dof\n" );
325 assert(0);
326 return rc;
327 }
328 spmExit( spm );
329 memcpy( spm, &spmtmp, sizeof(spmatrix_t) );
330 }
331
332 return SPM_SUCCESS;
333}
334
335/**
336 *******************************************************************************
337 *
338 * @ingroup spm_dev_driver
339 *
340 * @brief Generate a extended Laplacian of size spm->n
341 *
342 *******************************************************************************
343 *
344 * @param[in] filename
345 * Configuration string of the Laplacian.
346 * [type:]dim1[:dim2[:dim3]]
347 * type p = pattern only
348 * s = real simple
349 * d = real double [default]
350 * c = complex simple
351 * z = complex double
352 * dim1 size of the first dimension of the 1D|2D|3D laplacian
353 * dim2 size of the second dimension of the 2D|3D laplacian
354 * dim3 size of the third dimension of the 3D laplacian
355 *
356 * @param[inout] spm
357 * At start, an allocated spm structure.
358 * At exit, contains a laplacian matrix in the spm format.
359 *
360 *******************************************************************************
361 *
362 * @retval SPM_SUCCESS if the matrix has been generated successfully
363 * @retval SPM_ERR_BADPARAMETER if the configuration string is incorrect
364 *
365 *******************************************************************************/
366int
367genExtendedLaplacian( const char *filename,
368 spmatrix_t *spm )
369{
370 spm_coeftype_t flttype;
371 spm_int_t dim1, dim2, dim3, dof;
372 double alpha = 1.;
373 double beta = 1.;
374 int rc;
375
376 rc = spmParseLaplacianInfo(filename, &flttype, &dim1, &dim2, &dim3, &alpha, &beta, &dof );
377 if (rc != SPM_SUCCESS)
378 return rc;
379
380 /* Build global SPM */
381 spm->flttype = flttype;
382 spm->gN = dim1 * dim2 * dim3;
383 spm->dof = 1;
384 laplacian_27points[spm->flttype]( spm, dim1, dim2, dim3, alpha, beta );
385
386 /* Update the info with dof if necessary */
388
389 /* Extend the spm values if necessary */
390 if ( dof != 1 ) {
391 spmatrix_t spmtmp;
392 int rc;
393 if ( dof < 1 ) {
394 rc = spmDofExtend( spm, 1, -dof, &spmtmp );
395 }
396 else {
397 rc = spmDofExtend( spm, 0, dof, &spmtmp );
398 }
399 if ( rc != SPM_SUCCESS ) {
400 fprintf( stderr, "Issue while extending the matrix to multi-dof\n" );
401 assert(0);
402 return SPM_ERR_UNKNOWN;
403 }
404 spmExit( spm );
405 memcpy( spm, &spmtmp, sizeof(spmatrix_t) );
406 }
407
408 return SPM_SUCCESS;
409}
void c_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 c_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.
void d_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.
void d_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.
double spm_fixdbl_t
Double datatype that is not converted through precision generator functions.
Definition datatypes.h:150
static spm_int_t spm_imax(spm_int_t a, spm_int_t b)
Internal function to compute max(a,b)
Definition datatypes.h:119
enum spm_coeftype_e spm_coeftype_t
Arithmetic types.
@ SPM_ERR_BADPARAMETER
Definition const.h:89
@ SPM_SUCCESS
Definition const.h:82
@ SPM_ERR_UNKNOWN
Definition const.h:83
@ SpmComplex64
Definition const.h:66
@ SpmDouble
Definition const.h:64
@ SpmFloat
Definition const.h:63
@ SpmComplex32
Definition const.h:65
@ SpmPattern
Definition const.h:62
spm_coeftype_t flttype
Definition spm.h:67
spm_int_t dof
Definition spm.h:82
spm_int_t gN
Definition spm.h:72
int spmParseLaplacianInfo(const char *filename, spm_coeftype_t *flttype, spm_int_t *dim1, spm_int_t *dim2, spm_int_t *dim3, double *alpha, double *beta, spm_int_t *dof)
Parse information given through the filename string to configure the laplacian matrix to generate.
Definition laplacian.c:96
void spmExit(spmatrix_t *spm)
Cleanup the spm structure but do not free the spm pointer.
Definition spm.c:224
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
int spmDofExtend(const spmatrix_t *spm, int type, int dof, spmatrix_t *spm_out)
Generate a random multidof spm from a given spm (with dof=1).
The sparse matrix data structure.
Definition spm.h:64
int genExtendedLaplacian(const char *filename, spmatrix_t *spm)
Generate a extended Laplacian of size spm->n.
Definition laplacian.c:367
static void(* laplacian_7points[6])(spmatrix_t *, spm_int_t, spm_int_t, spm_int_t, spm_fixdbl_t, spm_fixdbl_t)
Pointers to the 7 points Laplacian generator functions.
Definition laplacian.c:234
static void(* laplacian_27points[6])(spmatrix_t *, spm_int_t, spm_int_t, spm_int_t, spm_fixdbl_t, spm_fixdbl_t)
Pointers to the 27 points Laplacian generator functions.
Definition laplacian.c:249
int genLaplacian(const char *filename, spmatrix_t *spm)
Generate a Laplacian of size spm->n.
Definition laplacian.c:291
static void laplacian_usage(void)
Print the usage information to generate correct Laplacian matrices.
Definition laplacian.c:27
void p_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 p_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.
void s_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 s_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.
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.