Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_lobalap.F90
Go to the documentation of this file.
1 ! module pour gérer et résoudre le laplacien sur un domaine
2 ! difféomorphe à un carré
3 ! la solution est le potentiel: phi
4 ! le terme source est la charge: rho
5 ! conditions aux limites de Dirichlet données par la fonction
6 ! "potexact"
8 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 #include "sll_working_precision.h"
10 
11  use sll_m_map_function, only: &
12  sll_s_map
13 
14  implicit none
15 
16  public :: &
17  sll_s_assemb, &
22  sll_s_init, &
25 
26  private
27 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
28  ! ordre de l'interpolation élément fini
29  integer :: order
30  ! nombre de noeuds locaux dans chaque élément
31  integer :: nloc
32 
33  ! tableaux pour intégration de Gauss-Lobatto
34  ! points et poids
35  sll_real64, dimension(:), allocatable :: xpg, wpg
36  ! dérivées des polynômes de Lagrange aux points de gauss
37  sll_real64, dimension(:, :), allocatable :: dlag
38 
39  ! variable pour vérifier que les initialisations ont eu lieu
40  logical :: is_init = .false.
41 
42  ! nombre d'éléments en x et en y
43  integer :: nx, ny
44  ! nombre d'éléments
45  integer :: nel
46  ! nombre d'inconnues en x, en y, en tout
47  integer :: neqx, neqy, neq
48  ! nombre de conditions de bord
49  integer :: nbc
50 
51  ! noeuds du maillage
52  sll_real64, dimension(:, :), allocatable :: node
53  ! connectivité
54  integer, dimension(:, :), allocatable :: connec
55 
56  ! tableaux pour le stockage morse de la matrice
57  ! indices de ligne et de colonne des valeurs non nulles
58  !integer,dimension(:),allocatable :: icol,irow
59  ! valeurs correspondantes de la matrice
60  !sll_real64,dimension(:),allocatable :: matval
61 
62  ! tableaux pour le stockage skyline de la matrice
63  ! profil, début des colonnes
64  integer, dimension(:), allocatable :: prof, kld
65  sll_real64, dimension(:), allocatable :: vdiag, vsup, vinf
66  ! taille de ces tableaux
67  integer :: nsky
68  ! grand pivot pour les cl
69  sll_real64, parameter :: big = 1.e20_f64
70 
71  ! vecteur pour le second membre et la solution
72  sll_real64, dimension(:), allocatable :: phi, rho
73 
74  ! liste des noeuds du bord
75  integer, dimension(:), allocatable :: indexbc
76 
77 contains
78 
79  ! fonction donnant le potentiel exact (debug) et/ou les conditions aux limites
80  function potexact(x, y)
81  implicit none
82  sll_real64, intent(in) :: x, y
83  sll_real64 :: potexact
84  !potexact=x*x+y*y
85  potexact = 0.0_f64 + x - x + y - y
86  end function potexact
87 
88  ! fonction donnant le terme source
89  function source(x, y)
90  implicit none
91  sll_real64, intent(in) :: x, y
92  sll_real64 :: source
93  source = -4.0_f64 + x - x + y - y
94  end function source
95 
96  ! fonction qui envoie le carré [0,1]x[0,1] sur le vrai domaine de calcul
97  ! variables de référence: (u,v)
98  ! variables physiques: (x,y)
99  ! autres données calculées:
100  ! jac, invjac, det: jacobienne, son inverse et déterminant de la jacobienne
101 ! ! subroutine sll_s_map(u,v,x,y,jac,invjac,det)
102 ! ! pour l'instant on n'utilise pas la jacobienne
103 ! subroutine sll_s_map(u,v,x,y)
104 ! implicit none
105 ! sll_real64,intent(in) :: u,v
106 ! sll_real64,intent(out) :: x,y
107 ! sll_real64 :: jac(2,2),invjac(2,2),det
108 ! sll_real64,parameter :: pi=4*atan(1._f64)
109 !
110 ! x=(1+u)*(1+v)*cos(pi*v)
111 ! y=(1+u)*sin(pi*v)
112 !
113 ! x=u
114 ! y=v
115 !
116 ! !x=u
117 ! !y=v
118 ! ! non utilisé
119 ! jac=0
120 ! jac(1,1)=1
121 ! jac(2,2)=1
122 ! invjac=jac
123 ! det=1
124 !
125 ! end subroutine sll_s_map
126 
127  ! remplissage des tableaux de pg
128  ! et de polynômes de Lagrange
129  ! dlag(i,j): dérivé polynôme i au point j
130  subroutine init_gauss()
131  implicit none
132 
133  write (*, *) 'sll_s_init tableaux points de Gauss...'
134 
135  allocate (xpg(order + 1))
136  allocate (wpg(order + 1))
137  allocate (dlag(order + 1, order + 1))
138 
139  select case (order)
140  case (1)
141  xpg(1) = 0.0_f64
142  xpg(2) = 1.0_f64
143  wpg(1) = 0.5_f64
144  wpg(2) = 0.5_f64
145  dlag(1, 1) = -1.0_f64
146  dlag(1, 2) = -1.0_f64
147  dlag(2, 1) = 1.0_f64
148  dlag(2, 2) = 1.0_f64
149 
150  case (2)
151  xpg(1) = 0.0_f64
152  xpg(2) = 0.5_f64
153  xpg(3) = 1.0_f64
154  wpg(1) = 1.0_f64/6.0_f64
155  wpg(2) = 4.0_f64/6.0_f64
156  wpg(3) = 1.0_f64/6.0_f64
157  dlag(1, 1) = -0.300000000000000000000000000000e1_f64
158  dlag(1, 2) = -0.100000000000000000000000000000e1_f64
159  dlag(1, 3) = 0.100000000000000000000000000000e1_f64
160  dlag(2, 1) = 0.400000000000000000000000000000e1_f64
161  dlag(2, 3) = -0.400000000000000000000000000000e1_f64
162  dlag(3, 1) = -0.100000000000000000000000000000e1_f64
163  dlag(3, 2) = 0.100000000000000000000000000000e1_f64
164  dlag(3, 3) = 0.300000000000000000000000000000e1_f64
165  case (3)
166  xpg(1) = 0.0_f64
167  xpg(2) = (1.0_f64 - sqrt(1.0_f64/5.0_f64))/2.0_f64
168  xpg(3) = (1.0_f64 + sqrt(1.0_f64/5.0_f64))/2.0_f64
169  xpg(4) = 1.0_f64
170  wpg(1) = 1.0_f64/12.0_f64
171  wpg(2) = 5.0_f64/12.0_f64
172  wpg(3) = 5.0_f64/12.0_f64
173  wpg(4) = 1.0_f64/12.0_f64
174  dlag(1, 1) = -0.599999999999999999999999999998e1_f64
175  dlag(1, 2) = -0.161803398874989484820458683436e1_f64
176  dlag(1, 3) = 0.618033988749894848204586834362e0_f64
177  dlag(1, 4) = -0.999999999999999999999999999994e0_f64
178  dlag(2, 1) = 0.809016994374947424102293417177e1_f64
179  dlag(2, 2) = -0.1d-28
180  dlag(2, 3) = -0.223606797749978969640917366872e1_f64
181  dlag(2, 4) = 0.309016994374947424102293417184e1_f64
182  dlag(3, 1) = -0.309016994374947424102293417182e1_f64
183  dlag(3, 2) = 0.223606797749978969640917366872e1_f64
184  dlag(3, 3) = 0.1d-28
185  dlag(3, 4) = -0.809016994374947424102293417177e1_f64
186  dlag(4, 1) = 0.999999999999999999999999999994e0_f64
187  dlag(4, 2) = -0.618033988749894848204586834362e0_f64
188  dlag(4, 3) = 0.161803398874989484820458683436e1_f64
189  dlag(4, 4) = 0.599999999999999999999999999998e1_f64
190  case (4)
191  xpg(1) = 0.0_f64
192  xpg(2) = (1.0_f64 - sqrt(3.0_f64/7.0_f64))/2.0_f64
193  xpg(3) = 0.5_f64
194  xpg(4) = (1.0_f64 + sqrt(3.0_f64/7.0_f64))/2.0_f64
195  xpg(5) = 1.0_f64
196  wpg(1) = 1.0_f64/20.0_f64
197  wpg(2) = 49.0_f64/180.0_f64
198  wpg(3) = 32.0_f64/90.0_f64
199  wpg(4) = 49.0_f64/180.0_f64
200  wpg(5) = 1.0_f64/20.0_f64
201  dlag(1, 1) = -0.100000000000000000000000000000e2_f64
202  dlag(1, 2) = -0.248198050606196571569743868439e1_f64
203  dlag(1, 3) = 0.750000000000000000000000000000e0_f64
204  dlag(1, 4) = -0.518019493938034284302561315633e0_f64
205  dlag(1, 5) = 0.100000000000000000000000000002e1_f64
206  dlag(2, 1) = 0.135130049774484800076860550594e2_f64
207  dlag(2, 2) = -0.2e-28_f64
208  dlag(2, 3) = -0.267316915539090667050969419638e1_f64
209  dlag(2, 4) = 0.152752523165194666886268239794e1_f64
210  dlag(2, 5) = -0.282032835588485332564727827395e1_f64
211  dlag(3, 1) = -0.533333333333333333333333333328e1_f64
212  dlag(3, 2) = 0.349148624377587810025755976661e1_f64
213  dlag(3, 3) = 0.2e-28_f64
214  dlag(3, 4) = -0.349148624377587810025755976659e1_f64
215  dlag(3, 5) = 0.533333333333333333333333333332e1_f64
216  dlag(4, 1) = 0.282032835588485332564727827398e1_f64
217  dlag(4, 2) = -0.152752523165194666886268239791e1_f64
218  dlag(4, 3) = 0.267316915539090667050969419635e1_f64
219  dlag(4, 4) = -0.4e-28_f64
220  dlag(4, 5) = -0.135130049774484800076860550595e2_f64
221  dlag(5, 1) = -0.100000000000000000000000000000e1_f64
222  dlag(5, 2) = 0.518019493938034284302561315635e0_f64
223  dlag(5, 3) = -0.750000000000000000000000000006e0_f64
224  dlag(5, 4) = 0.248198050606196571569743868439e1_f64
225  dlag(5, 5) = 0.100000000000000000000000000000e2_f64
226  case default
227  write (*, *) é'pas prvu...'
228  stop
229  end select
230 
231  end subroutine init_gauss
232 
233  ! tracé de la solution avec gmsh
234  subroutine sll_s_plotgmsh()
235  implicit none
236  integer, parameter :: nlocmax = 25
237  integer :: typelem
238  integer, dimension(4) :: invpermut1 = (/1, 2, 4, 3/)
239  integer, dimension(9) :: invpermut2 = (/1, 5, 2, 8, 9, 6, 4, 7, 3/)
240  integer, dimension(16) :: invpermut3 = (/1, 5, 6, 2, 12, 13, 14, 7, 11, 16, 15, 8, 4, 10, 9, 3/)
241  integer :: invpermut(nloc), permut(nloc), i, ii
242 
243  write (*, *) é'Trac gmsh...'
244 
245  if (order .gt. 3) then
246  write (*, *) é'ordre non prvu'
247  stop
248  end if
249 
250  select case (order)
251  case (1)
252  invpermut(1:nloc) = invpermut1
253  typelem = 3
254  case (2)
255  invpermut(1:nloc) = invpermut2
256  typelem = 10
257  case (3)
258  invpermut(1:nloc) = invpermut3
259  typelem = 36
260  case default
261  write (*, *) é'ordre non prvu'
262  stop
263  end select
264 
265  do i = 1, nloc
266  permut(invpermut(i)) = i
267  end do
268 
269  open (101, file='sll_m_lobalap.msh')
270  write (101, '(A)') '$MeshFormat'
271  write (101, '(A)') '2 0 8'
272  write (101, '(A)') '$EndMeshFormat'
273  write (101, '(A)') '$Nodes'
274  write (101, *) neq
275  do i = 1, neq
276  write (101, *) i, node(1, i), node(2, i), 0._f64
277  end do
278  write (101, '(A)') '$EndNodes'
279  write (101, '(A)') '$Elements'
280  write (101, *) nel
281  do i = 1, nel
282  write (101, *) i, typelem, 0, (connec(permut(ii), i), ii=1, nloc)
283  end do
284  write (101, '(A)') '$EndElements'
285  write (101, '(A)') '$NodeData'
286  write (101, *) 1
287  write (101, *) 'PHI'
288  write (101, *) 1
289  write (101, *) 0
290  write (101, *) 3
291  write (101, *) 0
292  write (101, *) 1
293  write (101, *) neq
294  do i = 1, neq
295  write (101, *) i, phi(i) - potexact(node(1, i), node(2, i))
296  end do
297  write (101, '(A)') '$EndNodeData'
298 
299  close (101)
300 
301  end subroutine sll_s_plotgmsh
302 
303  ! construction du maillage
304  subroutine build_mesh()
305  implicit none
306  integer :: iix, ix, iiy, iy, inoloc, ino, iel
307  sll_real64 :: du, dv, u, v, x, y, eps
308 
309  ! construit les tableaux de pg
310  call init_gauss()
311 
312  write (*, *) 'Construction du maillage...'
313  write (*, *) 'Elements:', nel, ' Noeuds:', neq
314  allocate (node(2, neq))
315  allocate (connec(nloc, neq))
316 
317  du = 1._f64/nx
318  dv = 1._f64/ny
319 
320  ! compteur pour les noeuds du bord
321  nbc = 0
322  ! tolérance
323  eps = 1.0e-12_f64
324 
325  ! construit la connectivité éléments --> noeuds
326  ! boucle sur les éléments
327  do ix = 0, nx - 1
328  do iy = 0, ny - 1
329  iel = 1 + ix + iy*nx
330  !boucle sur les noeuds de l'éléments
331  do iix = 0, order
332  do iiy = 0, order
333  ! numéro local dans l'élément
334  inoloc = 1 + iix + (order + 1)*iiy
335  ! numéro global dans le maillage
336  ino = 1 + iix + order*ix + (order*nx + 1)*(iiy + order*iy)
337  connec(inoloc, iel) = ino
338  ! coordonnées
339  u = ix*du + du*xpg(iix + 1)
340  v = iy*dv + dv*xpg(iiy + 1)
341  node(1, ino) = u
342  node(2, ino) = v
343  end do
344  end do
345  end do
346  end do
347  write (*, *) " ino = ", ino
348 
349  write (*, *) é'Reprage noeuds du bord'
350 
351  ! repère les noeuds du bord
352  ! première passe pour compter
353  do ino = 1, neq
354  u = node(1, ino)
355  v = node(2, ino)
356  if (abs(u*(1 - u)*v*(1 - v)) .lt. eps) nbc = nbc + 1
357  end do
358 
359  allocate (indexbc(nbc))
360 
361  ! deuxième passe pour remplir
362  ! et calculer les coords physiques
363  ! des noeuds
364  nbc = 0
365  do ino = 1, neq
366  u = node(1, ino)
367  v = node(2, ino)
368  if (abs(u*(1 - u)*v*(1 - v)) .lt. eps) then
369  nbc = nbc + 1
370  indexbc(nbc) = ino
371  end if
372  call sll_s_map(u, v, x, y)
373  node(1, ino) = x
374  node(2, ino) = y
375  end do
376 
377 !!$ write(*,*) 'Points de bord: ',nbc
378 !!$ do ino=1,nbc
379 !!$ write(*,*) indexbc(ino)
380 !!$ end do
381 
382  end subroutine build_mesh
383 
384  ! alloue et prépare les données pour le calcul
385  subroutine sll_s_init(nx0, ny0, order0)
386  implicit none
387  integer, intent(in) :: nx0, ny0, order0
388  integer :: ino, iel, i, ii, j, jj
389  nx = nx0
390  ny = ny0
391  order = order0
392  nloc = (order + 1)*(order + 1)
393  is_init = .true.
394 
395  ! nombre d'inconnues
396  neqx = nx*order + 1
397  neqy = ny*order + 1
398  neq = neqx*neqy
399  nel = nx*ny
400 
401  ! construction du maillage
402  ! et des listes de conditions aux limites
403  call build_mesh()
404 
405  write (*, *) 'Allocation solution et source...'
406 
407  ! allocation solution et source
408  allocate (phi(neq))
409  allocate (rho(neq))
410 
411  ! une solution bidon pour tester la visu
412  do ino = 1, neq
413  phi(ino) = potexact(node(1, ino), node(2, ino))
414  end do
415 
416  ! initialisation du second pour l'assemblage
417  rho = 0.0_f64
418 
419  write (*, *) 'Calcul structure matrice creuse...'
420 
421  ! préparation de la matrice skyline
422  allocate (prof(neq))
423  allocate (kld(neq + 1))
424 
425  ! construction du profil
426  prof = 0
427  do iel = 1, nel
428  do ii = 1, nloc
429  do jj = 1, nloc
430  i = connec(ii, iel)
431  j = connec(jj, iel)
432  prof(j) = max(prof(j), j - i)
433  prof(i) = max(prof(i), i - j)
434  end do
435  end do
436  end do
437  ! tableau des débuts de colonnes
438  kld(1) = 1
439  do i = 1, neq
440  kld(i + 1) = kld(i) + prof(i)
441  end do
442 
443  nsky = kld(neq + 1) - 1
444 
445  allocate (vdiag(neq))
446  allocate (vinf(nsky))
447  allocate (vsup(nsky))
448 
449  vdiag = 0.0_f64
450  vinf = 0.0_f64
451  vsup = 0.0_f64
452 
453  end subroutine sll_s_init
454 
455  ! symbole de kronecker delta
456  function delta(i, j)
457  implicit none
458  integer :: i, j
459  sll_real64 :: delta
460  if (i .eq. j) then
461  delta = 1.0_f64
462  else
463  delta = 0.0_f64
464  end if
465  end function delta
466 
467  ! gradient de la fonction de base iloc au point de gauss ipg
468  ! sur l'élément de référence dans les variables de référence
469  ! on utilise le fait que les fonctions de base sont des produits
470  ! tensoriels de polynômes de Lagrange associés aux
471  ! point de Guass-Lobatto
472  subroutine gradpg(iloc, ipg, grad, poids)
473  implicit none
474  integer, intent(in) :: iloc, ipg
475  sll_real64, intent(out) :: grad(2), poids
476  integer :: ilocx, ilocy, ipgx, ipgy
477  ! indices locaux du pg
478  ! dans les directions de référence
479  ipgx = mod(ipg - 1, order + 1) + 1
480  ipgy = (ipg - 1)/(order + 1) + 1
481 
482  ! indices de la fonction de base
483  ! suivant u et v dans l'élément de référence
484  ilocx = mod(iloc - 1, order + 1) + 1
485  ilocy = (iloc - 1)/(order + 1) + 1
486 
487  ! gradient de la fonction de base au pg
488  ! dans les variables de référence
489  grad(1) = dlag(ilocx, ipgx)*delta(ilocy, ipgy)
490  grad(2) = dlag(ilocy, ipgy)*delta(ilocx, ipgx)
491 
492  poids = wpg(ipgx)*wpg(ipgy)
493 
494  end subroutine gradpg
495 
496  ! calcul du champ électrique
497  subroutine sll_s_compute_electric_field(dg_ex, dg_ey)
498  implicit none
499  ! matrice locale
500  sll_real64 :: jac(2, 2), cojac(2, 2), det
501  sll_real64 :: gradref(2), xg, yg
502  sll_real64 :: grad(2), dxy(2), poids
503  integer :: iel, ipg, ii, jj, ig, ib, iib, ielx, iely
504  sll_real64, dimension(order + 1, order + 1, nx, ny) :: dg_ex, dg_ey
505 
506  ! assemblage de la matrice de rigidité
507  ! et du second membre
508 
509  write (*, *) éé'Calcul champ lectrique...'
510 
511  dg_ex = 0.0_f64
512  dg_ey = 0.0_f64
513 
514  ! boucle sur les éléments
515  do iel = 1, nel
516  ! boucle sur les pg pour le calcul du champ
517  ielx = mod(iel - 1, nx) + 1
518  iely = (iel - 1)/nx + 1
519  do ipg = 1, nloc
520  ! numéros locaux du pg
521  ii = mod(ipg - 1, order + 1) + 1
522  jj = (ipg - 1)/(order + 1) + 1
523  ! numéro global du pg
524  ig = connec(ipg, iel)
525  xg = node(1, ig)
526  yg = node(2, ig)
527  ! calcul de la jacobienne au pg
528  ! on pourra le faire directement avec sll_s_map plus tard
529  jac = 0.0_f64
530  ! boucle sur les fonctions de base d'interpolation
531  ! pour construire la jacobienne de la transformation
532  ! géométrique
533  do iib = 1, nloc
534  ! gradient de la fonction de base au pg
535  ! dans les variables de référence
536  ! calcul du poids de gauss
537  call gradpg(iib, ipg, dxy, poids)
538  ib = connec(iib, iel)
539  ! contribution à la jacobienne
540  jac(1, 1) = jac(1, 1) + node(1, ib)*dxy(1)
541  jac(1, 2) = jac(1, 2) + node(1, ib)*dxy(2)
542  jac(2, 1) = jac(2, 1) + node(2, ib)*dxy(1)
543  jac(2, 2) = jac(2, 2) + node(2, ib)*dxy(2)
544  end do
545  !write(*,*) ipg,jac
546  ! déterminant et transposée de l'inverse
547  det = jac(1, 1)*jac(2, 2) - jac(1, 2)*jac(2, 1)
548  cojac(1, 1) = jac(2, 2)/det
549  cojac(2, 2) = jac(1, 1)/det
550  cojac(1, 2) = -jac(2, 1)/det
551  cojac(2, 1) = -jac(1, 2)/det
552 
553  ! nouvelle boucle sur les noeuds locaux de l'élément iel
554  ! pour calculer le gradient du potentiel
555  do iib = 1, nloc
556  ! gradients dans les variables de référence
557  call gradpg(iib, ipg, gradref, poids)
558  ib = connec(iib, iel)
559  grad = matmul(cojac, gradref)
560  dg_ex(ii, jj, ielx, iely) = dg_ex(ii, jj, ielx, iely) + phi(ib)*grad(1)
561  dg_ey(ii, jj, ielx, iely) = dg_ey(ii, jj, ielx, iely) + phi(ib)*grad(2)
562  end do
563  end do
564  end do
565 
566  end subroutine sll_s_compute_electric_field
567 
568  ! assemblage de la matrice élément fini et des conditions aux limites
569  subroutine sll_s_assemb()
570  implicit none
571  ! matrice locale
572  sll_real64 :: jac(2, 2), cojac(2, 2), det
573  sll_real64 :: gradref_i(2), gradref_j(2), xg, yg
574  sll_real64 :: grad_i(2), grad_j(2), dxy(2), v, poids, vf
575  integer :: iel, ipg, i, ii, j, jj, ig, ib, iib
576 
577  ! assemblage de la matrice de rigidité
578  ! et du second membre
579 
580  write (*, *) 'Assemblage matrice...'
581 
582  ! boucle sur les éléments
583  do iel = 1, nel
584  ! boucle sur les pg pour intégrer
585  do ipg = 1, nloc
586  ! numéro global du pg
587  ig = connec(ipg, iel)
588  ! coordonnées du pg
589  xg = node(1, ig)
590  yg = node(2, ig)
591  ! on calcule la charge au point de Gauss
592  vf = source(xg, yg)
593  ! calcul de la jacobienne au pg
594  ! on pourra le faire directement avec sll_s_map plus tard
595  jac = 0.0_f64
596  ! boucle sur les fonctions de base d'interpolation
597  ! pour construire la jacobienne de la transformation
598  ! géométrique
599  do iib = 1, nloc
600  ! gradient de la fonction de base au pg
601  ! dans les variables de référence
602  ! calcul du poids de gauss
603  call gradpg(iib, ipg, dxy, poids)
604  ib = connec(iib, iel)
605  ! contribution à la jacobienne
606  jac(1, 1) = jac(1, 1) + node(1, ib)*dxy(1)
607  jac(1, 2) = jac(1, 2) + node(1, ib)*dxy(2)
608  jac(2, 1) = jac(2, 1) + node(2, ib)*dxy(1)
609  jac(2, 2) = jac(2, 2) + node(2, ib)*dxy(2)
610  end do
611  !write(*,*) ipg,jac
612  ! déterminant et transposée de l'inverse
613  det = jac(1, 1)*jac(2, 2) - jac(1, 2)*jac(2, 1)
614  cojac(1, 1) = jac(2, 2)/det
615  cojac(2, 2) = jac(1, 1)/det
616  cojac(1, 2) = -jac(2, 1)/det
617  cojac(2, 1) = -jac(1, 2)/det
618 
619  ! assemblage du second membre
620  !rho(ig)=rho(ig)+vf*det*poids
621 
622  ! nouvelle boucle sur les noeuds locaux de l'élément iel
623  ! pour calculer la matrice élémentaire
624  do ii = 1, nloc
625  ! gradients dans les variables de référence
626  call gradpg(ii, ipg, gradref_i, poids)
627  ! gradient dans les variables physiques
628  grad_i = matmul(cojac, gradref_i)
629  ! gradient
630  ! indice global
631  i = connec(ii, iel)
632  do jj = 1, nloc
633  call gradpg(jj, ipg, gradref_j, poids)
634  j = connec(jj, iel)
635  ! gradient dans les variables physiques
636  grad_j = matmul(cojac, gradref_j)
637  ! produit scalaire gradi . gradj
638  v = (grad_i(1)*grad_j(1) + grad_i(2)*grad_j(2))*det*poids
639  call add(v, i, j)
640  end do
641  end do
642  end do
643  end do
644 
645  write (*, *) 'Assemblage conditions aux limites matrice...'
646 
647  ! assemblage des conditions aux limites de dirichlet
648  ! par pénalisation
649  do ii = 1, nbc
650  i = indexbc(ii)
651  call add(big, i, i)
652  end do
653 
654  end subroutine sll_s_assemb
655 
656  ! assemblage du second membre
657  subroutine sll_s_assemb_rhs(dg_rho)
658  implicit none
659  ! matrice locale
660  sll_real64 :: jac(2, 2), det
661  sll_real64 :: dxy(2), poids, vf
662  sll_real64, dimension(order + 1, order + 1, nx, ny) :: dg_rho
663  integer :: iel, ipg, i, ii, jj, ig, ib, iib, ielx, iely
664 
665  ! assemblage de la matrice de rigidité
666  ! et du second membre
667 
668  write (*, *) 'Assemblage second membre...'
669 
670  rho = 0.0_f64
671 
672  ! boucle sur les éléments
673  do iel = 1, nel
674  ielx = mod(iel - 1, nx) + 1
675  iely = (iel - 1)/nx + 1
676  ! boucle sur les pg pour intégrer
677  do ipg = 1, nloc
678  ! numéro global du pg
679  ig = connec(ipg, iel)
680 
681  ! on récupère la charge au point de Gauss
682  ii = mod(ipg - 1, order + 1) + 1
683  jj = (ipg - 1)/(order + 1) + 1
684 
685  vf = dg_rho(ii, jj, ielx, iely)
686  !write(*,*) 'vf=',vf
687 
688  ! calcul de la jacobienne au pg
689  ! on pourra le faire directement avec sll_s_map plus tard
690  jac = 0.0_f64
691  ! boucle sur les fonctions de base d'interpolation
692  ! pour construire la jacobienne de la transformation
693  ! géométrique
694  do iib = 1, nloc
695  ! gradient de la fonction de base au pg
696  ! dans les variables de référence
697  ! calcul du poids de gauss
698  call gradpg(iib, ipg, dxy, poids)
699  ib = connec(iib, iel)
700  ! contribution à la jacobienne
701  jac(1, 1) = jac(1, 1) + node(1, ib)*dxy(1)
702  jac(1, 2) = jac(1, 2) + node(1, ib)*dxy(2)
703  jac(2, 1) = jac(2, 1) + node(2, ib)*dxy(1)
704  jac(2, 2) = jac(2, 2) + node(2, ib)*dxy(2)
705  end do
706  !write(*,*) ipg,jac
707  ! déterminant et transposée de l'inverse
708  det = jac(1, 1)*jac(2, 2) - jac(1, 2)*jac(2, 1)
709 !!$ cojac(1,1)=jac(2,2)/det
710 !!$ cojac(2,2)=jac(1,1)/det
711 !!$ cojac(1,2)=-jac(2,1)/det
712 !!$ cojac(2,1)=-jac(1,2)/det
713 
714  ! assemblage du second membre
715  rho(ig) = rho(ig) + vf*det*poids
716  end do
717  end do
718 
719  write (*, *) 'Assemblage conditions aux limites rhs...'
720 
721  ! assemblage des conditions aux limites de dirichlet
722  ! par pénalisation
723  do ii = 1, nbc
724  i = indexbc(ii)
725  rho(i) = potexact(node(1, i), node(2, i))*big
726  !rho(i)=0
727  end do
728 
729  end subroutine sll_s_assemb_rhs
730 
731  ! compute (in place) the LU decomposition
732  subroutine sll_s_computelu()
733  implicit none
734 
735  integer :: nsym = 1, mp = 6, ifac = 1, isol = 0, ier
736  sll_real64 :: energ, vu(1), vfg(1)
737 
738  write (*, *) 'Factorisation LU...'
739 
740  call sol(vsup, vdiag, vinf, &
741  vfg, kld, vu, neq, mp, ifac, isol, &
742  nsym, energ, ier, nsky)
743  end subroutine sll_s_computelu
744 
745  ! résout le système linéaire
746  subroutine sll_s_compute_phi()
747  implicit none
748 
749  integer :: nsym = 1, mp = 6, ifac = 0, isol = 1, ier
750  sll_real64 :: energ !,solution(neq),rhs(neq)
751 
752  write (*, *) é'Rsolution...'
753 
754  call sol(vsup, vdiag, vinf, &
755  rho, kld, phi, neq, mp, ifac, isol, &
756  nsym, energ, ier, nsky)
757 
758  end subroutine sll_s_compute_phi
759 
760  ! ajoute la valeur val à la position (i,j)
761  ! dans la matrice ligne de ciel
762  subroutine add(val, i, j)
763  implicit none
764  integer, intent(in) :: i, j
765  integer :: ll
766  sll_real64, intent(in) :: val
767 
768  if (i - j .gt. prof(i) .or. j - i .gt. prof(j)) then
769  write (*, *) '(', i, ',', j, ') out of matrix profile'
770  write (*, *) prof(i)
771  write (*, *) prof(j)
772  stop
773  end if
774  if (i .eq. j) then
775  vdiag(i) = vdiag(i) + val
776  else if (j .gt. i) then
777  ll = kld(j + 1) - j + i
778  vsup(ll) = vsup(ll) + val
779  else
780  ll = kld(i + 1) - i + j
781  vinf(ll) = vinf(ll) + val
782  end if
783 
784  end subroutine add
785 
786  ! libère la mémoire
787  subroutine sll_s_release()
788  implicit none
789 
790  write (*, *) éé'Libration mmoire...'
791 
792  deallocate (xpg)
793  deallocate (wpg)
794  deallocate (dlag)
795  deallocate (node)
796  deallocate (connec)
797  deallocate (indexbc)
798  deallocate (prof)
799  deallocate (kld)
800  deallocate (vdiag)
801  deallocate (vsup)
802  deallocate (vinf)
803  deallocate (phi)
804  deallocate (rho)
805 
806  end subroutine sll_s_release
807 
808 end module sll_m_lobalap
809 
subroutine, public sll_s_assemb()
subroutine, public sll_s_assemb_rhs(dg_rho)
real(kind=f64) function source(x, y)
subroutine, public sll_s_compute_electric_field(dg_ex, dg_ey)
integer, dimension(:), allocatable kld
real(kind=f64), dimension(:), allocatable phi
subroutine add(val, i, j)
subroutine, public sll_s_computelu()
real(kind=f64), dimension(:), allocatable vinf
real(kind=f64) function potexact(x, y)
real(kind=f64) function delta(i, j)
real(kind=f64), dimension(:), allocatable vdiag
integer, dimension(:), allocatable indexbc
real(kind=f64), parameter big
subroutine, public sll_s_release()
subroutine init_gauss()
real(kind=f64), dimension(:, :), allocatable node
subroutine build_mesh()
subroutine, public sll_s_compute_phi()
integer, dimension(:, :), allocatable connec
integer, dimension(:), allocatable prof
real(kind=f64), dimension(:), allocatable rho
subroutine, public sll_s_init(nx0, ny0, order0)
subroutine gradpg(iloc, ipg, grad, poids)
subroutine, public sll_s_plotgmsh()
real(kind=f64), dimension(:), allocatable vsup
subroutine, public sll_s_map(u, v, x, y)
subroutine sol(vkgs, vkgd, vkgi, vfg, kld, vu, neq, mp, ifac, isol, nsym, energ, ier, nsky)
Definition: sol.f:3
    Report Typos and Errors