I want to incorporate Plplot into the Fortran Tools,
and include a brief introduction in the FT manual.

Here is my first attempt at something beyond just
plotting and labeling a graph. I would appreciate any
comments about how I could use Plplot more
effectively or anything you would care to let me know
about. It creates a little "movie" of heat spreading
through a plate. (The computation was written by
Dick Hendrickson years ago to show a cute, but trivial
use of pointers.) This is a result of using the
documentation, the examples, and lots of trial and
error :-).

One thing I have not figured out yet is I think the
opposite of what somewhat who posted recently was
trying to do. I would like to destroy a plot and continue
execution of the program (to create the next plot). The
way heat.f90 works is that each plot is laid over the
previous one. I think somebody else asked about
stopping the program, but keeping the plot displayed.

Alan: I also attach my version of example x00f.f90. The
plotting stuff is all the same, but it uses some perhaps slightly
updated Fortran style. Use any part of it you like (you will
have to put the stuff at the top back on--didn't want to
blame you for anything you don't want blame/credit for).

-- 
Walt Brainerd
program ft_x00f

! This is a modified version of x00f.f90
! which was written by Alan Irwin

   use plplot
   implicit none

   integer, parameter :: NSIZE = 100

   real(kind=plflt), dimension(0:NSIZE) :: x, y

   real(kind=plflt) :: xmin =   0.0_plflt, &
                       xmax =   1.0_plflt, &
                       ymin =   0.0_plflt, &
                       ymax = 100.0_plflt
   integer :: i

   ! Prepare data to be plotted.
   ! x = .00, .01, .02, ..., .99, 1.00
   x = [(i, i=0,NSIZE)] / real(NSIZE)
   y = ymax * x**2

   ! Parse and process command line arguments
   call plparseopts( PL_PARSE_FULL )

   ! Initialize plplot
   call plinit( )

   ! Create a labelled box to hold the plot.
   call plenv( xmin, xmax, ymin, ymax, just=0, axis=0 )
   call pllab( "x", "y=100 x#u2#d", &
               "Simple PLplot demo of a 2D line plot" )

   ! Plot the data that was prepared above.
   call plline( x, y )

   ! Close PLplot library
   call plend( )

end program ft_x00f
module globals
   use plplot
   implicit none

   ! Plate is nn x nn
   integer, parameter :: nn = 50, &
                         plot_frequency = 5*nn, &
                         pause_time = 1
end module globals

module plotting_module

   use globals
   implicit none
   private
   public :: initialize_plot, draw_plot
   integer, parameter :: nr_contours = 100
   integer, parameter :: nr_bar_levels = 20
   real(kind=plflt), dimension(nr_contours+1) :: contours
   integer :: cont_color
   real(kind=plflt) :: fill_width, cont_width
   real(kind=plflt) :: bar_width, bar_height
   character(len=20) :: axis_opts(1)
   integer :: num_bar_values(1)
   real(kind=plflt) :: bar_values(1, nr_bar_levels+1)
   real(kind=plflt) :: axis_ticks(1)
   integer :: axis_subticks(1)
   character(len=100) :: labels(1)
   integer :: label_opts(1)
   character(len=1) :: defined = " "

contains

subroutine initialize_plot()
   integer :: i
   call plspal1("cmap1_blue_red.pal", 1)
   contours = &
      [(i, i=0, nr_contours)] / real(nr_contours)
   bar_values(1, :) = &
      [(i, i=0, nr_bar_levels)] / real(nr_bar_levels)
   num_bar_values = nr_bar_levels + 1
   fill_width = 2
   cont_color = 0
   cont_width = 1
   axis_opts = "bcvtm"
   bar_width = 0
   bar_height = 0
   axis_ticks = 0
   axis_subticks = 0
   label_opts = PL_COLORBAR_LABEL_BOTTOM
   labels = "Temp"
end subroutine initialize_plot

subroutine draw_plot(plate, stop)
   real, dimension(:, :), intent(in) :: plate
   logical, optional, intent(in) :: stop
   integer :: i, j, p

   call initialize_plot()
   call plsdev("wingcc")
   call plspage(0.0_plflt, 0.0_plflt, &
                600, 600, 100, 100)
   call plscolbg(255, 255, 255)  ! White background
   call plinit()
   call pladv(0)
   call plvpor(0.05_plflt, 0.85_plflt, 0.1_plflt, 0.9_plflt)
   call plwind(0.0_plflt, 1.0_plflt, 0.0_plflt, 1.0_plflt)

   call plshades(transpose(real(plate,kind=plflt)), defined, &
                 0.0_plflt, 1.0_plflt, 1.0_plflt, 0.0_plflt, &
                 contours, &
                 fill_width, cont_color, cont_width)

   ! Smaller text for color bar labels
   call plschr(0.0_plflt, 0.65_plflt)

   call plcolorbar(bar_width, bar_height, &
      ior(PL_COLORBAR_SHADE, PL_COLORBAR_SHADE_LABEL), 0, &
      0.04_plflt, 0.0_plflt, 0.0375_plflt, 0.875_plflt, &
      0, 1, 1, &
      0.0_plflt, 0.0_plflt, &
      cont_color, cont_width, &
      label_opts, labels, &
      axis_opts, axis_ticks, axis_subticks, &
      num_bar_values, bar_values)

   ! Reset text sizes
   call plschr(0.0_plflt, 1.0_plflt)
   call pllab("Heat transfer in a plate", "", "")

   if(present(stop)) then
      if(stop) return
   end if

   ! More plots
   ! Remove plspause to wait for CR
   call plspause(.false.)
   call plend()
   call plspause(.true.)
   call sleep(pause_time)

end subroutine draw_plot

end module plotting_module

module heat_module

   use globals
   use plotting_module
   implicit none
   private

   real, dimension(nn,nn), target :: plate
   real, dimension(nn-2,nn-2)     :: temp
   real, pointer, dimension(:,:)  :: n, e, s, w, inside
   real, parameter                :: tolerance = 1.0e-4
   integer :: niter = 0

   public :: initialize_plate, compute_heat

contains

subroutine initialize_plate()

   integer :: i
   plate = 0
   plate(:, 1) = 1.0  ! boundary values
   plate(1, :) = [ ( real(i)/nn, i = nn,1,-1 ) ]

!  Point to parts of the plate
   inside => plate(2:nn-1, 2:nn-1)
   n => plate(1:nn-2, 2:nn-1)
   s => plate(3:nn, 2:nn-1)
   e => plate(2:nn-1, 3:nn)
   w => plate(2:nn-1, 1:nn-2)

end subroutine initialize_plate

subroutine compute_heat()

   real    :: diff

!  Iterate
   do
      niter = niter + 1
      temp = (n + e + s + w)/4.0
      diff = maxval(abs(temp-inside))
      inside = temp
      if (diff < tolerance) exit
      if (modulo(niter, plot_frequency) == 0) then
         print *, niter, diff
         call draw_plot(plate)
      end if
   end do

   call draw_plot(plate, stop=.true.)

end subroutine compute_heat

end module heat_module

program heat

   use plplot
   use heat_module
   use plotting_module
   implicit none

   call plparseopts(PL_PARSE_FULL)
   call initialize_plate()
   call compute_heat()

   call plend()

end program heat
------------------------------------------------------------------------------
Is your legacy SCM system holding you back? Join Perforce May 7 to find out:
&#149; 3 signs your SCM is hindering your productivity
&#149; Requirements for releasing software faster
&#149; Expert tips and advice for migrating your SCM now
http://p.sf.net/sfu/perforce
_______________________________________________
Plplot-general mailing list
Plplot-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-general

Reply via email to