Solution to Worksheet 8 of phy201


!_______________________________________________________________________
! Donev Aleksandar, PHY201, a Fortran 90 program
! that find the magnetic field of a circular ring (11/6/99)
!_______________________________________________________________________

!_______________________________________________________________________
! This module contains the functions that give the
! magnetic field elements dBx and dBz for a current-carrying ring
! placed in the xy plane and for y=0.
! Both functions are Fortran 90 versions of elemental and pure
! functions in Fortran 95 (not supported by the F compiler)
!_______________________________________________________________________
module dB
  use Precision
  implicit none
  public :: dBx,dBz
  real(kind=wp), public :: x,z

  contains
  !___________________________________
  ! This is the x component of dB:
  !___________________________________
  function dBx(theta) result(Bx)
    real(kind=wp), intent(in) :: theta
    real(kind=wp) :: Bx
    Bx=z*cos(theta)/(1+x**2+z**2-2*x*cos(theta))**1.5
  end function dBx

  !___________________________________
  ! This is the z component of dB:
  !___________________________________
  function dBz(theta) result(Bz)
    real(kind=wp), intent(in) :: theta
    real(kind=wp) :: Bz
    Bz=(1-x*cos(theta))/(1+x**2+z**2-2*x*cos(theta))**1.5
  end function dBz

end module dB
!_______________________________________________________________________

!_______________________________________________________________________
module B
  use Precision
  use dB
  use Numerical_Integration, only: AdaptiveIntegral,error_flag
  implicit none
  public
      
  integer, save :: error_status
  real(kind=wp), parameter, private :: pi=3.141592653589793116_wp
  
  contains
  !___________________________________
  ! This is the x component of B:
  !___________________________________
  function Bx(x_,z_) result(Bx_)
    real(kind=wp), intent(in) :: x_, z_
    real(kind=wp) :: Bx_
    real(kind=wp) :: error
    ! I must use these dirty methods because in Fortran
    ! we are restricted about the interface of the function
    ! we can pass on to ready-made routines:
    x=x_
    z=z_
    Bx_=AdaptiveIntegral(f=dBx,a=0.0_wp,b=2.0_wp*pi,error_estimate=error)
    error_status=error_flag
  end function Bx

  !___________________________________
  ! This is the z component of B:
  !___________________________________
  function Bz(x_,z_) result(Bz_)
    real(kind=wp), intent(in) :: x_, z_
    real(kind=wp) :: Bz_
    real(kind=wp) :: error
    x=x_
    z=z_
    Bz_=AdaptiveIntegral(f=dBz,a=0.0_wp,b=2.0_wp*pi,error_estimate=error)
    error_status=error_flag
  end function Bz

  function B_(x_,z_) result(Bxz)
    real(kind=sp), intent(in) :: x_, z_
    real(kind=sp), dimension(2) :: Bxz
    real(kind=wp) :: error
    x=real(x_,wp)
    z=real(z_,wp)
    Bxz(1)=real(AdaptiveIntegral(f=dBx,a=0.0_wp,b=2.0_wp*pi,error_estimate=error),sp)   
    Bxz(2)=real(AdaptiveIntegral(f=dBz,a=0.0_wp,b=2.0_wp*pi,error_estimate=error),sp)
  end function B_

end module B
!_______________________________________________________________________

!_______________________________________________________________________
! The main program B_ring gives the value of the magnetic field
! Bx and Bz for a current-carrying ring placed in the xy plane for y=0
! by calculating a numerical integral using Newton-Cottes formulae.
!_______________________________________________________________________
program B_ring
  use Precision
  use B, only: Bx, Bz, B_, error_status
  USE SimpleGraphics
  USE FunGraphics  
  implicit none

  real(kind=wp) :: x, z
  real(kind=sp), parameter :: length=2.5644_wp
  CHARACTER(LEN=100), DIMENSION(2) :: title
  
  write(unit=*,fmt=*) "Enter the values of x and z:"
  read(unit=*,fmt=*) x,z

  write(unit=*,fmt=*) "Bx=",Bx(x,z)," with error status",error_status
  write(unit=*,fmt=*) "Bz=",Bz(x,z)," with error status",error_status

  title(1)="The magnetic field of a current-carrying ring" 
  title(2)="A. Donev, 10/19/00" 
  CALL InitGraphics(file="ring.png",file_type="XWIN", & 
                    plot_title=title, & 
                    x_label="x",y_label="z",z_label="|B(x,z)|") 
  CALL FunVectorPlot2D(f_xy=B_,xy_range=(/-length,length,-length,length/), &
                       num_points=(/25,25/),plot_spec="11g", &
                       axis=(/-length,length,-length,length,0.1,5.0/),zoom=0.2)
  CALL EndGraphics()   

end program B_ring