Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/src/LinearForms.F90
3203 views
1
!/*****************************************************************************/
2
! *
3
! * Elmer, A Finite Element Software for Multiphysical Problems
4
! *
5
! * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
6
! *
7
! * This library is free software; you can redistribute it and/or
8
! * modify it under the terms of the GNU Lesser General Public
9
! * License as published by the Free Software Foundation; either
10
! * version 2.1 of the License, or (at your option) any later version.
11
! *
12
! * This library is distributed in the hope that it will be useful,
13
! * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
! * Lesser General Public License for more details.
16
! *
17
! * You should have received a copy of the GNU Lesser General Public
18
! * License along with this library (in file ../LGPL-2.1); if not, write
19
! * to the Free Software Foundation, Inc., 51 Franklin Street,
20
! * Fifth Floor, Boston, MA 02110-1301 USA
21
! *
22
! *****************************************************************************/
23
!
24
!/******************************************************************************
25
! *
26
! * Authors: Mikko Byckling
27
! * Web: http://www.csc.fi/elmer
28
! * Address: CSC - IT Center for Science Ltd.
29
! * Keilaranta 14
30
! * 02101 Espoo, Finland
31
! *
32
! * Original Date: 31 May 2017
33
! *
34
! *****************************************************************************/
35
36
!> \ingroup ElmerLib
37
!> \{
38
39
!-----------------------------------------------------------------------------
40
!> Module defining vectorized operations on common (bi)linear forms.
41
!-----------------------------------------------------------------------------
42
43
44
#include "../config.h"
45
46
MODULE LinearForms
47
USE Types, ONLY: dp, VECTOR_BLOCK_LENGTH, VECTOR_SMALL_THRESH
48
USE Messages
49
IMPLICIT NONE
50
PRIVATE
51
52
INTERFACE LinearForms_ProjectToU
53
MODULE PROCEDURE LinearForms_ProjectToU_rank1, LinearForms_ProjectToU_rankn
54
END INTERFACE LinearForms_ProjectToU
55
56
PUBLIC LinearForms_GradUdotGradU, LinearForms_UdotU, LinearForms_GradUdotU, &
57
LinearForms_UdotF, LinearForms_ProjectToU, LinearForms_UdotV
58
CONTAINS
59
60
! Compute bilinear form G=G+(alpha grad u, grad u) = grad u .dot. (alpha grad u)
61
SUBROUTINE LinearForms_GradUdotGradU(m, n, dim, GradU, weight, G, alpha)
62
IMPLICIT NONE
63
64
INTEGER, INTENT(IN) :: m, n, dim
65
REAL(KIND=dp) CONTIG, INTENT(IN) :: GradU(:,:,:), weight(:)
66
REAL(KIND=dp) CONTIG, INTENT(INOUT) :: G(:,:)
67
REAL(KIND=dp) CONTIG, INTENT(IN), OPTIONAL :: alpha(:)
68
69
REAL(KIND=dp) :: wrk(VECTOR_BLOCK_LENGTH,n)
70
INTEGER :: i, ii, iin, j, l, k, kk, ldbasis, ldwrk, ldk, blklen
71
LOGICAL :: noAlphaWeight
72
!DIR$ ATTRIBUTES ALIGN:64::wrk
73
74
ldbasis = SIZE(GradU,1)
75
ldwrk = SIZE(wrk,1)
76
ldk = SIZE(G,1)
77
78
noAlphaWeight = .TRUE.
79
IF (PRESENT(alpha)) noAlphaWeight = .FALSE.
80
81
DO ii=1,m,VECTOR_BLOCK_LENGTH
82
iin=MIN(ii+VECTOR_BLOCK_LENGTH-1,m)
83
blklen=iin-ii+1
84
85
IF (blklen < VECTOR_SMALL_THRESH) THEN
86
! Do not attempt to call BLAS for small cases to avoid preprocessing overhead
87
IF (noAlphaWeight) THEN
88
DO j=1,n
89
!_ELMER_OMP_SIMD PRIVATE(l,k)
90
DO i=1,n
91
!DIR$ LOOP COUNT MAX=3
92
!DIR$ UNROLL
93
DO k=1,dim
94
DO l=ii,iin
95
G(i,j) = G(i,j) + GradU(l,i,k)*GradU(l,j,k)*weight(l)
96
END DO
97
END DO
98
END DO
99
END DO
100
ELSE
101
DO j=1,n
102
!_ELMER_OMP_SIMD PRIVATE(l,k)
103
DO i=1,n
104
!DIR$ LOOP COUNT MAX=3
105
!DIR$ UNROLL
106
DO k=1,dim
107
DO l=ii,iin
108
G(i,j) = G(i,j) + GradU(l,i,k)*GradU(l,j,k)*weight(l)*alpha(l)
109
END DO
110
END DO
111
END DO
112
END DO
113
END IF
114
ELSE
115
DO k=1, dim
116
IF (noAlphaWeight) THEN
117
DO j=1,n
118
!_ELMER_OMP_SIMD
119
DO i=ii,iin
120
wrk(i-ii+1,j)=weight(i)*GradU(i,j,k)
121
END DO
122
END DO
123
ELSE
124
DO j=1,n
125
!_ELMER_OMP_SIMD
126
DO i=ii,iin
127
wrk(i-ii+1,j)=weight(i)*alpha(i)*GradU(i,j,k)
128
END DO
129
END DO
130
END IF
131
! Compute matrix \grad u \dot \grad u for dim=k
132
CALL DGEMM('T', 'N', n, n, blklen, &
133
1D0, GradU(ii,1,k), ldbasis, &
134
wrk, ldwrk, 1D0, G, ldk)
135
END DO
136
END IF
137
END DO ! Vector blocks
138
END SUBROUTINE LinearForms_GradUdotGradU
139
140
! Compute bilinear form G=G+(alpha grad u, u) = u .dot. (alpha grad u)
141
SUBROUTINE LinearForms_GradUdotU(m, n, dim, GradU, U, weight, G, alpha, beta)
142
IMPLICIT NONE
143
144
INTEGER, INTENT(IN) :: m, n, dim
145
REAL(KIND=dp) CONTIG, INTENT(IN) :: GradU(:,:,:), U(:,:), weight(:)
146
REAL(KIND=dp) CONTIG, INTENT(INOUT) :: G(:,:)
147
REAL(KIND=dp) CONTIG, INTENT(IN), OPTIONAL :: alpha(:), beta(:,:)
148
149
REAL(KIND=dp) :: wrk(VECTOR_BLOCK_LENGTH,n)
150
INTEGER :: i, ii, iin, j, l, k, kk, lbasis, ldwrk, ldk, blklen
151
LOGICAL :: noAlphaWeight, noBetaWeight
152
!DIR$ ATTRIBUTES ALIGN:64::wrk
153
154
lbasis = SIZE(GradU,1)
155
ldwrk = SIZE(wrk,1)
156
ldk = SIZE(G,1)
157
158
noAlphaWeight = .TRUE.
159
IF (PRESENT(alpha)) noAlphaWeight = .FALSE.
160
noBetaWeight = .TRUE.
161
IF (PRESENT(beta)) noBetaWeight = .FALSE.
162
163
DO ii=1,m,VECTOR_BLOCK_LENGTH
164
iin=MIN(ii+VECTOR_BLOCK_LENGTH-1,m)
165
blklen=iin-ii+1
166
167
IF (blklen < VECTOR_SMALL_THRESH) THEN
168
! Do not attempt to call BLAS for small cases to avoid preprocessing overhead
169
IF (noAlphaWeight .AND. noBetaWeight) THEN
170
DO j=1,n
171
!_ELMER_OMP_SIMD PRIVATE(l,k)
172
DO i=1,n
173
!DIR$ LOOP COUNT MAX=3
174
!DIR$ UNROLL
175
DO k=1,dim
176
DO l=ii,iin
177
G(i,j) = G(i,j) + GradU(l,j,k)*U(l,i)*weight(l)
178
END DO
179
END DO
180
END DO
181
END DO
182
ELSE IF (.NOT. noAlphaWeight .AND. noBetaWeight) THEN
183
DO j=1,n
184
!_ELMER_OMP_SIMD PRIVATE(l,k)
185
DO i=1,n
186
!DIR$ LOOP COUNT MAX=3
187
!DIR$ UNROLL
188
DO k=1,dim
189
DO l=ii,iin
190
G(i,j) = G(i,j) + GradU(l,j,k)*U(l,i)*weight(l)*alpha(l)
191
END DO
192
END DO
193
END DO
194
END DO
195
ELSE IF (noAlphaWeight .AND. .NOT. noBetaWeight) THEN
196
DO j=1,n
197
!_ELMER_OMP_SIMD PRIVATE(l,k)
198
DO i=1,n
199
!DIR$ LOOP COUNT MAX=3
200
!DIR$ UNROLL
201
DO k=1,dim
202
DO l=ii,iin
203
G(i,j) = G(i,j) + GradU(l,j,k)*U(l,i)*weight(l)*beta(l,k)
204
END DO
205
END DO
206
END DO
207
END DO
208
ELSE
209
DO j=1,n
210
!_ELMER_OMP_SIMD PRIVATE(l,k)
211
DO i=1,n
212
!DIR$ LOOP COUNT MAX=3
213
!DIR$ UNROLL
214
DO k=1,dim
215
DO l=ii,iin
216
G(i,j) = G(i,j) + GradU(l,j,k)*U(l,i)*weight(l)*alpha(l)*beta(l,k)
217
END DO
218
END DO
219
END DO
220
END DO
221
END IF
222
ELSE
223
DO k=1, dim
224
IF (noAlphaWeight .AND. noBetaWeight) THEN
225
DO j=1,n
226
!_ELMER_OMP_SIMD
227
DO i=ii,iin
228
wrk(i-ii+1,j)=weight(i)*GradU(i,j,k)
229
END DO
230
END DO
231
ELSE IF (.NOT. noAlphaWeight .AND. noBetaWeight) THEN
232
DO j=1,n
233
!_ELMER_OMP_SIMD
234
DO i=ii,iin
235
wrk(i-ii+1,j)=weight(i)*alpha(i)*GradU(i,j,k)
236
END DO
237
END DO
238
ELSE IF (noAlphaWeight .AND. .NOT. noBetaWeight) THEN
239
DO j=1,n
240
!_ELMER_OMP_SIMD
241
DO i=ii,iin
242
wrk(i-ii+1,j)=weight(i)*beta(i,k)*GradU(i,j,k)
243
END DO
244
END DO
245
ELSE
246
DO j=1,n
247
!_ELMER_OMP_SIMD
248
DO i=ii,iin
249
wrk(i-ii+1,j)=weight(i)*alpha(i)*beta(i,k)*GradU(i,j,k)
250
END DO
251
END DO
252
END IF
253
! Compute matrix \grad u \dot u for dim=k
254
CALL DGEMM('T', 'N', n, n, blklen, &
255
1D0, U(ii,1), lbasis, &
256
wrk, ldwrk, 1D0, G, ldk)
257
END DO
258
END IF
259
END DO ! Vector blocks
260
END SUBROUTINE LinearForms_GradUdotU
261
262
263
! Compute bilinear form G=G+(alpha u, v), where u and v can be different basis functions
264
SUBROUTINE LinearForms_UdotV(m, n, dim, U, V, weight, G, alpha)
265
IMPLICIT NONE
266
267
INTEGER, INTENT(IN) :: m, n, dim
268
REAL(KIND=dp) CONTIG, INTENT(IN) :: U(:,:), V(:,:), weight(:)
269
REAL(KIND=dp) CONTIG, INTENT(INOUT) :: G(:,:)
270
REAL(KIND=dp) CONTIG, INTENT(IN), OPTIONAL :: alpha(:)
271
272
REAL(KIND=dp) :: wrk(VECTOR_BLOCK_LENGTH,n)
273
INTEGER :: i, ii, iin, j, l, ldbasis, ldwrk, ldk, blklen
274
LOGICAL :: noAlphaWeight
275
!DIR$ ATTRIBUTES ALIGN:64::wrk
276
277
ldbasis = SIZE(U,1)
278
ldwrk = SIZE(wrk,1)
279
ldk = SIZE(G,1)
280
281
noAlphaWeight = .TRUE.
282
IF (PRESENT(alpha)) noAlphaWeight = .FALSE.
283
284
DO ii=1,m,VECTOR_BLOCK_LENGTH
285
iin=MIN(ii+VECTOR_BLOCK_LENGTH-1,m)
286
blklen=iin-ii+1
287
288
IF (blklen < VECTOR_SMALL_THRESH) THEN
289
! Do not attempt to call BLAS for small cases to avoid preprocessing overhead
290
IF (noAlphaWeight) THEN
291
DO j=1,n
292
!PRIVATE(l)
293
DO i=1,n
294
!DIR$ LOOP COUNT MAX=3
295
DO l=ii,iin
296
G(i,j) = G(i,j) + U(l,i)*V(l,j)*weight(l)
297
END DO
298
END DO
299
END DO
300
ELSE
301
DO j=1,n
302
!_ELMER_OMP_SIMD PRIVATE(l)
303
DO i=1,n
304
!DIR$ LOOP COUNT MAX=3
305
DO l=ii,iin
306
G(i,j) = G(i,j) + U(l,i)*V(l,j)*weight(l)*alpha(l)
307
END DO
308
END DO
309
END DO
310
END IF
311
ELSE
312
IF (noAlphaWeight) THEN
313
DO j=1,n
314
!_ELMER_OMP_SIMD
315
DO i=ii,iin
316
wrk(i-ii+1,j)=weight(i)*V(i,j)
317
END DO
318
END DO
319
ELSE
320
DO j=1,n
321
!_ELMER_OMP_SIMD
322
DO i=ii,iin
323
wrk(i-ii+1,j)=weight(i)*alpha(i)*V(i,j)
324
END DO
325
END DO
326
END IF
327
! Compute matrix u \dot u
328
CALL DGEMM('T', 'N', n, n, blklen, &
329
1D0, U(ii,1), ldbasis, &
330
wrk, ldwrk, 1D0, G, ldk)
331
END IF
332
END DO ! Vector blocks
333
END SUBROUTINE LinearForms_UdotV
334
335
! Compute bilinear form G=G+(alpha u, u) = u .dot. (grad u)
336
SUBROUTINE LinearForms_UdotU(m, n, dim, U, weight, G, alpha)
337
IMPLICIT NONE
338
339
INTEGER, INTENT(IN) :: m, n, dim
340
REAL(KIND=dp) CONTIG, INTENT(IN) :: U(:,:), weight(:)
341
REAL(KIND=dp) CONTIG, INTENT(INOUT) :: G(:,:)
342
REAL(KIND=dp) CONTIG, INTENT(IN), OPTIONAL :: alpha(:)
343
344
REAL(KIND=dp) :: wrk(VECTOR_BLOCK_LENGTH,n)
345
INTEGER :: i, ii, iin, j, l, ldbasis, ldwrk, ldk, blklen
346
LOGICAL :: noAlphaWeight
347
!DIR$ ATTRIBUTES ALIGN:64::wrk
348
349
ldbasis = SIZE(U,1)
350
ldwrk = SIZE(wrk,1)
351
ldk = SIZE(G,1)
352
353
noAlphaWeight = .TRUE.
354
IF (PRESENT(alpha)) noAlphaWeight = .FALSE.
355
356
DO ii=1,m,VECTOR_BLOCK_LENGTH
357
iin=MIN(ii+VECTOR_BLOCK_LENGTH-1,m)
358
blklen=iin-ii+1
359
360
IF (blklen < VECTOR_SMALL_THRESH) THEN
361
! Do not attempt to call BLAS for small cases to avoid preprocessing overhead
362
IF (noAlphaWeight) THEN
363
DO j=1,n
364
!_ELMER_OMP_SIMD PRIVATE(l)
365
DO i=1,n
366
!DIR$ LOOP COUNT MAX=3
367
DO l=ii,iin
368
G(i,j) = G(i,j) + U(l,i)*U(l,j)*weight(l)
369
END DO
370
END DO
371
END DO
372
ELSE
373
DO j=1,n
374
!_ELMER_OMP_SIMD PRIVATE(l)
375
DO i=1,n
376
!DIR$ LOOP COUNT MAX=3
377
DO l=ii,iin
378
G(i,j) = G(i,j) + U(l,i)*U(l,j)*weight(l)*alpha(l)
379
END DO
380
END DO
381
END DO
382
END IF
383
ELSE
384
IF (noAlphaWeight) THEN
385
DO j=1,n
386
!_ELMER_OMP_SIMD
387
DO i=ii,iin
388
wrk(i-ii+1,j)=weight(i)*U(i,j)
389
END DO
390
END DO
391
ELSE
392
DO j=1,n
393
!_ELMER_OMP_SIMD
394
DO i=ii,iin
395
wrk(i-ii+1,j)=weight(i)*alpha(i)*U(i,j)
396
END DO
397
END DO
398
END IF
399
! Compute matrix u \dot u
400
CALL DGEMM('T', 'N', n, n, blklen, &
401
1D0, U(ii,1), ldbasis, &
402
wrk, ldwrk, 1D0, G, ldk)
403
END IF
404
END DO ! Vector blocks
405
END SUBROUTINE LinearForms_UdotU
406
407
SUBROUTINE LinearForms_ProjectToU_rank1(m, n, U, F, ProjectToU)
408
IMPLICIT NONE
409
410
INTEGER, INTENT(IN) :: m, n
411
REAL(KIND=dp) CONTIG, INTENT(IN) :: U(:,:), F(:)
412
REAL(KIND=dp) CONTIG, INTENT(INOUT) :: ProjectToU(:)
413
414
CALL DGEMV('N', m, n, 1D0, U, SIZE(U,1), F, 1, 0D0, ProjectToU, 1)
415
END SUBROUTINE LinearForms_ProjectToU_rank1
416
417
SUBROUTINE LinearForms_ProjectToU_rankn(m, n, U, F, ProjectToU)
418
IMPLICIT NONE
419
420
INTEGER, INTENT(IN) :: m, n
421
REAL(KIND=dp) CONTIG, INTENT(IN) :: U(:,:), F(:,:)
422
REAL(KIND=dp) CONTIG, INTENT(INOUT) :: ProjectToU(:,:)
423
424
CALL DGEMM('N', 'N', m, SIZE(F,2), n, 1D0, U, SIZE(U,1), F, SIZE(F,1), &
425
0D0, ProjectToU, SIZE(ProjectToU,1))
426
END SUBROUTINE LinearForms_ProjectToU_rankn
427
428
! Compute linear form UdotF=UdotF+(u,f)
429
SUBROUTINE LinearForms_UdotF(m, n, U, weight, F, UdotF, alpha)
430
IMPLICIT NONE
431
432
INTEGER, INTENT(IN) :: m, n
433
REAL(KIND=dp) CONTIG, INTENT(IN) :: U(:,:), F(:), weight(:)
434
REAL(KIND=dp) CONTIG, INTENT(INOUT) :: UdotF(:)
435
REAL(KIND=dp) CONTIG, INTENT(IN), OPTIONAL :: alpha(:)
436
437
REAL(KIND=dp) :: wrk(VECTOR_BLOCK_LENGTH)
438
INTEGER :: i, ii, iin, j, blklen, l
439
LOGICAL :: noAlphaWeight
440
!DIR$ ATTRIBUTES ALIGN:64::wrk
441
442
noAlphaWeight = .TRUE.
443
IF (PRESENT(alpha)) noAlphaWeight = .FALSE.
444
445
DO ii=1,m,VECTOR_BLOCK_LENGTH
446
iin = MIN(ii+VECTOR_BLOCK_LENGTH-1,m)
447
blklen= iin-ii+1
448
! Project local F to global basis
449
450
IF (blklen < VECTOR_SMALL_THRESH) THEN
451
IF (noAlphaWeight) THEN
452
!_ELMER_OMP_SIMD PRIVATE(l)
453
DO i=1,n
454
DO l=ii,iin
455
UdotF(i) = UdotF(i) + U(l,i)*F(l)*weight(l)
456
END DO
457
END DO
458
ELSE
459
!_ELMER_OMP_SIMD PRIVATE(l)
460
DO i=1,n
461
DO l=ii,iin
462
UdotF(i) = UdotF(i) + U(l,i)*F(l)*weight(l)*alpha(l)
463
END DO
464
END DO
465
END IF
466
ELSE
467
IF (noAlphaWeight) THEN
468
!_ELMER_OMP_SIMD
469
DO i=ii,iin
470
wrk(i-ii+1) = weight(i)*F(i)
471
END DO
472
ELSE
473
!_ELMER_OMP_SIMD
474
DO i=ii,iin
475
wrk(i-ii+1) = weight(i)*F(i)*alpha(i)
476
END DO
477
END IF
478
479
CALL DGEMV('T', blklen, n, &
480
1D0, U(ii,1), SIZE(U,1), wrk, 1, 1D0, UdotF, 1)
481
END IF
482
END DO
483
END SUBROUTINE LinearForms_UdotF
484
485
END MODULE LinearForms
486
487