Choral
diffusion_Neumann.f90
Go to the documentation of this file.
1 
83 
85 
87  use choral
88 
89  implicit none
90 
91  !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
92  !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
93  !!
94  !! VARAIBLE DEFINITION : BEGIN
95  !!
96  !!
97 
98  !! verb = verbosity level
99  !!
100  integer , parameter :: verb = 2
101 
102  !! Diffusivity coefficients
103  !!
104  real(RP), parameter :: L_1 = 1.0_rp
105  real(RP), parameter :: L_2 = 1.0_rp
106 
107 
108  !! SPACE DISCRETISATION
109  !!
110  !! fe_v = finite element method (volumic)
111  !! fe_s = finite element method (surfacic)
112  !! qd_v = quadrature method (volumic)
113  !! qd_s = quadrature method (surfacic)
114  !! mesh_idx = index for the mesh
115  !!
116  integer , parameter :: fe_v = fe_p2_2d
117  integer , parameter :: fe_s = fe_p2_1d
118  integer , parameter :: qd_v = quad_gauss_trg_12
119  integer , parameter :: qd_s = quad_gauss_edg_4
120  character(LEN=1), parameter :: mesh_idx = "2"
121  !!
122  !! m = mesh
123  !! X_h = finite element space
124  !! qdm = integration method
125  !!
126  type(mesh) :: msh
127  type(fespace) :: X_h
128  type(quadmesh) :: qdm
129  !!
130  !! msh_file
131  character(len=100), parameter :: mesh_file= &
132  & trim(GMSH_DIR)//"square/square_"//mesh_idx//".msh"
133 
134 
135  !! LINEAR SYSTEM
136  !!
137  !! precc_type = preconditioning type
138  !!
139  integer, parameter :: prec_type = pc_0
140  !!
141  !! kry = krylov method def.
142  !! mass = mass matrix
143  !! stiff = stiffness matrix
144  !! K = linear system matrix ( = mass + stiff )
145  !! pc = preconditionner
146  !! rhs = right hand side
147  !! u_h = numerical solution
148  !!
149  type(krylov) :: kry
150  type(csr) :: mass, stiff, K
151  type(precond) :: pc
152  real(RP), dimension(:), allocatable :: rhs, u_h, aux
153 
154 
155  !! NUMERICAL ERRORS
156  !!
157  real(RP) :: err_L2, err_H1
158 
159  character(LEN=300) :: shell_com
160 
161  !!
162  !! VARAIBLE DEFINITION : END
163  !!
164  !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
165  !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
166 
167 
168  !! !!!!!!!!!!!!!!!!!!!!! INITIALISATION
169  !!
170  call choral_init(verb=1)
171  write(*,*)
172  write(*,*)'diffusion_Neumann: start'
173  write(*,*)""
174  write(*,*)" EXAMPLE OF AN ELLIPTIC PROBLEM"
175  write(*,*)""
176  write(*,*)" -div(B(x) grad u) + rho(x)u = f on \Omega"
177  write(*,*)""
178  write(*,*)" WITH A NEUMANN BOUNDARY CONDITION "
179  write(*,*)""
180  write(*,*)" B(x)grad u . n = g on \partial\Omega"
181  write(*,*)""
182  write(*,*)" AND WITH AN ANISOTROPIC DIFFUSIVITY TENSOR B(x)."
183  write(*,*)""
184  write(*,*)" The problem data 'B', 'u', 'f' and 'g' "
185  write(*,*)" have been derived in"
186  write(*,*)" choral/maple/example_diffusion_Neumann.mw"
187  write(*,*)""
188  write(*,*)""
189  write(*,*)""
190 
191  write(*,*) ""
192  write(*,*)"================================== MESH ASSEMBLING"
193  msh = mesh(mesh_file, 'gmsh')
194 
195  call print(msh)
196 
197  write(*,*) ""
198  write(*,*)"================================== FINITE ELEMENT&
199  & SPACE ASSEMBLING"
200  x_h =fespace(msh)
201  call set(x_h, fe_v)
202  call set(x_h, fe_s)
203  call assemble(x_h)
204  call print(x_h)
205 
206  write(*,*) ""
207  write(*,*)"================================== INTEGRATION METHOD&
208  & ON \Omega ASSEMBLING"
209  qdm = quadmesh(msh)
210  call set(qdm, qd_v)
211  call assemble(qdm)
212  call print(qdm)
213 
214  write(*,*) ""
215  write(*,*)"================================== MASS AND STIFFNESS&
216  & MATRIX ASSEMBLING"
217  call diffusion_massmat(mass , rho, x_h, qdm)
218  call diffusion_stiffmat(stiff, bl_form_b, x_h, qdm)
219 
220 
221  write(*,*) ""
222  write(*,*)"================================== LINEAR SYSTEM MATRIX&
223  & AND PRECONDITIONING"
224  !!
225  !! K = mass + stiff
226  call add(k, stiff, 1._rp, mass, 1._rp)
227  !!
228  !! cleaning
229  call clear(mass)
230  call clear(stiff)
231  !!
232  !! preconditioning
233  pc = precond(k, prec_type)
234 
235 
236  write(*,*) ""
237  write(*,*)"================================== RIGHT HAND SIDE"
238  write(*,*)" 1- COMPUTATION OF F"
239  !!
240  !! \int_\Omega f u_i dx
241  !! The function 'f' here is defined below after the 'contains' keyword
242  !!
243  call l2_product(rhs, f, x_h, qdm)
244 
245 
246  write(*,*) ""
247  write(*,*)"================================== RIGHT HAND SIDE"
248  write(*,*)" 2- COMPUTATION OF G"
249  !!
250  !! \int_{Gamma, x=0} g u_i dx
251  !! The function 'g' here is defined below after the 'contains' keyword
252  !! 'g_x_0' is a function that defines the boundary subdomain
253  !! {x\in \Gamma, x=0}
254  !!
255  call diffusion_neumann_rhs(aux, g_x_0, x_h, qd_s, x_le_0)
256  rhs = rhs + aux
257  !!
258  !! \int_{Gamma, x=1} g u_i dx
259  call diffusion_neumann_rhs(aux, g_x_1, x_h, qd_s, x_ge_1)
260  rhs = rhs + aux
261  !!
262  !! \int_{Gamma, y=0} g u_i dx
263  call diffusion_neumann_rhs(aux, g_y_0, x_h, qd_s, y_le_0)
264  rhs = rhs + aux
265  !!
266  !! \int_{Gamma, y=1} g u_i dx
267  call diffusion_neumann_rhs(aux, g_y_1, x_h, qd_s, y_ge_1)
268  rhs = rhs + aux
269 
270  write(*,*) ""
271  write(*,*)"================================== SOLVE LINEAR SYSTEM&
272  & K U = RHS "
273  !!
274  !! Solver setting
275  kry = krylov(kry_cg, tol=1e-10_rp, itmax=1000, verb=0)
276  call print(kry)
277  !!
278  !! initial guess
279  call interp_scal_func(u_h, u, x_h)
280  !!
281  !! linear system inversion
282  call solve(u_h, kry, rhs, k, pc)
283  !!
284  !! cleaning
285  call clear(k)
286  call clear(pc)
287  call freemem(rhs)
288 
289  write(*,*) ""
290  write(*,*)"================================== POST-TREATMENT"
291  if (verb>1) then
292  !!
293  !! graphical display
294  !!
295  !! output file def.
296  shell_com = 'diff_Neumann_u.msh'
297  !!
298  !! first write the 'finite element mesh'
299  call write(x_h, trim(shell_com), 'gmsh')
300  !!
301  !! second save the finite element solution u_h
302  call gmsh_addview(x_h, u_h, &
303  & trim(shell_com), &
304  & 'Diffusion problem: numerical solution', 0.0_rp, 1)
305  !!
306  !! shell command to visualise with gmsh
307  shell_com = 'gmsh -option '//trim(gmsh_dir)//'gmsh-options-view'&
308  & //' '//trim(shell_com)
309  call system(shell_com)
310 
311  end if
312 
313  !!
314  !! L2 and H1_0 numerical errors
315  !! The exact solution 'u' and its gradient 'grad_y'
316  !! are defined below after the 'contains' keyword
317  write(*,*) ""
318  write(*,*) "Numerical errors"
319  err_l2 = l2_dist(u, u_h, x_h, qdm)
320  err_h1 = l2_dist_grad(grad_u, u_h, x_h, qdm)
321  write(*,*)" Error | u - u_h|_L2 =", err_l2
322  write(*,*)" Error |\nabla (u - u_h)|_L2 =", err_h1
323 
324  call freemem(u_h)
325  call freemem(aux)
326 
327 contains
328 
331  function u(x)
332  real(RP) :: u
333  real(RP), dimension(3), intent(in) :: x
334 
335  u = sin(pi*x(1) ) * sin(pi*x(2))
336 
337  end function u
338 
339 
342  function grad_u(x)
343  real(RP), dimension(3) :: grad_u
344  real(RP), dimension(3), intent(in) :: x
345 
346  grad_u(1) = pi * cos(pi*x(1)) * sin(pi*x(2))
347  grad_u(2) = pi * sin(pi*x(1)) * cos(pi*x(2))
348  grad_u(3) = 0._rp
349 
350  end function grad_u
351 
352 
355  function f(x)
356  real(RP) :: f
357  real(RP), dimension(3), intent(in) :: x
358 
359  real(RP) :: cx, sx, cy, sy, aux
360  real(RP) :: t, ct, st
361 
362  t = theta(x)
363  ct = cos(t)
364  st = sin(t)
365 
366  cx = cos(pi*x(1))
367  sx = sin(pi*x(1))
368  cy = cos(pi*x(2))
369  sy = sin(pi*x(2))
370 
371  aux =-4.0_rp *ct*st
372  f = aux*cx*cy
373 
374  aux = 2.0_rp*ct*st - 2.0_rp*ct**2 + 1.0_rp
375  f = f + aux*cx*sy
376 
377  aux =-2.0_rp*ct*st - 2.0_rp*ct**2 + 1.0_rp
378  f = f + aux*sx*cy
379 
380  f = f * (l_1-l_2)
381 
382  aux = 2.0_rp*(l_1+l_2)
383  f = f + aux*sx*sy
384 
385  f = f * pi**2 * 0.5_rp + rho(x)*u(x)
386 
387  end function f
388 
391  function rho(x)
392  real(RP) :: rho
393  real(RP), dimension(3), intent(in) :: x
394 
395  rho = sum(x*x)
396  rho = log( 1.0_rp + rho)
397 
398  end function rho
399 
400  !! Bilinear form associated with the diffuion tensor B(x)
401  !! \f$ (x, \xi_1, \xi_2) \mapsto B(x)\xi_1 \cdot \xi_2 \f$
402  !!
403  function bl_form_b(x, w1, w2) result(res)
404  real(RP) :: res
405  real(RP), dimension(3), intent(in) :: x, w1, w2
406 
407  real(RP), dimension(2,2) :: B_x
408  real(RP), dimension(2 ) :: B_w1
409 
410  b_x = b(x)
411  call matvecprod(b_w1, b_x, w1(1:2))
412 
413  res = b_w1(1)*w2(1) + b_w1(2)*w2(2)
414 
415  end function bl_form_b
416 
417 
421  function theta(x)
422  real(RP) :: theta
423  real(RP), dimension(3), intent(in) :: x
424 
425  theta = 0.5_rp * pi * ( x(1) + x(2) )
426 
427  end function theta
428 
431  function b(x)
432  real(RP), dimension(2,2) :: B
433  real(RP), dimension(3), intent(in) :: x
434 
435  real(RP) :: t, c, s
436 
437  t = theta(x)
438  c = cos(t)
439  s = sin(t)
440 
441  t = l_1 * c**2 + l_2 * s**2
442  b(1,1) = t
443  b(2,2) = l_1 + l_2 - t
444 
445  t = (l_1 - l_2) * c*s
446  b(1,2) = t
447  b(2,1) = t
448 
449  end function b
450 
451 
452 
455  function x_le_0(x) result(r)
456  real(RP) :: r
457  real(RP), dimension(3), intent(in) :: x
458 
459  r = -x(1)
460 
461  end function x_le_0
462 
463 
466  function x_ge_1(x) result(r)
467  real(RP) :: r
468  real(RP), dimension(3), intent(in) :: x
469 
470  r = x(1) - 1.0_rp
471 
472  end function x_ge_1
473 
476  function y_le_0(x) result(r)
477  real(RP) :: r
478  real(RP), dimension(3), intent(in) :: x
479 
480  r = -x(2)
481 
482  end function y_le_0
483 
484 
487  function y_ge_1(x) result(r)
488  real(RP) :: r
489  real(RP), dimension(3), intent(in) :: x
490 
491  r = x(2) - 1.0_rp
492 
493  end function y_ge_1
494 
495 
498  function g_x_0(x) result(r)
499  real(RP) :: r
500  real(RP), dimension(3), intent(in) :: x
501 
502  real(RP) :: t, c2, s2
503 
504  t = theta(x)
505  c2 = cos(t)**2
506  s2 = 1.0_rp - c2
507 
508  r = - pi * sin(pi*x(2)) * (l_1*c2 + l_2*s2)
509 
510  end function g_x_0
511 
512 
515  function g_x_1(x) result(r)
516  real(RP) :: r
517  real(RP), dimension(3), intent(in) :: x
518 
519  r = g_x_0(x)
520 
521  end function g_x_1
522 
523 
526  function g_y_0(x) result(r)
527  real(RP) :: r
528  real(RP), dimension(3), intent(in) :: x
529 
530  real(RP) :: t, c2, s2
531 
532  t = theta(x)
533  c2 = cos(t)**2
534  s2 = 1.0_rp - c2
535 
536  r = - pi * sin(pi*x(1)) * (l_1*s2 + l_2*c2)
537 
538  end function g_y_0
539 
540 
543  function g_y_1(x) result(r)
544  real(RP) :: r
545  real(RP), dimension(3), intent(in) :: x
546 
547  r = g_y_0(x)
548 
549  end function g_y_1
550 
551 
552 end program diffusion_neumann
real(rp) function x_ge_1(x)
To characterise {x=1}.
subroutine, public choral_init(verb)
Initialisation for the CHORAL library
Definition: choral.F90:166
TOP-LEVEL MODULE FOR THE LIBRARY CHORAL
Definition: choral.F90:27
integer, parameter fe_p2_2d
real(rp) function g_y_1(x)
g(x) on {y=1}
integer, parameter quad_gauss_edg_4
real(rp) function x_le_0(x)
To characterise {x=0}.
real(rp) function bl_form_b(x, w1, w2)
real(rp) function e(x, v1, v2)
real(rp) function y_le_0(x)
To characterise {x=0}.
real(rp) function, dimension(3) grad_u(x)
gradient of the exact solution
CHORAL CONSTANTS
real(rp) function f(x)
right hand side 'f'
real(rp) function u(x)
exact solution 'u'
real(rp) function y_ge_1(x)
To characterise {x=1}.
real(rp) function rho(x)
density '(x)'
real(rp) function g_y_0(x)
g(x) on {y=0}
real(rp) function g_x_0(x)
g(x) on {x=0}
real(rp) function g_x_1(x)
g(x) on {x=1}
integer, parameter quad_gauss_trg_12
real(rp) function theta(x)
Angle of the principal direction with e_x.
integer, parameter pc_0
void preconditioning
integer, parameter fe_p2_1d
integer, parameter kry_cg
CG linear solver.
real(rp) function b(x, w1, w2)
program diffusion_neumann
SOLVES THE DIFFUSION PROBLEM with Neumann boundary conditions