Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_coordinate_transformations_2d.F90
Go to the documentation of this file.
1 
34 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
35 #include "sll_assert.h"
36 #include "sll_memory.h"
37 #include "sll_working_precision.h"
38 
40  sll_p_dirichlet
41 
42  use sll_m_cartesian_meshes, only: &
46 
50  sll_p_io_mtv, &
51  sll_p_io_xdmf, &
52  sll_i_transformation_func_nopass
53 
54  use sll_m_gnuplot, only: &
56 
57  use sll_m_interpolators_2d_base, only: &
59 
60  use sll_m_plotmtv, only: &
62 
63  use sll_m_utilities, only: &
65 
66  use sll_m_xdmf, only: &
70 
71  implicit none
72 
73  public :: &
81 
82  private
83 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
84  abstract interface
85  function j_matrix_f_nopass(eta1, eta2, params) result(val)
87  sll_real64, dimension(2, 2) :: val
88  sll_real64 :: eta1
89  sll_real64 :: eta2
90  sll_real64, dimension(:), optional, intent(in) :: params
91  end function j_matrix_f_nopass
92  end interface
93 
101  procedure(sll_i_transformation_func_nopass), pointer, nopass :: f
102  end type jacobian_matrix_element
103 
107 !!$ sll_real64, dimension(:,:), pointer :: x1_node ! x1(i,j)
108 !!$ sll_real64, dimension(:,:), pointer :: x2_node ! x2(i,j)
109  !character(len=64) :: label
110  !logical :: written! = .false.
111  !type(sll_t_cartesian_mesh_2d), pointer :: mesh => null()
113  type(jacobian_matrix_element), dimension(2, 2) :: j_matrix
115  procedure(sll_i_transformation_func_nopass), pointer, nopass :: x1_func ! user
117  procedure(sll_i_transformation_func_nopass), pointer, nopass :: x2_func ! user
119  procedure(two_arg_message_passing_func_analyt), pointer, pass :: jacobian_func
121  procedure(j_matrix_f_nopass), pointer, nopass :: jacobian_matrix_function
123  sll_real64, dimension(:), pointer :: params => null() ! transf params
124  contains
126  procedure, pass(transf) :: init => sll_s_coordinate_transformation_2d_analytic_init
128  procedure, pass(transf) :: get_cartesian_mesh => get_cartesian_mesh_analytic
129  ! Functions with integer arguments
131  procedure, pass(transf) :: x1_at_node => x1_node_analytic
133  procedure, pass(transf) :: x2_at_node => x2_node_analytic
135  procedure, pass(transf) :: jacobian_at_node => jacobian_node_analytic
137  procedure, pass(transf) :: x1_at_cell => x1_cell_analytic
139  procedure, pass(transf) :: x2_at_cell => x2_cell_analytic
141  procedure, pass(transf) :: jacobian_at_cell => jacobian_2d_cell_analytic
142  ! Functions with real arguments
144  procedure, pass(transf) :: x1 => x1_analytic
146  procedure, pass(transf) :: x2 => x2_analytic
148  procedure, pass(transf) :: jacobian => jacobian_2d_analytic
150  procedure, pass(transf) :: jacobian_matrix => jacobian_matrix_2d_analytic
152  procedure, pass(transf) :: inverse_jacobian_matrix => &
155  procedure, pass(transf) :: write_to_file => write_to_file_2d_analytic
157  procedure, pass(transf) :: read_from_file => read_from_file_2d_analytic
159  procedure, pass(transf) :: delete => delete_transformation_2d_analytic
161 
162  ! -----------------------------------------------------------------------
163  !
164  ! Discrete case
165  !
166  ! -----------------------------------------------------------------------
167 
171  sll_real64, dimension(:, :), pointer :: x1_node => null() ! x1(i,j)
173  sll_real64, dimension(:, :), pointer :: x2_node => null() ! x2(i,j)
175  sll_real64, dimension(:, :), pointer :: x1_cell => null()
177  sll_real64, dimension(:, :), pointer :: x2_cell => null()
179  sll_real64, dimension(:, :), pointer :: jacobians_n => null()
181  sll_real64, dimension(:, :), pointer :: jacobians_c => null()
182 ! type(jacobian_matrix_element), dimension(2,2) :: j_matrix
184  class(sll_c_interpolator_2d), pointer :: x1_interp
186  class(sll_c_interpolator_2d), pointer :: x2_interp
187  !type(sll_t_cartesian_mesh_2d), pointer :: mesh => null()
188  contains
190  procedure, pass(transf) :: init => &
193  procedure, pass(transf) :: get_cartesian_mesh => get_cartesian_mesh_discrete
195  procedure, pass(transf) :: x1_at_node => x1_node_discrete
197  procedure, pass(transf) :: x2_at_node => x2_node_discrete
199  procedure, pass(transf) :: jacobian_at_node => transf_2d_jacobian_node_discrete
201  procedure, pass(transf) :: x1 => x1_discrete
203  procedure, pass(transf) :: x2 => x2_discrete
205  procedure, pass(transf) :: x1_at_cell => x1_cell_discrete
207  procedure, pass(transf) :: x2_at_cell => x2_cell_discrete
209  procedure, pass(transf) :: jacobian_at_cell => jacobian_2d_cell_discrete
211  procedure, pass(transf) :: jacobian => jacobian_2d_discrete
213  procedure, pass(transf) :: jacobian_matrix => jacobian_matrix_2d_discrete
215  procedure, pass(transf) :: inverse_jacobian_matrix => &
218  procedure, pass(transf) :: write_to_file => write_to_file_2d_discrete
220  procedure, pass(transf) :: read_from_file => read_from_file_2d_discrete
222  procedure, pass(transf) :: delete => delete_transformation_2d_discrete
224 
225 #ifndef DOXYGEN_SHOULD_SKIP_THIS
226 
227  abstract interface
228  function two_arg_message_passing_func_discr(transf, eta1, eta2)
231  sll_real64 :: two_arg_message_passing_func_discr
233  sll_real64, intent(in) :: eta1
234  sll_real64, intent(in) :: eta2
235  end function two_arg_message_passing_func_discr
236  end interface
237 
238  abstract interface
239  function two_arg_message_passing_func_analyt(transf, eta1, eta2)
242  sll_real64 :: two_arg_message_passing_func_analyt
244  sll_real64, intent(in) :: eta1
245  sll_real64, intent(in) :: eta2
246  end function two_arg_message_passing_func_analyt
247  end interface
248 
249 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
250 
252  interface sll_o_delete
253  module procedure &
256  end interface sll_o_delete
257 
258 contains
259 
260  !**************************************************************************
261  !
262  ! Functions for the analytic coordinate transformation
263  !
264  !**************************************************************************
265 
268  label, &
269  mesh_2d, &
270  x1_func, &
271  x2_func, &
272  j11_func, &
273  j12_func, &
274  j21_func, &
275  j22_func, &
276  params)
277 
280  character(len=*), intent(in) :: label
281  type(sll_t_cartesian_mesh_2d), target :: mesh_2d
282  procedure(sll_i_transformation_func_nopass) :: x1_func
283  procedure(sll_i_transformation_func_nopass) :: x2_func
284  procedure(sll_i_transformation_func_nopass) :: j11_func
285  procedure(sll_i_transformation_func_nopass) :: j12_func
286  procedure(sll_i_transformation_func_nopass) :: j21_func
287  procedure(sll_i_transformation_func_nopass) :: j22_func
288  sll_real64, dimension(:), intent(in) :: params
289  sll_int32 :: ierr
290 
292 
295  label, &
296  mesh_2d, &
297  x1_func, &
298  x2_func, &
299  j11_func, &
300  j12_func, &
301  j21_func, &
302  j22_func, &
303  params)
304 
306 
308  transf, &
309  label, &
310  mesh_2d, &
311  x1_func, &
312  x2_func, &
313  j11_func, &
314  j12_func, &
315  j21_func, &
316  j22_func, &
317  params)
318 
319  class(sll_t_coordinate_transformation_2d_analytic), intent(inout) :: &
320  transf
321  character(len=*), intent(in) :: label
322  procedure(sll_i_transformation_func_nopass) :: x1_func
323  procedure(sll_i_transformation_func_nopass) :: x2_func
324  procedure(sll_i_transformation_func_nopass) :: j11_func
325  procedure(sll_i_transformation_func_nopass) :: j12_func
326  procedure(sll_i_transformation_func_nopass) :: j21_func
327  procedure(sll_i_transformation_func_nopass) :: j22_func
328  type(sll_t_cartesian_mesh_2d), target :: mesh_2d
329  sll_real64, dimension(:), intent(in) :: params
330  sll_int32 :: ierr
331 
332  transf%label = trim(label)
333  transf%mesh => mesh_2d
334 
335  ! Assign the transformation functions and parameters
336  transf%x1_func => x1_func
337  transf%x2_func => x2_func
338  if (size(params) > 0) then
339  sll_allocate(transf%params(size(params)), ierr)
340  transf%params(:) = params(:)
341  else
342  sll_clear_allocate(transf%params(1), ierr)
343  end if
344 
345  ! Fill the jacobian matrix
346  transf%j_matrix(1, 1)%f => j11_func
347  transf%j_matrix(1, 2)%f => j12_func
348  transf%j_matrix(2, 1)%f => j21_func
349  transf%j_matrix(2, 2)%f => j22_func
350  transf%jacobian_func => jacobian_2d_analytic
351 
353 
355  class(sll_t_coordinate_transformation_2d_analytic), intent(inout) :: transf
356 
357  nullify (transf%x1_func)
358  nullify (transf%x2_func)
359  nullify (transf%jacobian_func)
360  nullify (transf%jacobian_matrix_function)
361  end subroutine delete_transformation_2d_analytic
362 
363  function get_cartesian_mesh_analytic(transf) result(res)
364  class(sll_t_coordinate_transformation_2d_analytic), intent(in) :: transf
365  class(sll_t_cartesian_mesh_2d), pointer :: res
366  res => transf%mesh
367  end function get_cartesian_mesh_analytic
368 
369  function jacobian_2d_analytic(transf, eta1, eta2) result(val)
370  sll_real64 :: val
372  sll_real64, intent(in) :: eta1
373  sll_real64, intent(in) :: eta2
374  sll_real64 :: j11
375  sll_real64 :: j12
376  sll_real64 :: j21
377  sll_real64 :: j22
378  j11 = (transf%j_matrix(1, 1)%f(eta1, eta2, transf%params))
379  j12 = (transf%j_matrix(1, 2)%f(eta1, eta2, transf%params))
380  j21 = (transf%j_matrix(2, 1)%f(eta1, eta2, transf%params))
381  j22 = (transf%j_matrix(2, 2)%f(eta1, eta2, transf%params))
382  ! For debugging:
383  ! print *, 'jacobian_2d_analytic: '
384  ! print *, j11, j12
385  ! print *, j21, j22
386  val = j11*j22 - j12*j21
387  end function jacobian_2d_analytic
388 
389  ! The efficiency of the following function could be improved by just
390  ! passing the output array rather than returning values on the stack which
391  ! need to be caught by the caller.
392  function jacobian_matrix_2d_analytic(transf, eta1, eta2)
393  sll_real64, dimension(1:2, 1:2) :: jacobian_matrix_2d_analytic
394  class(sll_t_coordinate_transformation_2d_analytic), intent(inout):: transf
395  sll_real64, intent(in) :: eta1
396  sll_real64, intent(in) :: eta2
397  sll_real64 :: j11
398  sll_real64 :: j12
399  sll_real64 :: j21
400  sll_real64 :: j22
401  j11 = (transf%j_matrix(1, 1)%f(eta1, eta2, transf%params))
402  j12 = (transf%j_matrix(1, 2)%f(eta1, eta2, transf%params))
403  j21 = (transf%j_matrix(2, 1)%f(eta1, eta2, transf%params))
404  j22 = (transf%j_matrix(2, 2)%f(eta1, eta2, transf%params))
405  ! For debugging:
406  ! print *, 'jacobian_2d_analytic: '
407  ! print *, j11, j12
408  ! print *, j21, j22
409  jacobian_matrix_2d_analytic(1, 1) = j11
410  jacobian_matrix_2d_analytic(1, 2) = j12
411  jacobian_matrix_2d_analytic(2, 1) = j21
412  jacobian_matrix_2d_analytic(2, 2) = j22
413  end function jacobian_matrix_2d_analytic
414 
415  function inverse_jacobian_matrix_2d_analytic(transf, eta1, eta2)
416  sll_real64, dimension(1:2, 1:2) :: inverse_jacobian_matrix_2d_analytic
417  class(sll_t_coordinate_transformation_2d_analytic), intent(inout) :: transf
418  sll_real64, intent(in) :: eta1
419  sll_real64, intent(in) :: eta2
420  sll_real64 :: inv_j11
421  sll_real64 :: inv_j12
422  sll_real64 :: inv_j21
423  sll_real64 :: inv_j22
424  sll_real64 :: r_jacobian ! reciprocal of the jacobian
425 
426  r_jacobian = 1.0_f64/transf%jacobian(eta1, eta2)
427  inv_j11 = (transf%j_matrix(2, 2)%f(eta1, eta2, transf%params))*r_jacobian
428  inv_j12 = -(transf%j_matrix(1, 2)%f(eta1, eta2, transf%params))*r_jacobian
429  inv_j21 = -(transf%j_matrix(2, 1)%f(eta1, eta2, transf%params))*r_jacobian
430  inv_j22 = (transf%j_matrix(1, 1)%f(eta1, eta2, transf%params))*r_jacobian
431  ! For debugging:
432  ! print *, 'jacobian_2d_analytic: '
433  ! print *, j11, j12
434  ! print *, j21, j22
440 
441  function x1_analytic(transf, eta1, eta2) result(val)
442  sll_real64 :: val
444  sll_real64, intent(in) :: eta1
445  sll_real64, intent(in) :: eta2
446  val = transf%x1_func(eta1, eta2, transf%params)
447  end function x1_analytic
448 
449  function x2_analytic(transf, eta1, eta2) result(val)
450  sll_real64 :: val
452  sll_real64, intent(in) :: eta1
453  sll_real64, intent(in) :: eta2
454  val = transf%x2_func(eta1, eta2, transf%params)
455  end function x2_analytic
456 
457  function x1_node_analytic(transf, i, j) result(val)
459  sll_real64 :: val
460  sll_int32, intent(in) :: i
461  sll_int32, intent(in) :: j
462  sll_real64 :: eta1
463  sll_real64 :: eta2
464 
465  eta1 = transf%mesh%eta1_node(i, j)
466  eta2 = transf%mesh%eta2_node(i, j)
467  val = transf%x1_func(eta1, eta2, transf%params)
468  end function x1_node_analytic
469 
470  function x2_node_analytic(transf, i, j) result(val)
472  sll_real64 :: val
473  sll_int32, intent(in) :: i
474  sll_int32, intent(in) :: j
475  sll_real64 :: eta1
476  sll_real64 :: eta2
477 
478  eta1 = transf%mesh%eta1_node(i, j)
479  eta2 = transf%mesh%eta2_node(i, j)
480  val = transf%x2_func(eta1, eta2, transf%params)
481  end function x2_node_analytic
482 
483  function x1_cell_analytic(transf, i, j) result(var)
485  sll_real64 :: var
486  sll_int32, intent(in) :: i
487  sll_int32, intent(in) :: j
488  sll_real64 :: eta1
489  sll_real64 :: eta2
490 
491  eta1 = transf%mesh%eta1_cell(i, j)
492  eta2 = transf%mesh%eta2_cell(i, j)
493  var = transf%x1_func(eta1, eta2, transf%params)
494  end function x1_cell_analytic
495 
496  function x2_cell_analytic(transf, i, j) result(var)
498  sll_real64 :: var
499  sll_int32, intent(in) :: i
500  sll_int32, intent(in) :: j
501  sll_real64 :: eta1
502  sll_real64 :: eta2
503 
504  eta1 = transf%mesh%eta1_cell(i, j)
505  eta2 = transf%mesh%eta2_cell(i, j)
506  var = transf%x2_func(eta1, eta2, transf%params)
507  end function x2_cell_analytic
508 
509  function jacobian_2d_cell_analytic(transf, i, j) result(val)
511  sll_real64 :: val
512  sll_int32, intent(in) :: i
513  sll_int32, intent(in) :: j
514  sll_real64 :: eta1
515  sll_real64 :: eta2
516  sll_real64 :: j11
517  sll_real64 :: j12
518  sll_real64 :: j21
519  sll_real64 :: j22
520 
521  eta1 = transf%mesh%eta1_cell(i, j)
522  eta2 = transf%mesh%eta2_cell(i, j)
523  j11 = (transf%j_matrix(1, 1)%f(eta1, eta2, transf%params))
524  j12 = (transf%j_matrix(1, 2)%f(eta1, eta2, transf%params))
525  j21 = (transf%j_matrix(2, 1)%f(eta1, eta2, transf%params))
526  j22 = (transf%j_matrix(2, 2)%f(eta1, eta2, transf%params))
527  ! For debugging:
528  ! print *, 'jacobian_2d_analytic: '
529  ! print *, j11, j12
530  ! print *, j21, j22
531  val = j11*j22 - j12*j21
532  end function jacobian_2d_cell_analytic
533 
534  function jacobian_node_analytic(transf, i, j)
536  sll_real64 :: jacobian_node_analytic
537  sll_int32, intent(in) :: i
538  sll_int32, intent(in) :: j
539  sll_int32 :: num_pts_1
540  sll_int32 :: num_pts_2
541  sll_real64 :: eta1
542  sll_real64 :: eta2
543  sll_real64 :: j11
544  sll_real64 :: j12
545  sll_real64 :: j21
546  sll_real64 :: j22
547 
548  num_pts_1 = transf%mesh%num_cells1 + 1
549  num_pts_2 = transf%mesh%num_cells2 + 1
550  sll_assert((i .ge. 1) .and. (i .le. num_pts_1))
551  sll_assert((j .ge. 1) .and. (j .le. num_pts_2))
552 
553  eta1 = transf%mesh%eta1_cell(i, j)
554  eta2 = transf%mesh%eta2_cell(i, j)
555  j11 = (transf%j_matrix(1, 1)%f(eta1, eta2, transf%params))
556  j12 = (transf%j_matrix(1, 2)%f(eta1, eta2, transf%params))
557  j21 = (transf%j_matrix(2, 1)%f(eta1, eta2, transf%params))
558  j22 = (transf%j_matrix(2, 2)%f(eta1, eta2, transf%params))
559  ! For debugging:
560  ! print *, 'jacobian_2d_analytic: '
561  ! print *, j11, j12
562  ! print *, j21, j22
563  jacobian_node_analytic = j11*j22 - j12*j21
564  end function jacobian_node_analytic
565 
566  subroutine write_to_file_2d_analytic(transf, output_format)
567  class(sll_t_coordinate_transformation_2d_analytic), intent(inout) :: transf
568  sll_int32, intent(in), optional :: output_format
569  sll_int32 :: local_format
570  sll_real64, dimension(:, :), allocatable :: x1mesh
571  sll_real64, dimension(:, :), allocatable :: x2mesh
572  sll_int32 :: i1
573  sll_int32 :: i2
574  sll_real64 :: eta1
575  sll_real64 :: eta2
576  sll_int32 :: ierr
577  sll_int32 :: file_id
578  sll_int32 :: nc_eta1
579  sll_int32 :: nc_eta2
580 
581  nc_eta1 = transf%mesh%num_cells1
582  nc_eta2 = transf%mesh%num_cells2
583 
584  if (.not. present(output_format)) then
585  local_format = sll_p_io_gnuplot
586  else
587  local_format = output_format
588  end if
589 
590  if (.not. transf%written) then
591  if (local_format == sll_p_io_xdmf) then
592  sll_allocate(x1mesh(nc_eta1 + 1, nc_eta2 + 1), ierr)
593  sll_allocate(x2mesh(nc_eta1 + 1, nc_eta2 + 1), ierr)
594  eta1 = transf%mesh%eta1_min
595  do i1 = 1, nc_eta1 + 1
596  eta2 = transf%mesh%eta2_min
597  do i2 = 1, nc_eta2 + 1
598  x1mesh(i1, i2) = x1_node_analytic(transf, i1, i2)
599  x2mesh(i1, i2) = x2_node_analytic(transf, i1, i2)
600  eta2 = eta2 + transf%mesh%delta_eta2
601  end do
602  eta1 = eta1 + transf%mesh%delta_eta1
603  end do
604 
605  call sll_o_xdmf_open(trim(transf%label)//".xmf", transf%label, &
606  nc_eta1 + 1, nc_eta2 + 1, file_id, ierr)
607  call sll_o_xdmf_write_array(transf%label, x1mesh, "x1", ierr)
608  call sll_o_xdmf_write_array(transf%label, x2mesh, "x2", ierr)
609  call sll_s_xdmf_close(file_id, ierr)
610 
611  else if (local_format == sll_p_io_gnuplot) then
612 
613  sll_allocate(x1mesh(nc_eta1 + 1, nc_eta2 + 1), ierr)
614  sll_allocate(x2mesh(nc_eta1 + 1, nc_eta2 + 1), ierr)
615 
616  do i1 = 1, nc_eta1 + 1
617  do i2 = 1, nc_eta2 + 1
618  x1mesh(i1, i2) = x1_node_analytic(transf, i1, i2)
619  x2mesh(i1, i2) = x2_node_analytic(transf, i1, i2)
620  end do
621  end do
622 
623  call sll_o_gnuplot_2d(nc_eta1 + 1, nc_eta2 + 1, x1mesh, x2mesh, &
624  trim(transf%label), ierr)
625 
626  else if (local_format == sll_p_io_mtv) then
627 
628  sll_allocate(x1mesh(nc_eta1 + 1, nc_eta2 + 1), ierr)
629  sll_allocate(x2mesh(nc_eta1 + 1, nc_eta2 + 1), ierr)
630 
631  do i1 = 1, nc_eta1 + 1
632  do i2 = 1, nc_eta2 + 1
633  x1mesh(i1, i2) = x1_node_analytic(transf, i1, i2)
634  x2mesh(i1, i2) = x2_node_analytic(transf, i1, i2)
635  end do
636  end do
637 
638  call sll_o_plotmtv_write(nc_eta1 + 1, nc_eta2 + 1, &
639  x1mesh, x2mesh, trim(transf%label), ierr)
640 
641  else
642  print *, 'Not recognized format to write this mesh'
643  stop
644  end if
645  else
646  print *, ' Warning, you have already written the mesh '
647  end if
648  transf%written = .true.
649  if (allocated(x1mesh)) deallocate (x1mesh)
650  if (allocated(x2mesh)) deallocate (x2mesh)
651 
652  end subroutine write_to_file_2d_analytic
653 
654  subroutine read_from_file_2d_analytic(transf, filename)
655  class(sll_t_coordinate_transformation_2d_analytic), intent(inout) :: transf
656  character(len=*), intent(in) :: filename
657  print *, filename
658  print *, 'read_from_file_2d_analytic: not yet implemented'
659  !call sll_o_display(transf%mesh)
660  call transf%mesh%display()
661  ! here we could put a case select to choose which analytic transformation
662  ! we would like to use.
663  end subroutine read_from_file_2d_analytic
664 
665  !**************************************************************************
666  !
667  ! Functions for the discrete general transformation
668  !
669  !**************************************************************************
670 
671  function get_cartesian_mesh_discrete(transf) result(res)
672  class(sll_t_coordinate_transformation_2d_discrete), intent(in) :: transf
673  class(sll_t_cartesian_mesh_2d), pointer :: res
674  res => transf%mesh
675  end function get_cartesian_mesh_discrete
676 
677  function x1_node_discrete(transf, i, j) result(val)
679  sll_real64 :: val
680  sll_int32, intent(in) :: i
681  sll_int32, intent(in) :: j
682  val = transf%x1_node(i, j)
683  end function x1_node_discrete
684 
685  function x2_node_discrete(transf, i, j) result(val)
687  sll_real64 :: val
688  sll_int32, intent(in) :: i
689  sll_int32, intent(in) :: j
690  val = transf%x2_node(i, j)
691  end function x2_node_discrete
692 
693  function x1_cell_discrete(transf, i, j) result(var)
695  sll_real64 :: var
696  sll_int32, intent(in) :: i
697  sll_int32, intent(in) :: j
698  var = transf%x1_cell(i, j)
699  end function x1_cell_discrete
700 
701  function x2_cell_discrete(transf, i, j) result(var)
703  sll_real64 :: var
704  sll_int32, intent(in) :: i
705  sll_int32, intent(in) :: j
706  var = transf%x2_cell(i, j)
707  end function x2_cell_discrete
708 
709  function x1_discrete(transf, eta1, eta2) result(val)
711  sll_real64 :: val
712  sll_real64, intent(in) :: eta1
713  sll_real64, intent(in) :: eta2
714  val = transf%x1_interp%interpolate_from_interpolant_value(eta1, eta2)
715  end function x1_discrete
716 
717  function x2_discrete(transf, eta1, eta2) result(val)
719  sll_real64 :: val
720  sll_real64, intent(in) :: eta1
721  sll_real64, intent(in) :: eta2
722  val = transf%x2_interp%interpolate_from_interpolant_value(eta1, eta2)
723  end function x2_discrete
724 
725  function jacobian_2d_discrete(transf, eta1, eta2) result(jac)
727  sll_real64 :: jac
728  sll_real64, intent(in) :: eta1
729  sll_real64, intent(in) :: eta2
730  sll_real64 :: j11
731  sll_real64 :: j12
732  sll_real64 :: j21
733  sll_real64 :: j22
734  j11 = transf%x1_interp%interpolate_from_interpolant_derivative_eta1(eta1, eta2)
735  j12 = transf%x1_interp%interpolate_from_interpolant_derivative_eta2(eta1, eta2)
736  j21 = transf%x2_interp%interpolate_from_interpolant_derivative_eta1(eta1, eta2)
737  j22 = transf%x2_interp%interpolate_from_interpolant_derivative_eta2(eta1, eta2)
738  ! For debugging:
739  ! print *, 'jacobian_2D_discrete: '
740  ! print *, j11, j12
741  ! print *, j21, j22
742  jac = j11*j22 - j12*j21
743  end function jacobian_2d_discrete
744 
745  function jacobian_2d_cell_discrete(transf, i, j) result(var)
747  sll_real64 :: var
748  sll_int32, intent(in) :: i
749  sll_int32, intent(in) :: j
750  var = transf%jacobians_c(i, j)
751  end function jacobian_2d_cell_discrete
752 
753  function jacobian_matrix_2d_discrete(transf, eta1, eta2)
754  class(sll_t_coordinate_transformation_2d_discrete), intent(inout) :: transf
755  sll_real64, dimension(1:2, 1:2) :: jacobian_matrix_2d_discrete
756  sll_real64, intent(in) :: eta1
757  sll_real64, intent(in) :: eta2
758  sll_real64 :: j11
759  sll_real64 :: j12
760  sll_real64 :: j21
761  sll_real64 :: j22
762  j11 = transf%x1_interp%interpolate_from_interpolant_derivative_eta1(eta1, eta2)
763  j12 = transf%x1_interp%interpolate_from_interpolant_derivative_eta2(eta1, eta2)
764  j21 = transf%x2_interp%interpolate_from_interpolant_derivative_eta1(eta1, eta2)
765  j22 = transf%x2_interp%interpolate_from_interpolant_derivative_eta2(eta1, eta2)
766  ! For debugging:
767  ! print *, 'jacobian_2D_discrete: '
768  ! print *, j11, j12
769  ! print *, j21, j22
770  jacobian_matrix_2d_discrete(1, 1) = j11
771  jacobian_matrix_2d_discrete(1, 2) = j12
772  jacobian_matrix_2d_discrete(2, 1) = j21
773  jacobian_matrix_2d_discrete(2, 2) = j22
774  end function jacobian_matrix_2d_discrete
775 
776  function inverse_jacobian_matrix_2d_discrete(transf, eta1, eta2)
777  class(sll_t_coordinate_transformation_2d_discrete), intent(inout) :: transf
778  sll_real64, dimension(1:2, 1:2) :: inverse_jacobian_matrix_2d_discrete
779  sll_real64, intent(in) :: eta1
780  sll_real64, intent(in) :: eta2
781  sll_real64 :: inv_j11
782  sll_real64 :: inv_j12
783  sll_real64 :: inv_j21
784  sll_real64 :: inv_j22
785  sll_real64 :: r_jac ! reciprocal of the jacobian
786  r_jac = 1.0_f64/transf%jacobian(eta1, eta2)
787  inv_j11 = transf%x1_interp%interpolate_from_interpolant_derivative_eta1(eta1, eta2)
788  inv_j12 = transf%x1_interp%interpolate_from_interpolant_derivative_eta2(eta1, eta2)
789  inv_j21 = transf%x2_interp%interpolate_from_interpolant_derivative_eta1(eta1, eta2)
790  inv_j22 = transf%x2_interp%interpolate_from_interpolant_derivative_eta2(eta1, eta2)
791  ! For debugging:
792  ! print *, 'jacobian_2D_discrete: '
793  ! print *, j11, j12
794  ! print *, j21, j22
795  inverse_jacobian_matrix_2d_discrete(1, 1) = inv_j22*r_jac
796  inverse_jacobian_matrix_2d_discrete(1, 2) = -inv_j12*r_jac
797  inverse_jacobian_matrix_2d_discrete(2, 1) = -inv_j21*r_jac
798  inverse_jacobian_matrix_2d_discrete(2, 2) = inv_j11*r_jac
800 
803  mesh_2d, &
804  label, &
805  x1_interpolator, &
806  x2_interpolator, &
807  jacobians_n_interpolator, &
808  x1_node, &
809  x2_node, &
810  jacobians_node, &
811  x1_cell, &
812  x2_cell, &
813  jacobians_cell)
814 
815  ! INPUT VARIABLES
816  type(sll_t_cartesian_mesh_2d), pointer :: mesh_2d
817  character(len=*), intent(in) :: label
818 
819  class(sll_c_interpolator_2d), target :: x1_interpolator
820  class(sll_c_interpolator_2d), target :: x2_interpolator
821  class(sll_c_interpolator_2d), target :: jacobians_n_interpolator
822  sll_real64, dimension(:, :), intent(in), optional :: x1_node
823  sll_real64, dimension(:, :), intent(in), optional :: x2_node
824  sll_real64, dimension(:, :), intent(in), optional :: jacobians_node
825  sll_real64, dimension(:, :), intent(in), optional :: x1_cell
826  sll_real64, dimension(:, :), intent(in), optional :: x2_cell
827  sll_real64, dimension(:, :), intent(in), optional :: jacobians_cell
828 
829  ! LOCAL VARIABLES
832  sll_int32 :: ierr
833 
837  mesh_2d, &
838  label, &
839  x1_interpolator, &
840  x2_interpolator, &
841  jacobians_n_interpolator, &
842  x1_node, &
843  x2_node, &
844  jacobians_node, &
845  x1_cell, &
846  x2_cell, &
847  jacobians_cell)
849 
851  transf, &
852  mesh_2d, &
853  label, &
854  x1_interpolator, &
855  x2_interpolator, &
856  jacobians_n_interpolator, &
857  x1_node, &
858  x2_node, &
859  jacobians_node, &
860  x1_cell, &
861  x2_cell, &
862  jacobians_cell)
863 
865  type(sll_t_cartesian_mesh_2d), target :: mesh_2d
866  character(len=*), intent(in) :: label
867 
868  class(sll_c_interpolator_2d), target :: x1_interpolator
869  class(sll_c_interpolator_2d), target :: x2_interpolator
870  class(sll_c_interpolator_2d), target :: jacobians_n_interpolator
871  sll_real64, dimension(:, :), intent(in), optional :: x1_node
872  sll_real64, dimension(:, :), intent(in), optional :: x2_node
873  sll_real64, dimension(:, :), intent(in), optional :: jacobians_node
874  sll_real64, dimension(:, :), intent(in), optional :: jacobians_cell
875  sll_real64, dimension(:, :), intent(in), optional :: x1_cell
876  sll_real64, dimension(:, :), intent(in), optional :: x2_cell
877 
878  sll_real64 :: eta_1
879  sll_real64 :: eta_2
880  sll_real64 :: eta_1_min
881  sll_real64 :: eta_2_min
882  sll_real64 :: delta_eta_1
883  sll_real64 :: delta_eta_2
884  sll_real64 :: jacobian_val
885  sll_int32 :: i
886  sll_int32 :: j
887  sll_int32 :: ierr
888  sll_int32 :: npts1
889  sll_int32 :: npts2
890  logical :: x1n
891  logical :: x2n
892  logical :: x1c
893  logical :: x2c
894  logical :: jc
895  logical :: jn
896 
897  transf%mesh => mesh_2d
898  transf%label = trim(label)
899  x1n = present(x1_node)
900  x2n = present(x2_node)
901  x1c = present(x1_cell)
902  x2c = present(x2_cell)
903  jc = present(jacobians_cell)
904  jn = present(jacobians_node)
905  npts1 = mesh_2d%num_cells1 + 1
906  npts2 = mesh_2d%num_cells2 + 1
907 
908  ! Check argument consistency
909  ! DISCRETE_MAPs require only some of the parameters. If the mapping is
910  ! defined from the nodes of the logical (eta1, eta2) mesh to the nodes
911  ! of the physical mesh (x1,x2), then either:
912  ! - the node arrays are required: jacobians_node, x1_node and x2_node. Or
913  ! - the x1_interpolator and x2_interpolator must contain already the
914  ! coefficient information that would permit the calculation of the
915  ! x1 and x2 points.
916  !
917  ! If the transformation is done on the points at the center of the cells
918  ! then these parameters are also required:
919  ! jacobians_cell, x1_cell, x2_cell.
920  ! node and cell values are not mutually exclusive, thus all 6 parameters
921  ! can be provided in the discrete case. It is up to the caller to make
922  ! sure that the data set is consistent.
923 
924  ! 1. Check that the discrete representation of the transformation is
925  ! consistent with the size of the 2D array.
926 
927  if ((x1n .and. (.not. x2n)) .or. &
928  ((.not. x1n) .and. x2n)) then
929 
930  print *, 'ERROR, sll_s_coordinate_transformation_2d_discrete_init():', &
931  'for the moment, this function does not support specifying ', &
932  'transformation only with one of the node arrays x1_node or ', &
933  'x2_node. Either pass both, or none, but with the ', &
934  'corresponding interpolators having their coefficients ', &
935  'already set.'
936  stop
937  call jacobians_n_interpolator%delete() !PN added to remove the warning
938  end if
939 
940  if (x1n) then
941  if (size(x1_node, 1) .lt. npts1) then
942  print *, 'ERROR, sll_s_coordinate_transformation_2d_discrete_init()', &
943  ' the size of the x1_node arrays is ', &
944  'inconsistent with the number of points declared, ', &
945  'in the logical mesh.'
946  stop
947  end if
948  end if
949 
950  if (x2n) then
951  if (size(x1_node, 2) .lt. npts2) then
952  print *, 'ERROR, sll_s_coordinate_transformation_2d_discrete_init()', &
953  ' the size of the x2_node arrays is ', &
954  'inconsistent with the number of points declared, ', &
955  'in the logical mesh.'
956  stop
957  end if
958  end if
959 
960  if (jn .eqv. .true.) then
961  if ( &
962  (size(jacobians_node, 1) .lt. npts1 - 1) .or. &
963  (size(jacobians_node, 2) .lt. npts2 - 1)) then
964  print *, 'ERROR, sll_s_coordinate_transformation_2d_discrete_init()', &
965  ': the size of the jacobians_node array is ', &
966  'inconsistent with the number of points declared, ', &
967  'npts1 or npts2.'
968  stop
969  end if
970  end if
971 
972  if (jc .eqv. .true.) then
973  if ( &
974  (size(jacobians_cell, 1) .lt. npts1 - 1) .or. &
975  (size(jacobians_cell, 2) .lt. npts2 - 1)) then
976  print *, 'ERROR, sll_s_coordinate_transformation_2d_discrete_init()', &
977  ': the size of the jacobians_cell arrays is ', &
978  'inconsistent with the number of points declared, ', &
979  'npts1 or npts2.'
980  stop
981  end if
982  end if
983 
984  transf%x1_interp => x1_interpolator
985  transf%x2_interp => x2_interpolator
986 
987  ! Allocate the arrays for precomputed jacobians.
988  sll_allocate(transf%jacobians_n(npts1, npts2), ierr)
989  sll_allocate(transf%jacobians_c(npts1 - 1, npts2 - 1), ierr)
990 
991  ! Allocation for x1 and x2 at nodes
992  sll_allocate(transf%x1_node(npts1, npts2), ierr)
993  sll_allocate(transf%x2_node(npts1, npts2), ierr)
994 
995  ! Allocation for x1 and x2 at cells
996  sll_allocate(transf%x1_cell(npts1 - 1, npts2 - 1), ierr)
997  sll_allocate(transf%x2_cell(npts1 - 1, npts2 - 1), ierr)
998 
999  ! initialize the local arrays. Note that since the map has its
1000  ! own copies, it owns this information locally and will destroy
1001  ! this information when the object is deleted. The caller is
1002  ! thus responsible for deallocating the arrays that were passed as
1003  ! arguments.
1004 
1005  eta_1_min = mesh_2d%eta1_min
1006  eta_2_min = mesh_2d%eta2_min
1007  delta_eta_1 = mesh_2d%delta_eta1
1008  delta_eta_2 = mesh_2d%delta_eta2
1009 
1010  if (x1n .and. x2n) then
1011  do j = 1, npts2
1012  do i = 1, npts1
1013  transf%x1_node(i, j) = x1_node(i, j)
1014  transf%x2_node(i, j) = x2_node(i, j)
1015  end do
1016  end do
1017  else
1018  if (x1_interpolator%coefficients_are_set() .eqv. .false.) then
1019  print *, 'ERROR, sll_s_coordinate_transformation_2d_discrete_init()', &
1020  ': the x1_node array was not passed and the corresponding ', &
1021  'interpolator has no initialized coefficients. Exiting...'
1022  stop
1023  end if
1024  if (x2_interpolator%coefficients_are_set() .eqv. .false.) then
1025  print *, 'ERROR, sll_s_coordinate_transformation_2d_discrete_init()', &
1026  ': the x2_node array was not passed and the corresponding ', &
1027  'interpolator has no initialized coefficients. Exiting...'
1028  stop
1029  end if
1030  ! now initialize the arrays starting from the interpolator information
1031  ! and the logical mesh information.
1032  do j = 0, npts2 - 1
1033  eta_2 = eta_2_min + real(j, f64)*delta_eta_2
1034  do i = 0, npts1 - 1
1035  eta_1 = eta_1_min + real(i, f64)*delta_eta_1
1036  transf%x1_node(i + 1, j + 1) = &
1037  x1_interpolator%interpolate_from_interpolant_value(eta_1, eta_2)
1038  transf%x2_node(i + 1, j + 1) = &
1039  x2_interpolator%interpolate_from_interpolant_value(eta_1, eta_2)
1040  end do
1041  end do
1042  end if
1043 
1044  ! Compute the spline coefficients
1045  if (x1n .and. (x1_interpolator%coefficients_are_set() .eqv. .false.)) then
1046  call x1_interpolator%compute_interpolants(transf%x1_node)
1047  end if
1048  if (x2n .and. (x2_interpolator%coefficients_are_set() .eqv. .false.)) then
1049  call x2_interpolator%compute_interpolants(transf%x2_node)
1050  end if
1051 
1052  ! The splines contain all the information to compute the
1053  ! jacobians everywhere; however, here we explore assigning
1054  ! the jacobians-at-the-nodes array with the values provided
1055  ! by the user if available. If there are discrepancies between
1056  ! the user-provided values and the predictions from the splines,
1057  ! then this may itself be a way to look for errors.
1058  !
1059  ! Copy the values of the jacobians at the nodes if user given:
1060  if (jn .eqv. .true.) then
1061  do j = 1, npts2
1062  do i = 1, npts1
1063  transf%jacobians_n(i, j) = jacobians_node(i, j)
1064  end do
1065  end do
1066  else
1067  ! Fill the jacobian values at the nodes calculated from the splines
1068  do j = 0, npts2 - 1
1069  eta_2 = eta_2_min + real(j, f64)*delta_eta_2
1070  do i = 0, npts1 - 1
1071  eta_1 = eta_1_min + real(i, f64)*delta_eta_1
1072  jacobian_val = transf%jacobian(eta_1, eta_2)
1073  transf%jacobians_n(i + 1, j + 1) = jacobian_val
1074  end do
1075  end do
1076  end if
1077 
1078  ! copy the cell-based transformation arrays if available
1079  if ((x1c .and. x2c) .eqv. .true.) then
1080  sll_allocate(transf%x1_cell(npts1 - 1, npts2 - 1), ierr)
1081  sll_allocate(transf%x2_cell(npts1 - 1, npts2 - 1), ierr)
1082  do j = 1, npts2 - 1
1083  do i = 1, npts1 - 1
1084  transf%x1_cell(i, j) = x1_cell(i, j)
1085  transf%x2_cell(i, j) = x2_cell(i, j)
1086  end do
1087  end do
1088  end if
1089  ! copy the cell-based jacobians if available
1090  if (jc .eqv. .true.) then
1091  do j = 1, npts2 - 1
1092  do i = 1, npts1 - 1
1093  transf%jacobians_c(i, j) = jacobians_cell(i, j)
1094  end do
1095  end do
1096  else ! if cell-based jacobians are not available, compute them.
1097  ! Fill the values at the mid-point of the cells
1098  do j = 0, npts2 - 2
1099  eta_2 = eta_2_min + delta_eta_2*(real(j, f64) + 0.5_f64)
1100  do i = 0, npts1 - 2
1101  ! it is very bad practice to invoke the mesh methods while
1102  ! we are not even done initializing the mesh object...
1103  eta_1 = eta_1_min + delta_eta_1*(real(i, f64) + 0.5_f64)
1104  transf%x1_cell(i + 1, j + 1) = transf%x1(eta_1, eta_2)
1105  transf%x2_cell(i + 1, j + 1) = transf%x2(eta_1, eta_2)
1106  transf%jacobians_c(i + 1, j + 1) = transf%jacobian(eta_1, eta_2)
1107  end do
1108  end do
1109  end if
1111 
1112  function transf_2d_jacobian_node_discrete(transf, i, j)
1114  sll_real64 :: transf_2d_jacobian_node_discrete
1115  sll_int32, intent(in) :: i
1116  sll_int32, intent(in) :: j
1117  sll_int32 :: num_pts_1
1118  sll_int32 :: num_pts_2
1119 
1120  num_pts_1 = transf%mesh%num_cells1 + 1
1121  num_pts_2 = transf%mesh%num_cells2 + 1
1122  sll_assert((i .ge. 1) .and. (i .le. num_pts_1))
1123  sll_assert((j .ge. 1) .and. (j .le. num_pts_2))
1124  transf_2d_jacobian_node_discrete = transf%jacobians_n(i, j)
1126 
1127  subroutine write_to_file_2d_discrete(transf, output_format)
1128  class(sll_t_coordinate_transformation_2d_discrete), intent(inout) :: transf
1129  sll_int32, intent(in), optional :: output_format
1130  sll_int32 :: local_format
1131  sll_real64, dimension(:, :), pointer :: x1mesh
1132  sll_real64, dimension(:, :), pointer :: x2mesh
1133  sll_int32 :: i1
1134  sll_int32 :: i2
1135  sll_real64 :: eta1
1136  sll_real64 :: eta2
1137  sll_int32 :: ierr
1138  sll_int32 :: file_id
1139  sll_int32 :: npts_eta1
1140  sll_int32 :: npts_eta2
1141  sll_real64 :: eta1_min
1142  sll_real64 :: eta2_min
1143  sll_real64 :: delta_eta1
1144  sll_real64 :: delta_eta2
1145 
1146  npts_eta1 = transf%mesh%num_cells1 + 1
1147  npts_eta2 = transf%mesh%num_cells2 + 1
1148  eta1_min = transf%mesh%eta1_min
1149  eta2_min = transf%mesh%eta1_min
1150  delta_eta1 = transf%mesh%delta_eta1
1151  delta_eta2 = transf%mesh%delta_eta2
1152 
1153  if (.not. present(output_format)) then
1154  local_format = sll_p_io_gnuplot
1155  else
1156  local_format = output_format
1157  end if
1158 
1159  if (.not. transf%written) then
1160 
1161  if (local_format == sll_p_io_xdmf) then
1162  sll_allocate(x1mesh(npts_eta1, npts_eta2), ierr)
1163  sll_allocate(x2mesh(npts_eta1, npts_eta2), ierr)
1164  eta1 = eta1_min
1165  do i1 = 1, npts_eta1
1166  eta2 = eta2_min
1167  do i2 = 1, npts_eta2
1168  x1mesh(i1, i2) = x1_node_discrete(transf, i1, i2)
1169  x2mesh(i1, i2) = x2_node_discrete(transf, i1, i2)
1170  eta2 = eta2 + delta_eta2
1171  end do
1172  eta1 = eta1 + delta_eta1
1173  end do
1174 
1175  call sll_o_xdmf_open(trim(transf%label)//".xmf", transf%label, &
1176  npts_eta1, npts_eta2, file_id, ierr)
1177  call sll_o_xdmf_write_array(transf%label, x1mesh, "x1", ierr)
1178  call sll_o_xdmf_write_array(transf%label, x2mesh, "x2", ierr)
1179  call sll_s_xdmf_close(file_id, ierr)
1180 
1181  else if (local_format == sll_p_io_gnuplot) then
1182 
1183  sll_allocate(x1mesh(npts_eta1, npts_eta2), ierr)
1184  sll_allocate(x2mesh(npts_eta1, npts_eta2), ierr)
1185 
1186  do i1 = 1, npts_eta1
1187  do i2 = 1, npts_eta2
1188  x1mesh(i1, i2) = x1_node_discrete(transf, i1, i2)
1189  x2mesh(i1, i2) = x2_node_discrete(transf, i1, i2)
1190  end do
1191  end do
1192 
1193  call sll_o_gnuplot_2d(npts_eta1, npts_eta2, x1mesh, x2mesh, &
1194  trim(transf%label), ierr)
1195 
1196  else if (local_format == sll_p_io_mtv) then
1197 
1198  sll_allocate(x1mesh(npts_eta1, npts_eta2), ierr)
1199  sll_allocate(x2mesh(npts_eta1, npts_eta2), ierr)
1200 
1201  do i1 = 1, npts_eta1
1202  do i2 = 1, npts_eta2
1203  x1mesh(i1, i2) = x1_node_discrete(transf, i1, i2)
1204  x2mesh(i1, i2) = x2_node_discrete(transf, i1, i2)
1205  end do
1206  end do
1207 
1208  call sll_o_plotmtv_write(npts_eta1, npts_eta2, &
1209  x1mesh, x2mesh, trim(transf%label), ierr)
1210 
1211  else
1212 
1213  print *, 'Not recognized format to write this mesh'
1214  stop
1215 
1216  end if
1217  else
1218  print *, ' Warning, you have already written the mesh '
1219  end if
1220 
1221  transf%written = .true.
1222  end subroutine
1223 
1225  class(sll_t_coordinate_transformation_2d_discrete), intent(inout) :: transf
1226  transf%label = ""
1227  transf%written = .false.
1228  nullify (transf%x1_node)
1229  nullify (transf%x2_node)
1230  nullify (transf%x1_cell)
1231  nullify (transf%x2_cell)
1232  nullify (transf%jacobians_n)
1233  nullify (transf%jacobians_c)
1234 
1235  !call delete( transf%x1_interp)
1236  !call delete( transf%x2_interp)
1237  call sll_o_delete(transf%mesh)
1238  ! Fix: there is a dependency problem where these pointers are not recognized
1239  ! during the linking step. A similar nullification of an abstract class
1240  ! pointer is carried out in the fields_2d type without problems.
1241 ! transf%x1_interp => null() this gives a different message.
1242 !!$ nullify( transf%x1_interp )
1243 !!$ nullify( transf%x2_interp )
1244  end subroutine delete_transformation_2d_discrete
1245 
1246  ! What do we need to initialize fully a discrete coordinate transformation?
1247  ! - logical mesh
1248  ! - label
1249  ! - array with x1 node positions
1250  ! - array with x2 node positions
1251  ! - array with x1 at cell-center positions
1252  ! - array with x2 at cell-center positions
1253  ! - array with jacobians at nodes
1254  ! - array with jacobians at cell-centers
1255  ! - interpolator 2d for x1
1256  ! - interpolator 2d for x2
1257  ! - the file used to initialize the transformation should allow us to
1258  ! initialize all this data. This routine has special rights in that it
1259  ! is allowed to allocate and initialize a logical mesh and the two
1260  ! interpolators.
1261 
1262  ! - Issues to decide:
1263  ! - Will there be a single file format? Or multiple file formats?
1264  ! The transformation can be specified by two 2D arrays of points, or by
1265  ! the spline coefficients...
1266  ! - The BC information is not inside the files we are currently considering,
1267  ! so this should be included.
1268 
1269  subroutine read_from_file_2d_discrete(transf, filename)
1270  class(sll_t_coordinate_transformation_2d_discrete), intent(inout) :: transf
1271  character(len=*), intent(in) :: filename
1272  intrinsic :: trim
1273  character(len=256) :: filename_local
1274  sll_int32 :: io_stat
1275  sll_int32 :: input_file_id
1276  sll_int32 :: ierr
1277  sll_int32 :: spline_deg1
1278  sll_int32 :: spline_deg2
1279  sll_int32 :: num_pts1
1280  sll_int32 :: num_pts2
1281  sll_int32 :: is_rational
1282  character(len=256) :: label
1283  sll_real64, dimension(:), allocatable :: knots1
1284  sll_real64, dimension(:), allocatable :: knots2
1285  sll_real64, dimension(:), allocatable :: control_pts1
1286  sll_real64, dimension(:), allocatable :: control_pts2
1287  sll_real64, dimension(:), allocatable :: weights
1288  sll_real64, dimension(:, :), allocatable :: control_pts1_2d
1289  sll_real64, dimension(:, :), allocatable :: control_pts2_2d
1290  sll_real64, dimension(:, :), allocatable :: weights_2d
1291  sll_real64 :: eta1_min
1292  sll_real64 :: eta1_max
1293  sll_real64 :: eta2_min
1294  sll_real64 :: eta2_max
1295  sll_int32 :: bc_left
1296  sll_int32 :: bc_right
1297  sll_int32 :: bc_bottom
1298  sll_int32 :: bc_top
1299 ! sll_real64, dimension(:,:), allocatable :: nodes1
1300 ! sll_real64, dimension(:,:), allocatable :: nodes2
1301  sll_int32 :: number_cells1, number_cells2
1302  sll_int32 :: sz_knots1, sz_knots2
1303  type(sll_t_cartesian_mesh_2d), pointer :: mesh_2d
1304 
1305  namelist /transf_label/ label
1306  namelist /degree/ spline_deg1, spline_deg2
1307  namelist /shape/ num_pts1, num_pts2 ! it is not the number of points but the number of coeff sdpline in each direction !!
1308  namelist /rational/ is_rational
1309  namelist /knots_1/ knots1
1310  namelist /knots_2/ knots2
1311  namelist /control_points/ control_pts1, control_pts2
1312  namelist /pt_weights/ weights
1313  namelist /logical_mesh_2d/ number_cells1, number_cells2
1314 
1315  if (len(filename) >= 256) then
1316  print *, 'ERROR, read_coefficients_from_file => ', &
1317  'read_from_file_discrete():', &
1318  'filenames longer than 256 characters are not allowed.'
1319  stop
1320  end if
1321  filename_local = trim(filename)
1322 
1323  ! get a new identifier for the file.
1324  call sll_s_new_file_id(input_file_id, ierr)
1325  if (ierr .ne. 0) then
1326  print *, 'ERROR while trying to obtain an unique identifier for file ', &
1327  filename, '. Called from read_coeffs_ad2d().'
1328  stop
1329  end if
1330  open (unit=input_file_id, file=filename_local, status="OLD", iostat=io_stat)
1331  if (io_stat .ne. 0) then
1332  print *, 'ERROR while opening file ', filename, &
1333  '. Called from read_coeffs_ad2d().'
1334  stop
1335  end if
1336 
1337  read (input_file_id, transf_label)
1338  read (input_file_id, degree)
1339  read (input_file_id, shape)
1340  read (input_file_id, rational)
1341  sll_allocate(knots1(num_pts1 + spline_deg1 + 1), ierr)
1342  sll_allocate(knots2(num_pts2 + spline_deg2 + 1), ierr)
1343  read (input_file_id, knots_1)
1344  read (input_file_id, knots_2)
1345  sll_allocate(control_pts1(num_pts1*num_pts2), ierr)
1346  sll_allocate(control_pts2(num_pts1*num_pts2), ierr)
1347  sll_allocate(weights(num_pts1*num_pts2), ierr)
1348  sll_allocate(control_pts1_2d(num_pts1, num_pts2), ierr)
1349  sll_allocate(control_pts2_2d(num_pts1, num_pts2), ierr)
1350  sll_allocate(weights_2d(num_pts1, num_pts2), ierr)
1351 
1352  read (input_file_id, control_points)
1353  control_pts1_2d = reshape(control_pts1, (/num_pts1, num_pts2/))
1354  control_pts2_2d = reshape(control_pts2, (/num_pts1, num_pts2/))
1355  read (input_file_id, pt_weights)
1356  weights_2d = reshape(weights, (/num_pts1, num_pts2/))
1357  read (input_file_id, logical_mesh_2d)
1358  close (input_file_id)
1359 
1360  eta1_min = knots1(1)
1361  eta2_min = knots2(1)
1362  eta1_max = knots1(num_pts1 + spline_deg1 + 1)
1363  eta2_max = knots2(num_pts2 + spline_deg2 + 1)
1364 
1365  ! for the moment we put the boundary condition like a dirichlet
1366  ! boundary condition
1367  ! but we must modified this part <-- this means that this info must
1368  ! come within the input file: ECG
1369 
1370  bc_left = sll_p_dirichlet
1371  bc_right = sll_p_dirichlet
1372  bc_bottom = sll_p_dirichlet
1373  bc_top = sll_p_dirichlet
1374 
1375  sz_knots1 = size(knots1)
1376  sz_knots2 = size(knots2)
1377 
1378  ! Initialization of the interpolator spline 2D in x
1379  ! ACHTUNG we have not delete it <--- What???:ECG
1380  stop "This case in no longer supported"
1381  end subroutine read_from_file_2d_discrete
1382 
Write file for gnuplot to display 2d field.
Create the mtv file to plot a structured mesh (cartesian or curvilinear)
Create a xmf file.
Definition: sll_m_xdmf.F90:76
Write the field in xdmf format.
Definition: sll_m_xdmf.F90:82
Cartesian mesh basic types.
type(sll_t_cartesian_mesh_2d) function, pointer, public sll_f_new_cartesian_mesh_2d(num_cells1, num_cells2, eta1_min, eta1_max, eta2_min, eta2_max)
allocates the memory space for a new 2D cartesian mesh on the heap, initializes it with the given arg...
Abstract class for coordinate transformations.
class(sll_t_cartesian_mesh_2d) function, pointer get_cartesian_mesh_analytic(transf)
real(kind=f64) function x2_cell_discrete(transf, i, j)
real(kind=f64) function x2_discrete(transf, eta1, eta2)
subroutine, public sll_s_coordinate_transformation_2d_analytic_init(transf, label, mesh_2d, x1_func, x2_func, j11_func, j12_func, j21_func, j22_func, params)
real(kind=f64) function, dimension(1:2, 1:2) jacobian_matrix_2d_analytic(transf, eta1, eta2)
type(sll_t_coordinate_transformation_2d_analytic) function, pointer, public sll_f_new_coordinate_transformation_2d_analytic(label, mesh_2d, x1_func, x2_func, j11_func, j12_func, j21_func, j22_func, params)
Create the analytic coordinate transformation.
real(kind=f64) function x2_cell_analytic(transf, i, j)
class(sll_t_cartesian_mesh_2d) function, pointer get_cartesian_mesh_discrete(transf)
subroutine write_to_file_2d_discrete(transf, output_format)
type(sll_t_coordinate_transformation_2d_discrete) function, pointer, public sll_f_new_coordinate_transformation_2d_discrete(mesh_2d, label, x1_interpolator, x2_interpolator, jacobians_n_interpolator, x1_node, x2_node, jacobians_node, x1_cell, x2_cell, jacobians_cell)
Create a new coordinate transformation object.
real(kind=f64) function x1_cell_discrete(transf, i, j)
real(kind=f64) function jacobian_node_analytic(transf, i, j)
real(kind=f64) function x2_analytic(transf, eta1, eta2)
real(kind=f64) function jacobian_2d_cell_discrete(transf, i, j)
real(kind=f64) function x1_analytic(transf, eta1, eta2)
real(kind=f64) function x2_node_discrete(transf, i, j)
real(kind=f64) function, dimension(1:2, 1:2) inverse_jacobian_matrix_2d_discrete(transf, eta1, eta2)
real(kind=f64) function x1_node_discrete(transf, i, j)
real(kind=f64) function x1_node_analytic(transf, i, j)
real(kind=f64) function, dimension(1:2, 1:2) jacobian_matrix_2d_discrete(transf, eta1, eta2)
real(kind=f64) function jacobian_2d_cell_analytic(transf, i, j)
real(kind=f64) function transf_2d_jacobian_node_discrete(transf, i, j)
real(kind=f64) function x1_discrete(transf, eta1, eta2)
subroutine write_to_file_2d_analytic(transf, output_format)
subroutine, public sll_s_coordinate_transformation_2d_discrete_init(transf, mesh_2d, label, x1_interpolator, x2_interpolator, jacobians_n_interpolator, x1_node, x2_node, jacobians_node, x1_cell, x2_cell, jacobians_cell)
real(kind=f64) function x2_node_analytic(transf, i, j)
real(kind=f64) function jacobian_2d_analytic(transf, eta1, eta2)
real(kind=f64) function jacobian_2d_discrete(transf, eta1, eta2)
real(kind=f64) function x1_cell_analytic(transf, i, j)
real(kind=f64) function, dimension(1:2, 1:2) inverse_jacobian_matrix_2d_analytic(transf, eta1, eta2)
Implements the functions to write data file plotable by GNUplot.
abstract data type for 2d interpolation
Implements the functions to write data file plotable by Plotmtv.
Some common numerical utilities.
subroutine, public sll_s_new_file_id(file_id, error)
Get a file unit number free before creating a file.
Module to select the kind parameter.
Implements the functions to write xdmf file plotable by VisIt.
Definition: sll_m_xdmf.F90:24
subroutine, public sll_s_xdmf_close(file_id, error)
Close the XML file and finish to write last lines.
Definition: sll_m_xdmf.F90:895
Base class/basic interface for 2D interpolators.
    Report Typos and Errors