!>
!> @file test_gvec1d.f90
!>
!> @brief
!>
!> @copyright
!> Copyright (©) 2021 EPFL (Ecole Polytechnique Fédérale de Lausanne)
!> SPC (Swiss Plasma Center)
!>
!> SPClibs is free software: you can redistribute it and/or modify it under
!> the terms of the GNU Lesser General Public License as published by the Free
!> Software Foundation, either version 3 of the License, or (at your option)
!> any later version.
!>
!> SPClibs is distributed in the hope that it will be useful, but WITHOUT ANY
!> WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
!> FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
!>
!> You should have received a copy of the GNU Lesser General Public License
!> along with this program. If not, see .
!>
!> @authors
!> (in alphabetical order)
!> @author Trach-Minh Tran
!>
!
! Test implementation of 1D vectors with arbirary
! vector bounds and ghost cell width.
!
! T.M. Tran (09/2013)
!
MODULE gvector
USE iso_fortran_env, ONLY : rkind => real64
IMPLICIT NONE
PRIVATE
PUBLIC :: rkind, gvector_1d, disp, norm2, &
& OPERATOR(+), OPERATOR(-), OPERATOR(*), &
& ASSIGNMENT(=)
TYPE gvector_1d
INTEGER :: s, e, g
REAL(rkind), ALLOCATABLE :: val(:)
END TYPE gvector_1d
INTERFACE gvector_1d
MODULE PROCEDURE constructor
END INTERFACE gvector_1d
INTERFACE OPERATOR(+)
MODULE PROCEDURE add_scal
MODULE PROCEDURE add_vec
END INTERFACE OPERATOR(+)
INTERFACE OPERATOR(-)
MODULE PROCEDURE minus_vec
MODULE PROCEDURE substract_vec
END INTERFACE OPERATOR(-)
INTERFACE OPERATOR(*)
MODULE PROCEDURE scale_left
MODULE PROCEDURE scale_right
END INTERFACE OPERATOR(*)
INTERFACE ASSIGNMENT(=)
MODULE PROCEDURE from_scal
MODULE PROCEDURE from_vec
END INTERFACE ASSIGNMENT(=)
INTERFACE norm2
module procedure norm2_gvector_1d
END INTERFACE norm2
CONTAINS
FUNCTION constructor(s, e, g) RESULT(res)
INTEGER, INTENT(in) :: s, e
INTEGER, OPTIONAL, INTENT(in) :: g
TYPE(gvector_1d) :: res
INTEGER :: lb, ub
res%g= 0
IF(PRESENT(g)) res%g=g
res%s=s
res%e=e
lb = res%s-res%g
ub = res%e+res%g
ALLOCATE(res%val(lb:ub))
res%val = -9999.0
END FUNCTION constructor
FUNCTION add_vec(lhs, rhs) RESULT(res)
TYPE(gvector_1d), INTENT(in) :: lhs, rhs
TYPE(gvector_1d) :: res
res = gvector_1d(lhs%s, lhs%e, lhs%g)
res%val(res%s:res%e) = lhs%val(res%s:res%e) + rhs%val(res%s:res%e)
END FUNCTION add_vec
FUNCTION add_scal(lhs, rhs) RESULT(res)
TYPE(gvector_1d), INTENT(in) :: lhs
REAL(rkind), INTENT(in) :: rhs
TYPE(gvector_1d) :: res
res = gvector_1d(lhs%s, lhs%e, lhs%g)
res%val(res%s:res%e) = lhs%val(res%s:res%e) + rhs
END FUNCTION add_scal
FUNCTION minus_vec(this) RESULT(res)
TYPE(gvector_1d), INTENT(in) :: this
TYPE(gvector_1d) :: res
res = gvector_1d(this%s, this%e, this%g)
res%val(res%s:res%e) = -this%val(res%s:res%e)
END FUNCTION minus_vec
FUNCTION substract_vec(lhs, rhs) RESULT(res)
TYPE(gvector_1d), INTENT(in) :: lhs, rhs
TYPE(gvector_1d) :: res
res = gvector_1d(lhs%s, lhs%e, lhs%g)
res = lhs + (-rhs)
END FUNCTION substract_vec
FUNCTION scale_left(lhs, rhs) RESULT(res)
REAL(rkind), INTENT(in) :: lhs
TYPE(gvector_1d), INTENT(in) :: rhs
TYPE(gvector_1d) :: res
res = gvector_1d(rhs%s, rhs%e, rhs%g)
res%val(res%s:res%e) = lhs * rhs%val(res%s:res%e)
END FUNCTION scale_left
FUNCTION scale_right(lhs, rhs) RESULT(res)
TYPE(gvector_1d), INTENT(in) :: lhs
REAL(rkind), INTENT(in) :: rhs
TYPE(gvector_1d) :: res
res = gvector_1d(lhs%s, lhs%e, lhs%g)
res%val(res%s:res%e) = rhs * lhs%val(res%s:res%e)
END FUNCTION scale_right
SUBROUTINE from_vec(lhs, rhs)
TYPE(gvector_1d), INTENT(inout) :: lhs
REAL(rkind), INTENT(in) :: rhs(:)
INTEGER :: n
n = lhs%e - lhs%s + 1
IF(SIZE(rhs) .NE. n) THEN
PRINT*, 'from_vec: sizes of rhs and lhs not equal!'
STOP
END IF
lhs%val(lhs%s:lhs%e) = rhs(1:n)
END SUBROUTINE from_vec
SUBROUTINE from_scal(lhs, rhs)
TYPE(gvector_1d), INTENT(inout) :: lhs
REAL(rkind), INTENT(in) :: rhs
lhs%val(lhs%s:lhs%e) = rhs
END SUBROUTINE from_scal
SUBROUTINE disp(str,this)
CHARACTER(len=*), INTENT(in) :: str
TYPE(gvector_1d), INTENT(in) :: this
WRITE(*,'(/a,3i6)') str//': s, e, g =', this%s, this%e, this%g
WRITE(*,'(10(1pe12.3))') this%val
END SUBROUTINE disp
FUNCTION norm2_gvector_1d(this) RESULT(res)
TYPE(gvector_1d), INTENT(in) :: this
REAL(rkind) :: res
res = NORM2(this%val(this%s:this%e))
END FUNCTION norm2_gvector_1d
END MODULE gvector
PROGRAM main
USE gvector
IMPLICIT NONE
INTEGER :: s=0, e=5, g=1
INTEGER :: i, lb, ub
REAL(rkind) :: a=0.1
TYPE(gvector_1d) :: v1, v2, v3
!
lb = s-g
ub = e+g
v1 = gvector_1d(s, e, g)
v1%val(s:e) = [ (i, i=s,e) ]
CALL disp('v1', v1)
!
v2 = v1 + a*v1
CALL disp('v1+a*v1', v2)
!
v3 = v1 - v1*a
CALL disp('v1-v1*a', v3)
!
WRITE(*,'(a,1pe12.3)') 'norm of v1 =', NORM2(v1)
WRITE(*,'(a,1pe12.3)') 'norm of v1-a*v1 =', NORM2(v1-a*v1)
!
v1 = 0.0d0
CALL disp('Should be all zero', v1)
v2 = [ 1.d0, 2.d0, 3.d0, 4.d0, 5.d0, 6.d0 ]
CALL disp('Should be (1. 2. 3. 4. 5. 6.)', v2)
END PROGRAM main