Repository: kookma/ogpf Branch: master Commit: bd18021949be Files: 11 Total size: 187.6 KB Directory structure: gitextract_axg7b2oj/ ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── doc/ │ └── readme.txt ├── example/ │ └── demo.f90 ├── fpm.toml ├── meson.build ├── revision.txt ├── sample_script.gp └── src/ └── ogpf.f90 ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Prerequisites *.d # Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Fortran module files *.mod *.smod # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app # fpm build directory build* bin* ================================================ FILE: LICENSE ================================================ Copyright (c) 2012-2018 Mohammad Rahmani ! Author: Mohammad Rahmani ! Chem Eng Dep., Amirkabir Uni. of Tech ! Tehran, Ir ! url: aut.ac.ir/m.rahmani ! github: github.com/kookma ! email: m[dot]rahmani[at]aut[dot]ac[dot]ir Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ # # This Makefile was generated by Code::Blocks IDE. # SRCS_f90d1 = \ ogpf.f90 SRCS_f90d2 = \ demo.f90 OBJS_f90d1 = \ ogpf.o OBJS_f90d2 = \ demo.o SRC_DIR_f90d1 = \ ./src/ SRC_DIR_f90d2 = \ ./example/ OBJS_DIR = ./obj/Debug/ EXE_DIR = ./bin/Debug/ EXE = ogpf.exe FC = gfortran.exe LD = gfortran.exe IDIR = CFLAGS = -Wall -std=f2008 -Wl, -J$(OBJS_DIR) $(IDIR) LFLAGS = LIBS = VPATH = $(SRC_DIR_f90d1):$(OBJS_DIR):$(SRC_DIR_f90d2) OBJS = $(addprefix $(OBJS_DIR), $(OBJS_f90d1) $(OBJS_f90d2)) all : $(EXE) $(EXE) : $(OBJS_f90d1) $(OBJS_f90d2) @mkdir -p $(EXE_DIR) $(LD) -o $(EXE_DIR)$(EXE) $(OBJS) $(LFLAGS) $(LIBS) $(OBJS_f90d1): @mkdir -p $(OBJS_DIR) $(FC) $(CFLAGS) -c $(SRC_DIR_f90d1)$(@:.o=.f90) -o $(OBJS_DIR)$@ $(OBJS_f90d2): @mkdir -p $(OBJS_DIR) $(FC) $(CFLAGS) -c $(SRC_DIR_f90d2)$(@:.o=.f90) -o $(OBJS_DIR)$@ clean : rm -f $(OBJS_DIR)*.* rm -f $(EXE_DIR)$(EXE) # Dependencies of files demo.o: \ demo.f90 \ ogpf.o ogpf.o: \ ogpf.f90 ================================================ FILE: README.md ================================================ # ogpf Object Based Interface to GnuPlot from Fortran (ogpf) ## Installation __Prerequisite:__ [gnuplot](http://www.gnuplot.info/) must be installed on your system. ### Zero Installation Library The ogpf is a **zero installation library**! Just copy and paste the `ogpf.f90` in your project folder or in your library folder and use it! No any further step is required. However if you like to add ogpf to your projects through package managers, builders, installers see below options! ###
Fortran Package Manager (fpm) >To use ogpf with your [fpm](https://github.com/fortran-lang/fpm) project, add the following to your package manifest file (`fpm.toml`): > >```toml >[dependencies] >ogpf = { git = "https://github.com/kookma/ogpf.git" } >``` > >You can then `use` the package as normal in your Fortran program with `use ogpf`. > >To run the example program in this package with fpm: > >```sh >$ git clone https://github.com/kookma/ogpf.git >$ cd ogpf >$ fpm build >$ fpm run --example >```
###
Meson Builder >The alternative is through the use of the [Meson builder](https://mesonbuild.com/index.html), which is >multiplatform and multi source language build system. You can just use the ogpf git repo as a >subproject in your own meson project. If you're unfamiliar with it, just read this >[begginer's guide](https://mesonbuild.com/SimpleStart.html). > >After learning the basics, you can create a folder called subprojects on the root of your project >and create a file inside with the following content: > >``` >[wrap-git] >url=https://github.com/kookma/ogpf >revision=head >``` > >Then on the meson.build file you have to import the subproject and grab the library variable. >This is a sample meson.build file: > >```python >project('research','fortran') > >ogpf_proj = subproject('ogpf') >ogpf_dep = ogpf_proj.get_variable('ogpf_dep') > >executable('research', > dependencies: ogpf_dep) >``` >and all the compiler flags will be handled.
# Usage Make sure you have a working version of [gnuplot](http://www.gnuplot.info/) must be installed on your system. Start with provideed examples. ## 2D Plots Simple plot | Animation :-----------------------------:|:------------------------------------: ![Example 04](doc/exmp04.png) | ![Example 09](doc/exmp09.gif) ## 3D Plots Surface | Contour :-----------------------------:|:------------------------------------: ![Example 04](doc/exmp105.png) | ![Example 09](doc/exmp105_2.png) ### GnuPlot Interface Purpose: Object Based Interface to GnuPlot from Fortran (ogpf) Platform: Windows XP/Vista/7/10, Linux (It should work on other platforms, e.g Mac see the finalize_plot subroutine in ogpf.f90) Language: Fortran 2003 and 2008 Requires: 1. Fortran 2003 compiler (e.g gfortran 4.7, IVF 12.1, and later ...) There is only two more features needs Fortran 2008 standard execute_command_line and passing internal function as argument. 2. gnuplot 5 and higher (other previous version can be used) Author: Mohammad Rahmani Chem Eng Dep., Amirkabir Uni. of Tech Tehran, Ir url: aut.ac.ir/m.rahmani github: github.com/kookma email: m[dot]rahmani[at]aut[dot]ac[dot]ir License: MIT. Please always give a link to this repo ## PLotting Capabilities ### 2D Plots * plot(v) * plot(x,y) * plot(x,y, linespec) * plot(x1,y1,ls1, x2,y2,ls2, x3,y3,ls3, x4,y4,ls4) * plot(x, M) * semilogx(x,y) * semilogy(x,y) * loglog(x,y) ### 3D Plots * surf(x,y,z) * surf(x,y,z,lspec) * surf(x,y,z, palette) * surf(z, palette) * contour(x,y,z,palette) * contour(z,palette) ### Animation * animation_start(delay) * animation_show() ### Multiplot * multiplot(rows, cols) ## Mathematical Utility Functions * linspace(a,b,n) * linspace(a,b) * arange(a,b,dx) * meshgrid(X,Y, xgv,ygv) * meshgrid(X,Y, xgv) ## Color palette Nine different color palettes are available. See [Ann Schnider](https://github.com/aschn/gnuplot-colorbrewer) gnuplot color palettes and [Gnuplotting](https://github.com/Gnuplotting/gnuplot-palettes). These color palettes can be used with: > `surf(x,y,z,palette='plt-name')` > `contour(x,y,z,palette='plt-name')` * set1 * set2 * set3 * palette1 * palette2 * paired * dark2 * accent * jet ## The ogpf library other features There are plenty of commands to customise the plots. This includes: * Plot annotation (e.g. title, xlabel, ylabel, and zlabel) * Axes setting (e.g. xrange, yrange, zrange, and grid) ```fortran call gp%axis([-1.0,+1.0]) ! Sets xrange call gp%axis([-1.0,+1.0,-2.0,+2.0]) ! Sets both xrange and yrange call gp%axis([-1.0,+1.0,-2.0,+2.0,-3.0,+3.0]) ! Sets all axis at same time call gp%xlim([-1.0,+1.0]) ! Sets only the xrange call gp%ylim([-2.0,+3.0]) ! Sets only the yrange call gp%zlim([-3.0,+3.0]) ! Sets only the zrange ``` * Line and marker color and style * Gnuplot options (e.g. fonts, tics format, frame format,... ) ### The ogpf options command The option command is a very powerful command and can be used to customize the gnuplot in many ways. Options can be set by calling the ogpf options. In every call, it is possible to set several options separated by semicolon or options can be set by several calls. Below shows few samples: * **Sample 1** Set the legend (key) at the right bottom of window `call gp%options('set key bottom right')` * **Sample 2** Define a new line style `call gp%options('set style line 1 lc rgb "blue" lt 1 lw 2 pt 6 ps 1.5')` * **Sample 3** Use several options each uses separate command `call gp%options('set tics')` `call gp%options('set tics font ",8"') ! font size for tics` * **Sample 4** Set several options at the same time using semicolon as delimiter `call gp%options('unset tics; unset colorbox') ` # Demo There is a collection of examples in demo.f90 to show the capabilities of ogpf. ### Easy to use To use ogpf in your project, add the library file to your fortran project (code) * ogpf.f90 (the main library) For details see 'demo.f90' ##### Important Note To use ogpf on other operating system, you may need to modify the terminal type and fonts in the section of **Configuration Parameters**. A Makefile has been provided to build the demo from command line. ### Example codes This section shows selected example codes from **demo.f90** * **Example 1** ```fortran SUBROUTINE Exmp01 !............................................................................... !Example 1: A very basic example !............................................................................... TYPE(gpf):: gp INTEGER, PARAMETER:: n=17 Real(wp):: x(n) Real(wp):: y(n) ! Input data x=dble([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8]) y=dble([66,51,38,27,18,11,6,3,2,3,6,11,18,27,38,51,66]) ! Annotation: set title, xlabel, ylabel CALL gp%title('Example 1. A simple xy plot') CALL gp%xlabel('my x axis ...') CALL gp%ylabel('my y axis ...') Call gp%options('set style data linespoints') !Call Plot to draw a vector against a vector of data CALL gp%plot(x, y) END SUBROUTINE Exmp01 ``` Will produce ![Example 01](doc/exmp01.png) * **Example 04** Plot several data series at the same time ```fortran subroutine exmp04 type(gpf):: gp integer, parameter:: n=50 integer, parameter:: m=65 real(wp):: x(n) real(wp):: y(n) real(wp):: xv(m) real(wp):: yv(m) real(wp), parameter :: pi=4.d0*atan(1.d0) ! Input data x=linspace(-pi,pi,n) !linspace is a utility function from module ogpf y=sin(x) xv=linspace(0.d0, 2.d0*pi,m) yv=cos(2.d0*xv) ! This is the maximum number of plot can be drawn at the same time ! If you have more data see, you can plot can be used with matrices! call gp%title('Example 4. Plot four data sets using gnuplot') call gp%options('set key top left; set grid') call gp%plot(x,y, 'title "sin(x)"', & xv,yv, 'with lp lt 6 title "cos(2x)"', & xv, 2.d0*yv, 'title "2cos(2x)" lt 7', & xv, 0.5d0*yv, 'title "0.5cos(2x)" with points pt 8') ! Another example with keyboard arguments call gp%plot(x1=x,y1=y,x2=xv,y2=yv) end subroutine exmp04 ``` Will produce ![Example 04](doc/exmp04.png) ![Example 04](doc/exmp04_2.png) * **Example 05** ```fortran SUBROUTINE Exmp05 !............................................................................... ! Example 5: Use line style and legends !............................................................................... TYPE(gpf):: gplot INTEGER, PARAMETER:: n=50 Real(wp):: x(n) Real(wp):: ys(n) Real(wp):: yc(n) Real(wp):: ysc(n) Real(wp), PARAMETER :: pi=4.d0*atan(1.d0) ! Input data x=linspace(-2.d0*pi,2.d0*pi,n) !linspace is a utility function from module Utils ys=sin(x) yc=exp(-0.1d0*x)*cos(x) ysc=sin(x/2.d0)*cos(2.d0*x) ! Annotation, set title, xlabel, ylabel CALL gplot%title('Example 5. A sample with style and legends') CALL gplot%xlabel('x, rad') CALL gplot%ylabel('y, dimensionless') ! Plot to draw three set of data CALL gplot%plot(x,ys,'title "sin" with lines lt 5 lc rgb "#0008B0"', & x,yc,'title "cos" with points lt 6 lc rgb "#FF1100"', & x,ysc,'title "sin(x/2)cos(2x)" with lp lt 7 lc rgb "#00AA04"' ) END SUBROUTINE Exmp05 ``` Will produce ![Example 05](doc/exmp05.png) * **Example 06** ```fortran subroutine exmp06 type(gpf):: gplot integer, parameter:: n=125 real(wp):: x(n) real(wp):: y(n) real(wp), parameter :: pi=4.d0*atan(1.d0) ! Input data x=linspace(0.d0,pi*2.d0,n) !linspace is a utility function from module Utils y=sin(6.d0*x)*exp(-x) ! Annotation, set title, xlabel, ylabel call gplot%title('Example 6. A sample shows sin(x) and its zero on the plot') call gplot%xlabel('x, rad') call gplot%ylabel('sin(x), dimensionless') call gplot%options('set grid') ! Plot to draw two set of data, a series and a single point call gplot%plot(x,y,'title "sin(x)" with lines lt 2 lw 3', & [pi],[0.d0],'title "zero" with points pt 7 ps 3 lc rgb "#FF0000"') end subroutine exmp06 ``` Will produce ![Example 06](doc/exmp06.png) * **Example 08** Plotting matrix against a vector with customized linestyles ```fortran subroutine exmp08 type(gpf):: matplot integer, parameter:: n=25, m=6 integer :: i real(wp):: tf real(wp):: vo real(wp):: g real(wp):: t(n) real(wp):: y(n,m) !Create data tf=10.d0 g=32.d0; t=linspace(0.d0,tf,n) do i = 1, m vo = 25.0d0 * i y(:, i) = vo*t-0.5d0*g*t**2 end do !Draw the matrix y againest vector x call matplot%title('Example 8. Plotting a Matrix against a vector') call matplot%xlabel ('t, sec') call matplot%ylabel ('y, feet') call matplot%options('set xrange[0:10];set yrange [0:400];') call matplot%plot(t, y) !Another Matrix plot with legends and line specification call matplot%title('Example 8.2: Matrix plot, legends and linespec') call matplot%plot(t, 2.0d0*y(:,3:4), & lspec='t "vo=100" w lp lt 6 ps 3 lw 2;& & t "v=125" w lp lt 7 ps 3 lw 2 lc rgb "#ad6000"') end subroutine exmp08 ``` Will produce ![Example 08](doc/exmp08.png) ![Example 08](doc/exmp08_2.png) * **Example 9** Animation with 2D plot ```fortran subroutine exmp09 type(gpf):: gp integer, parameter:: n = 35 real(wp), parameter :: pi = 4.d0*atan(1.d0) real(wp):: x(n) real(wp):: y(n), z(n) integer :: i x=linspace(-pi, pi,n) y = 0.0_wp z = 0.0_wp call gp%animation_start(1.0) ! start animation, set delay is one second between frames call gp%axis([-pi, pi, -1.2_wp, 1.2_wp]) call gp%options('set grid') ! add frames do i=1, n, 10 y(i) = sin(x(i)) z(i) = cos(x(i)) ! each plot command adds one frame call gp%plot(x(1:i),y(1:i), 'w lines lc "red" lw 2', & x(i:i), y(i:i),'w points ps 3 pt 7 lc "red"', & x(1:i),z(1:i), 'w lines lc "blue" lw 2', & x(i:i), z(i:i), 'w points ps 3 pt 7 lc "blue"' ) end do ! finalize and show frames one by one with delay between them ! as set by animation_start call gp%animation_show() end subroutine exmp09 ``` will produce ![Example 09](doc/exmp09.gif) * **Example 10** Use options ```fortran subroutine exmp10() type(gpf):: mp real(wp):: x(15) real(wp):: y(15) !Options is a dynamic length string and can set all kind of gnuplot call mp%options('set style line 1 lc rgb "#0060ad" lt 1 lw 2 pt 5 ps 1.5 # --- blue') call mp%options('set style line 2 lc rgb "#ad6000" lt 2 lw 2 pt 6 ps 1.5 # --- red') call mp%options('set style line 3 lc rgb "#00ad00" lt 2 lw 2 pt 7 ps 1.5 # --- green') ! this is a multipart string spanned over several lines call mp%options('& &set style data linespoints;& &set xrange [0.1:100];& &set yrange [0.01:10000];& &set autoscale') call mp%options('set key top left') ! set the key location x=linspace(0.1d0,100d0,15); y=x**2; call mp%title("Example 10. x vs. x^2") call mp%plot(x1=x, y1=1.50*y, ls1='t "y=1.5x^2" ls 1', & x2=x, y2=2.00*y, ls2='t "y=2.0x^2" ls 2', & x3=x, y3=2.50*y, ls3='t "y=2.5x^2" ls 3') call mp%reset() call mp%title('Reset to initial setting') call mp%plot(x,2*y) end subroutine exmp10 ``` The first output is: ![Example 09](doc/exmp10.png) * **Example 11** ```fortran subroutine exmp11 type(gpf):: gp integer, parameter :: n=125 real(wp):: t(n) real(wp):: r(n) real(wp):: pi=4.d0*atan(1.d0) !1. reset gplot !!! CALL gp%reset() ! TODOD: There is a problem with reset, persist is off by reset !2. set option, and set plot as polar call gp%options("& &set polar;& &set trange [-pi:pi]") ! 3. create data t=linspace(-pi,pi,n) r=sin(3.d0*t) !Annotation, set title, xlabel, ylabel call gp%title("Example 11: simple polar plot") call gp%xlabel("x,...") call gp%ylabel("y,...") !Call plot method call gp%plot(t,r, 'title "sin(3t)"') call gp%plot(t, cos(4*t)) end subroutine exmp11 ``` Will produce ![Example 11](doc/exmp11.png) ![Example 11](doc/exmp11_2.png) ### Logarithmic scale * **Example 13** ```fortran subroutine exmp13 type(gpf):: gp integer, parameter :: n=25 real(wp):: x(n) real(wp):: y(n) ! 1. create data x=linspace(0.1d0,10.d0,n) y=5.d0*x**3+4.d0*x**2+3.d0*x+1.d0 !Annotation, set title, xlabel, ylabel call gp%title("Example 13: A simple matrix plot with semi-log y") call gp%ylabel("y,logarithmic scale") call gp%xlabel("x, normal scale") ! plot a matrix against vector in logarithmic y axis with line specification call gp%semilogy(x,reshape([y,10.d0*y],[n,2]), 'with lines lt 8; with points pt 7') end subroutine exmp13 ``` will produce ![Example 13](doc/exmp13.png) * **Example 14** ```fortran subroutine exmp14 type(gpf):: gp integer, parameter :: n=75 real(wp):: x(n) real(wp):: y(n) real(wp):: pi=4.d0*atan(1.d0) ! 1. create data x=exp(linspace(0.d0,2.d0*pi,n)) y=50.d0+exp( 3.d0* linspace(0.d0,2.d0*pi,n) ) ! 2. Annotation, set title, xlabel, ylabel call gp%title("Example 14: A loglog plot") call gp%xlabel("x,logarithmic scale") call gp%ylabel("y,logarithmic scale") ! 3. Set grid on call gp%options('set grid xtics ytics mxtics') ! 4. Call plot method call gp%loglog(x,y) end subroutine exmp14 ``` will produce ![Example 14](doc/exmp14.png) * **Example 16** Save the script file for future use ```fortran subroutine exmp16() type(gpf):: gp real(wp):: pi=4.d0*atan(1.d0) integer, parameter :: n=100 real(wp) :: x(n) real(wp) :: y(n) real(wp) :: z(n) ! create data x = linspace(-pi, 3.0d0*pi) y = sin(2.0d0*x)*exp(-x/5.0d0) z = cos(2.0d0*x)*exp(-x/5.0d0) ! several gnuplot optuons call gp%options('set border linewidth 1.5') call gp%options('set style line 1 lc rgb "#ad6009" lt 1 lw 2 pt 7 ps 1.5 # --- red like') call gp%options('set style line 2 lc rgb "#00ad09" lt 2 lw 2 pt 6 ps 1.5 # --- green like') call gp%options('unset key') call gp%options('set grid') call gp%options('set ytics 1') call gp%options('set tics scale 0.75') call gp%title("Example 16. Save the script into file for future use") call gp%xlabel("x...") call gp%ylabel("y...") ! save the script into a file call gp%filename("Example16.gp") call gp%plot(x, y, ls1='with lp ls 1', x2=x, y2=z, ls2='with lp ls 2') print* ! empty line print*, 'Plot commands were written in Example16.gp successfully' print*, 'Open gnuplot and load this script file to plot the results!' print* ! empty line end subroutine exmp16 ``` will produce ![Example 16](doc/exmp16.png) * **Example 17** Use add_script and run_script to do versatile operation with gnuplot ```fortran subroutine exmp17() ! Script is used to create multi window plots ! Each "set term wxt " creates a new window type(gpf):: gp call gp%add_script('set term wxt 0 title "My first plot" size 640,480') call gp%add_script('set title "Example 17. Multi windows plot using script"') call gp%add_script('plot x*x+2*x+1') call gp%add_script('set term wxt 1 title "My second plot"') call gp%add_script('set ylabel "xsin(x)"') call gp%add_script('plot x*sin(x)') call gp%run_script() end subroutine exmp17 ``` will produce ![Example 17](doc/exmp17.png) ![Example 17](doc/exmp17_2.png) * **Example 18** ```fortran subroutine exmp18() !Use gnuplot script !to send a special external script file to gnuplot !the file is an external file here is called "simple.plt" type(gpf):: gp ! add some options and commands call gp%title("Example 18. Running an external script file") call gp%add_script('load "sample_script.gp" ') ! run script call gp%run_script() end subroutine exmp18 ``` Will produce ![Example 18](doc/exmp18.png) * **Example 20** Scatter plot ```fortran subroutine exmp20() !............................................................................... ! Example 20: Making a scatter plot !............................................................................... type(gpf):: gp integer, parameter :: n=750 real(wp) :: x(n), y(n), ym(n), noise(n), d(n) real(wp) :: a, b ! generate data a = 00.0_wp b = 05.0_wp ! 1. generate the model data x = linspace(a,b,n) ym = sqrt(x) ! model data ! 2. generate the measured data with noise (ensembles the experimental data) call random_number(noise) ! generate noise in [0, 1] d = (b-a)/100.0_wp * (x-a)**2 ! define the deviation function d = 2.0_wp*(noise - 0.5_wp) * d ! distribute noise around y=0 y = ym + d call gp%title('Example 20. Scatter plot') call gp%xlabel('x,....') call gp%options('set key top left') call gp%options('set autoscale fix') call gp%options('set style line 1 lc rgb "blue" lt 1 lw 2 pt 6 ps 1.5') call gp%plot(x, y, 't "exp data" with points pt 6 ps 1.2 lc rgb "#ad2060"', & x, ym, 't "mode: y=sqrt(x)" w lines lt 1 lw 3 lc "blue"') ! plot only the experimental data call gp%title('Example 20. Scatter plot: data with noise') call gp%plot(x,y,'w l lc "blue"', x, ym, 'w l lc "dark-red" lw 2') end subroutine exmp20 ``` Will produce ![Example 20](doc/exmp20.png) ![Example 20](doc/exmp20_2.png) * **Example 21** Stem plot ```fortran subroutine exmp21() !............................................................................... ! Example 21: Making a stem plot !............................................................................... type(gpf):: gp integer, parameter :: n=50 real(wp) :: x(n), y(n) real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) ! generate data x = linspace(0.0_wp, 4.0_wp*pi, n) y = exp(-x/4.0)*sin(x) call gp%title('Example 21. Stem plot') ! making plot call gp%plot(x,y, 'with impulses lw 2.5', & x, y, 'with points pt 7') end subroutine exmp21 ``` Will produce ![Example 21](doc/exmp21.png) * **Example 22** Animation with stem plot ```fortran subroutine exmp22() !............................................................................... ! Example 22: Stem plot animation !............................................................................... type(gpf):: gp integer, parameter :: n=50 real(wp) :: x(n), y(n) real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) integer :: i ! generate data x = linspace(0.0_wp, 4.0_wp*pi, n) y = exp(-x/4.0)*sin(x) ! important, set the xy axis range call gp%axis([0.0_wp, 4.0_wp*pi, -1.0_wp, 1.0_wp]) ! start animation call gp%animation_start(delay=1.) ! one second delay between frames do i=1,n ! add frames ! each plot command adds one frame call gp%plot(x(1:i), y(1:i), 'with impulses lw 2', & x(1:i), y(1:i), 'with points pt 6') end do ! finalize and show all frames in ornithological order with pause as ! set by animation_start call gp%animation_show() end subroutine exmp22 ``` Will produce ![Example 22](doc/exmp22.gif) * **Example 25** Multiplot layout ```fortran subroutine exmp25() type(gpf):: gp integer, parameter :: n=25 real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) real(wp) :: x(n), y(n,4) integer :: i x=linspace(-pi, pi, n) y(:,1) = sin(x) y(:,2) = sin(x)*cos(x) y(:,3) = (1-x)*sin(x) y(:,4) = (1-x)*cos(x) ! general options call gp%options('set tics font ",8"') call gp%multiplot(2,2) do i=1, 4 call gp%plot(x, y(:,i), 'lt 4 pt 6') end do ! a new window will be started when all places in the multiplot ! layout is occupied. The multiplot window will be closed call gp%plot(x,y) end subroutine exmp25 ``` Will produce ![Example 25](doc/exmp25.png) ![Example 25](doc/exmp25_2.png) ## 3D plots: surf and contour * **Example 101** Using different color palettes ```fortran subroutine exmp101 type(gpf):: gp real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z(:,:) real(wp):: a=0.5d0 real(wp):: b=2.0d0 real(wp), allocatable :: xgrid(:) real(wp), allocatable :: ygrid(:) integer:: m integer:: n ! create 3D data m=55 ! number of grid points in y direction n=25 ! number of grid points in x direction xgrid=linspace(-10.0_wp, 10.0_wp, m) ygrid=linspace(0.0_wp, 5.0_wp, n) allocate( z(m,n) ) call meshgrid(x, y, xgrid, ygrid) ! generate the 2D grid data z=(x**2/a - y**2/b) ! annotation call gp%title('Example 101: Simple 3D plot') call gp%xlabel('x-axis,...') call gp%ylabel('y-axis,...') call gp%zlabel('z-axis,...') !plot the 3D data call gp%surf(x, y, z, lspec='t "default color spec"' ) ! color palette: gnuplot default call gp%surf(x, y, z, lspec='t "Ann Schnider set1"', palette='set1' ) ! color palette: set1 call gp%surf(x, y, z, lspec='t "Matlab Jet"', palette='jet' ) ! color palette: Matlab jet end subroutine exmp101 ``` Will produce ![Example 101](doc/exmp101.png) ![Example 101_2](doc/exmp101_2.png) ![Example 101_3](doc/exmp101_3.png) * **Example 102** Simple surface plot with color palette ```fortran subroutine exmp102() type(gpf):: gp real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z(:,:) integer:: m integer:: n ! generate data call meshgrid(x, y, linspace(-0.75_wp*pi, 0.75_wp*pi, 35) ) ! xgrid == ygrid m=size(x,1) n=size(x,2) allocate( z(m,n) ) !z= sin(x) * cos (y) where (x**2 + y**2 == 0.0_wp) z=1.0_wp elsewhere z=sin(x**2+y**2)/(x**2+y**2) end where call gp%title('Example 102: Simple 3D plot with color palette') call gp%xlabel('x-axis,...') call gp%ylabel('y-axis,...') call gp%options('set style data lines') !plot the 3D data CALL gp%surf(X,Y,Z, palette='jet') end subroutine exmp102 ``` Will produce ![Example ](doc/exmp102.png) * **Example 103** A beautiful surface and contour plot ```fortran subroutine exmp103() type(gpf):: gp real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z(:,:) real(wp):: a=-0.5_wp real(wp):: b= 0.5_wp real(wp):: pi= 4.0_wp * atan(1.0_wp) integer:: m integer:: n ! create 3D data call meshgrid( x, y, linspace(a, b, 55) ) m=size(x,1) n=size(x,2) allocate( z(m,n) ) z= cos(2.0*pi*x) * sin(2.0*pi*y) ! annotation call gp%title('Example 103: A beautiful surface plot with hidden details') call gp%options('set hidden3d') call gp%options('unset key') !plot the 3D data call gp%surf(x, y, z, palette='jet' ) ! color palette: Matlab jet ! contour call gp%contour(x,y,z, palette='set1') end subroutine exmp103 ``` Will produce ![Example ](doc/exmp103.png) ![Example ](doc/exmp103_2.png) * **Example 104** Cylindrical mapping ```fortran subroutine exmp104() type(gpf):: gp integer, parameter :: m = 35 integer, parameter :: n = 15 real(wp) :: xv(m), yv(n) real(wp), dimension(:,:), allocatable:: x,y,z real(wp):: pi= 4.0_wp * atan(1.0_wp) xv = linspace(0.0_wp, pi, m) yv = linspace(0.0_wp, pi, n) call meshgrid(x,y, xv, yv) allocate( z(size(x,dim=1), size(x, dim=2)) ) z = sin(y) ! advanced options call gp%options('set mapping cylindrical') call gp%options('unset tics') call gp%options('unset border') call gp%options('set view 147,312') call gp%options('set hidden3d') ! call gp%title('Example 104. Cylindrical Mapping') call gp%surf(x,y,z) end subroutine exmp104 ``` Will produce ![Example ](doc/exmp104.png) * **Example 105** Contour plot and surface plot with color palette ```fortran subroutine exmp105() type(gpf):: gp real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z(:,:) integer:: m integer:: n real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) ! create the xyz data call meshgrid(x, y, linspace(-2.0_wp,2.0_wp, 65), linspace(-2.0_wp,3.0_wp, 65) ) m=size(x,1) n=size(x,2) allocate( z(m,n) ) z = x * exp(-x**2 - y**2) call gp%options('unset key') call gp%options('unset surface') call gp%axis([real(wp):: -2, 2, -2, 3]) !plot the contour call gp%title('Example 105: Contour plot') call gp%options('unset border; unset tics') call gp%surf(x,y,z, palette='accent') call gp%contour(x,y,z, palette='jet') end subroutine exmp105 ``` Will produce ![Example ](doc/exmp105.png) ![Example ](doc/exmp105_2.png) * **Example 106** Animation with 3D plots ```fortran subroutine exmp106() type(gpf):: gp integer, parameter :: n=25, m=55 real(wp) :: xv(m), yv(n), t real(wp), allocatable :: x(:,:), y(:,:), z(:,:) real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) ! generate data xv = linspace(0.0_wp, 2.0_wp*pi, m) yv = linspace(0.0_wp, 2.0_wp*pi, n) call meshgrid(x, y, xv, yv) z = sin(x) + cos(y) call gp%title('Example 106. Animation of surface plot') call gp%axis([0.0_wp, 2.0*pi, 0.0_wp, 2.0*pi]) call gp%options('unset colorbox') call gp%options('set ticslevel 0') call gp%axis([0.0_wp, 2.0*pi, 0.0_wp, 2.0*pi, -2.0_wp, 2.0_wp]) call gp%animation_start(1.0) t=0.050_wp do ! add frames call gp%surf(x, y, sin(t*pi/2.0)*z, palette='jet') t=t+0.1_wp if (t > 1.0_wp) exit end do ! show frames in ornithological order with a pause set in ! animation_start call gp%animation_show() end subroutine exmp106 ``` Will produce ![Example 106](doc/exmp106.gif) * **Example 107** Multiplot layout for 3D plots ```fortran subroutine exmp107() !............................................................................... !Example 107: Multiplot layout in 3D and Contour plot !............................................................................... type(gpf):: gp real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z1(:,:) real(wp), allocatable:: z2(:,:) integer:: m integer:: n real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) ! create the xyz data call meshgrid(x, y, linspace(-pi,pi, 60) ) m=size(x,1) n=size(x,2) allocate( z1(m,n) ) allocate( z2(m,n) ) z1 = sin(x) + cos(y) z2 = sin(x) * cos(y) call gp%options('unset key') call gp%axis([-pi,pi,-pi,pi]) call gp%options('unset colorbox') call gp%options('set autoscale fix') call gp%options('unset tics') !plot the contour call gp%title('Example 105: Contour plot') call gp%multiplot(1,2) call gp%surf(x,y,z1) call gp%surf(x,y,z2) call gp%multiplot(2,1) call gp%options('set colorbox') call gp%options('set tics') call gp%options('set tics font ",8"') ! font size for tics call gp%contour(x,y,z1, palette='jet') call gp%contour(x,y,z2, palette='set1') end subroutine exmp107 ``` Will produce ![Example 107](doc/exmp107_2.png) ================================================ FILE: doc/readme.txt ================================================ This folder contains some outputs generated by demo.f90 Rev 0.2 March 1st, 2018 ================================================ FILE: example/demo.f90 ================================================ !------------------------------------------------------------------------------- ! GnuPlot Interface !------------------------------------------------------------------------------- ! Purpose: Object Based Interface to GnuPlot from Fortran (ogpf) ! Platform: Windows XP/Vista/7/10 ! (It should work on other platforms, see the Write2GnuPlot subroutine below) ! Language: Fortran 2003 and 2008 ! Requires: 1. Fortran 2003 compiler (e.g gfortran 4.7, IVF 12.1, ...) or 2008 ! 2. gnuplot 4.5 and higher (other previous version can be used ! Author: Mohammad Rahmani ! Chem Eng Dep., Amirkabir Uni of Tech ! Tehran, Ir ! url: aut.ac.ir/m.rahmani ! email: m[dot]rahmani[at]aut[dot]ac[dot]ir ! License: MIT ! This file demonstrate the capability of ogpf module ! An object based Fortran interface to gnuplot ! ! Acknowledgement: ! Special thanks to Hagen Wierstorf (http://www.gnuplotting.org) ! For vluable codes and examples on using gnuplot ! Some examples and color palletes are provided by gnuplotting. ! ! ! Revision 0.22 ! Date: Mar 9th, 2018 ! - see ogpf.f90 for details ! - more examples to reflect the new features ! Revision: 0.20 ! Date: Feb 20th, 2018 ! - more examples ! - animation of 2D and 3D plots ! Revision: 0.19 ! Date: Jan 15th, 2018 ! - new contour plot procedure ! Revision: 0.18 ! Date: Dec 22th, 2017 ! More example based on ogpf 0.18 ! Version: 0.17 ! Date: Dec 18th, 2017 ! Minor corrections ! - Multi window plots using script ! Version: 0.16 ! Date: Feb 11th, 2016 ! Minor corrections ! Correct the lspec processing in plot2D_matrix_vs_vector ! Some examples revised! ! Version: 0.15 ! Date: Apr 20th, 2012 ! Minor corrections ! Use of select_precision module and working precision: wp ! Version: 0.14 ! Date: Mar 28th, 2012 ! Minor corrections ! use of import keyboard and removing ogpf precision module ! Version: 0.13 ! Date: Feb 12th, 2012 ! Minor corrections ! Added more samples ! Use ogpf precision module ! Version: 0.12 ! Date: Feb 9th, 2012 ! New examples for semilogx, semilogy, loglog ! New set options method ! Version: 0.11 ! Date: Feb 9th, 2012 program demo use ogpf implicit none ! parameters ! local variables integer:: i=0 mainloop: do print* ! empty line print*, "gpf: gnuplot from Fortran Demonstration" print*, "Example 1: Demo for xy plot" print*, "Example 2: Line specification" print*, "Example 3: Plot several data series at the same time" print*, "Example 4: Plot four data series at the same time" print*, "Example 5: Use line style, line colors and more..." print*, "Example 6: An interesting plot, sin(x) and its zero on the same plot" print*, "Example 7: Plot a matrix against a vector" print*, "Example 8: Plot a matrix against a vector and set the linespec and legend" print*, "Example 9: Use gnuplot for animation" print*, "Example 10: Use ogpf options" print*, "Example 11: simple polar plot" print*, "Example 12: A plot with logarithmic x axis" print*, "Example 13: A matrix plot with logarithmic y axis" print*, "Example 14: A loglog plot" print*, "Example 15: Plotting a function" print*, "Example 16: Save the gnuplot script into a file for future use" print*, "Example 17: Multi window plots, using script" print*, "Example 18: Running an external script file" print*, "Example 19: Multiple linestyle in matrix plot" print*, "Example 20: Scatter plot" print*, "Example 21: Stem plot" print*, "Example 22: Stem plot animation" print*, "Example 23: Another animation using matrix plot" print*, "Example 24: Multiplot layout" print*, "Example 25: Multiplot layout followed by simple plot" print*, "Example 26: Plot matrix vs. matrix" print*, "Example 27: Using secondary y axis" print*, "Example 28: Using secondary x and y axis" print*, "Example 29: Using color and size for title and labels" print*, "Example 30: More on labels color and size with secondary axes" print* print*, "*** Surface and Contour Plots ***" print* print*, "Example 101: Simple 3D plot using surf" print*, "Example 102: Surface plot and color palette " print*, "Example 103: Surface plot with hidden details and its contour" print*, "Example 104: Cylindrical mapping" print*, "Example 105: More contour plot" print*, "Example 106: Animation of 3D plots" print*, "Example 106: Multiplot layout in 3D" print*, "Example 107: Multiplot layout for 3D data" print*, "Example 108: Plot a 2D grid" print*, "Example 109: Plot a 2D grid with random data, but use zlim to select a zrange" print* write (unit=*, fmt='(a)') "2D plots: select an example: 1 through 30" write (unit=*, fmt='(a)') "3D plots: select an example: 101 through 109" write (unit=*, fmt='(a)', advance='no') "enter 0 for exit: " read*, i select case(i) case(1) call exmp01 case(2) call exmp02 case(3) call exmp03 case(4) call exmp04 case(5) call exmp05 case(6) call exmp06 case(7) call exmp07 case(8) call exmp08 case(9) call exmp09 case(10) call exmp10 case(11) call exmp11 case(12) call exmp12 case(13) call exmp13 case(14) call exmp14 case(15) call exmp15 case(16) call exmp16 case(17) call exmp17 case(18) call exmp18 case(19) call exmp19 case(20) call exmp20 case(21) call exmp21 case(22) call exmp22 case(23) call exmp23 case(24) call exmp24 case(25) call exmp25 case(26) call exmp26 case(27) call exmp27 case(28) call exmp28 case(29) call exmp29 case(30) call exmp30 ! 3D plots case(101) call exmp101 case(102) call exmp102 case(103) call exmp103 case(104) call exmp104 case(105) call exmp105 case(106) call exmp106 case(107) call exmp107 case(108) call exmp108 case(109) call exmp109 case (0) print*, "Program terminated successfully" exit mainloop case default print*, "Try again, use a valid example number" print*, "Enter 0 to exit" end select print* print*, "press any key to continue..." read* end do mainloop contains !............................................................................... !Example 1: A very basic example !............................................................................... subroutine exmp01 type(gpf):: gp integer, parameter:: n=17 real(wp):: x(n) real(wp):: y(n) ! Input data ! x=dble([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8]) x=dble([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8]) x= abs(x) + 5 y=dble([66,51,38,27,18,11,6,3,2,3,6,11,18,27,38,51,66]) ! Annotation: set title, xlabel, ylabel call gp%title('Example 1. A simple xy plot','#990011') call gp%xlabel('my x axis ...','#99aa33',font_name="Tahoma") ! call gp%ylabel('my y axis ...') call gp%options('set border lc "#99aa33"; set ylabel "my label..." tc "#99aa33"') call gp%options('set logscale y2') call gp%plot(x, y) end subroutine exmp01 !............................................................................... !Example 2: Set line specification and legends !............................................................................... subroutine exmp02 type(gpf):: gp integer, parameter:: n=17 real(wp):: x(n) real(wp):: y(n) ! Input data x=dble([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8]) y=dble([66,51,38,27,18,11,6,3,2,3,6,11,18,27,38,51,66]) ! Annotation: set title, xlabel, ylabel, line specification call gp%title('Example 2. A simple xy plot') call gp%xlabel('my x axis ...') call gp%ylabel('my y axis ...') !Call Plot to draw a vector against a vector of data !The last argument defines the line specification call gp%plot(x,y,'with linespoints lt 2 pt 4') end subroutine exmp02 !............................................................................... ! Example 3: Plot several data set at the same time !............................................................................... subroutine exmp03 type(gpf):: g integer, parameter:: n = 50 integer, parameter:: m = 65 real(wp):: x(n) real(wp):: y(n) real(wp):: xv(m) real(wp):: yv(m) real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) ! Input data x=linspace(-pi,pi,n) !linspace is a utility function in ogpf module y=sin(x) !linspace(a,b,n) create a linear vector in [a,b] with n elements xv=linspace(0.d0, 2.d0*pi,m) yv=cos(2.d0*xv) ! Annotation, set title, xlabel, ylabel call g%title('Example 3. Plot two data series using gnuplot') call g%xlabel(' x axis ...') call g%ylabel(' y axis ...') call g%options('set key top left') ! Sample 1: Plot to draw two set of data call g%plot(x,y,'title "sin"','', xv,yv,'title "cos"') !Sample 2: Use keyword arguments to plot the same example as above call g%title('Example 3. Another plot using keyword arguments...') call g%plot(x1=x,y1=y,ls1='pt 8',x2=xv,y2=yv,ls2='title "cos(2x)"') ! Sample 3: An xy plot with line specification no legends call g%title('Example 3. Another plot without keyword arguments...') call g%plot(x,y,'title "sin(x)" with points pt 6 lc "blue"', '',xv,yv,'title "cos(2x)" pt 7 lc rgb "#993300"') end subroutine exmp03 !............................................................................... ! Example 4: Plot four data series, the maximum number of data series can be plotted! !............................................................................... subroutine exmp04 type(gpf):: gp integer, parameter:: n=50 integer, parameter:: m=65 real(wp):: x(n) real(wp):: y(n) real(wp):: xv(m) real(wp):: yv(m) real(wp), parameter :: pi=4.d0*atan(1.d0) ! Input data x=linspace(-pi,pi,n) !linspace is a utility function from module ogpf y=sin(x) xv=linspace(0.d0, 2.d0*pi,m) yv=cos(2.d0*xv) ! This is the maximum number of plot can be drawn at the same time ! If you have more data see, you can plot can be used with matrices! call gp%title('Example 4. Plot four data sets using gnuplot') call gp%options('set key top left; set grid') call gp%plot(x,y, 'title "sin(x)"', '', & xv,yv, 'with lp lt 6 title "cos(2x)"', '', & xv, 2.d0*yv, 'title "2cos(2x)" lt 7', '', & xv, 0.5d0*yv, 'title "0.5cos(2x)" with points pt 8') ! Another example with keyboard arguments call gp%plot(x1=x,y1=y,x2=xv,y2=yv) end subroutine exmp04 !............................................................................... ! Example 5: Use line style, line color and moree !............................................................................... subroutine exmp05 type(gpf):: gplot integer, parameter:: n=50 real(wp):: x(n) real(wp):: ys(n) real(wp):: yc(n) real(wp):: ysc(n) real(wp), parameter :: pi=4.d0*atan(1.d0) ! Input data x=linspace(-2.d0*pi,2.d0*pi,n) !linspace is a utility function from module Utils ys= sin(x) yc= exp(-0.1d0*x)*cos(x) ysc= sin(x/2.d0)*cos(2.d0*x) ! Annotation, set title, xlabel, ylabel call gplot%title('Example 5. A sample with customized line style') call gplot%xlabel('x, rad') call gplot%ylabel('y, dimensionless') ! Plot to draw three set of data call gplot%plot( & x,ys, 'title "sin" with lines lt 5 lc rgb "#0008B0"', '', & x,yc, 'title "cos" with points lt 6 lc rgb "#FF1100"', '', & x,ysc,'title "sin(x/2)cos(2x)" with lp lt 7 lc rgb "#00AA04"' ) end subroutine exmp05 !............................................................................... ! Example 6: Plot a single point along with a series of data !............................................................................... subroutine exmp06 type(gpf):: gplot integer, parameter:: n=125 real(wp):: x(n) real(wp):: y(n) real(wp), parameter :: pi=4.d0*atan(1.d0) ! Input data x=linspace(0.d0,pi*2.d0,n) !linspace is a utility function from module Utils y=sin(6.d0*x)*exp(-x) ! Annotation, set title, xlabel, ylabel call gplot%title('Example 6. A sample shows f(x) and its zero on the plot') call gplot%xlabel('x, rad') call gplot%ylabel('f(x) = sin(6x)exp(-x) dimensionless') call gplot%options('set grid') ! Plot to draw two set of data, a series and a single point call gplot%plot(x,y,'title "sin(6x)exp(-x)" with lines lt 2 lw 3', '', & [pi],[0.d0],'title "zero" with points pt 7 ps 3 lc rgb "#FF0000"') end subroutine exmp06 !............................................................................... ! Example 7: Plot a matrix against a vector !............................................................................... subroutine exmp07 type(gpf):: g integer, parameter:: n=25 real(wp), parameter :: pi=4.d0*atan(1.d0) real(wp):: x(n) real(wp):: y(n,6) !Create data x=linspace(-pi,pi,n) y(:,1)=sin(x) y(:,2)=cos(x) y(:,3)=cos(0.5d0*x) y(:,4)=sin(0.5d0*x) y(:,5)=sin(x)*cos(x) y(:,6)=sin(x)*exp(-x**2) !Draw the matrix y against vector x call g%title ('Example 7. Plotting a Matrix against a vector') call g%xlabel ('my x axis') call g%ylabel ('my y axis') call g%plot (x, y) end subroutine exmp07 !............................................................................... ! Example 08. Plot a matrix against a vector and set the linespec and legend (key) !............................................................................... subroutine exmp08 type(gpf):: matplot integer, parameter:: n=25, m=6 integer :: i real(wp):: tf real(wp):: vo real(wp):: g real(wp):: t(n) real(wp):: y(n,m) !Create data tf=10.d0 g=32.d0; t=linspace(0.d0,tf,n) do i = 1, m vo = 25.0d0 * i y(:, i) = vo*t-0.5d0*g*t**2 end do !Draw the matrix y againest vector x call matplot%title('Example 8. Plotting a Matrix against a vector') call matplot%xlabel ('t, sec') call matplot%ylabel ('y, feet') call matplot%options('set xrange[0:10];set yrange [0:400];') call matplot%plot(t, y) !Another Matrix plot with legends and line specification call matplot%title('Example 8.2: Matrix plot, legends and linespec') call matplot%plot(t, 2.0d0*y(:,3:4), & lspec='t "vo=100" w lp lt 6 ps 3 lw 2;& & t "v=125" w lp lt 7 ps 3 lw 2 lc rgb "#ad6000"') end subroutine exmp08 !............................................................................... ! Example 09: Use gnuplot for annimation !............................................................................... subroutine exmp09 type(gpf):: gp integer, parameter:: n = 35 real(wp), parameter :: pi = 4.d0*atan(1.d0) real(wp):: x(n) real(wp):: y(n), z(n) integer :: i x=linspace(-pi, pi,n) y = 0.0_wp z = 0.0_wp call gp%animation_start(1.) ! start animation, set delay is one second between frames call gp%axis([-pi, pi, -1.2_wp, 1.2_wp]) call gp%title('A beautiful animation using ogpf library', textcolor='#aa5500') ! add frames do i=1, n, 1 y(i) = sin(x(i)) z(i) = cos(x(i)) ! each plot command adds one frame call gp%plot(x(1:i),y(1:i), 'w lines lc "red" lw 2','', & x(i:i), y(i:i),'w points ps 3 pt 7 lc "red"','', & x(1:i),z(1:i), 'w lines lc "blue" lw 2', '',& x(i:i), z(i:i), 'w points ps 3 pt 7 lc "blue"' ) end do ! finalize and show frames one by one with delay between them ! as set by animation_start call gp%animation_show() end subroutine exmp09 !............................................................................... ! Example 10: Use gnuplot options !............................................................................... subroutine exmp10() type(gpf):: mp real(wp):: x(15) real(wp):: y(15) !Options is a dynamic length string and can set all kind of gnuplot call mp%options('set style line 1 lc rgb "#0060ad" lt 1 lw 2 pt 5 ps 1.5 # --- blue') call mp%options('set style line 2 lc rgb "#ad6000" lt 2 lw 2 pt 6 ps 1.5 # --- red') call mp%options('set style line 3 lc rgb "#00ad00" lt 2 lw 2 pt 7 ps 1.5 # --- green') ! this is a multipart string spanned over several lines call mp%options('& &set style data linespoints;& &set xrange [0.1:100];& &set yrange [0.01:10000];& &set autoscale') call mp%options('set key top left') ! set the key location x=linspace(0.1d0,100d0,15); y=x**2; call mp%title("Example 10. x vs. x^2") call mp%plot(x1=x, y1=1.50*y, ls1='t "y=1.5x^2" ls 1', & x2=x, y2=2.00*y, ls2='t "y=2.0x^2" ls 2', & x3=x, y3=2.50*y, ls3='t "y=2.5x^2" ls 3') call mp%reset() call mp%title('Reset to initial setting') call mp%plot(x,2*y) end subroutine exmp10 !............................................................................... ! Example 11: A simple polar plot !............................................................................... subroutine exmp11 type(gpf):: gp integer, parameter :: n=125 real(wp):: t(n) real(wp):: r(n) real(wp):: pi=4.d0*atan(1.d0) !1. reset gplot !!! CALL gp%reset() ! TODOD: There is a problem with reset, persist is off by reset !2. set option, and set plot as polar call gp%options("& &set polar;& &set trange [-pi:pi]") ! 3. create data t=linspace(-pi,pi,n) r=sin(3.d0*t) !Annotation, set title, xlabel, ylabel call gp%title("Example 11: simple polar plot") call gp%xlabel("x,...") call gp%ylabel("y,...") !Call plot method call gp%plot(t,r, 'title "sin(3t)"') call gp%plot(t, cos(4*t)) end subroutine exmp11 !............................................................................... ! Example 12: A simple plot with logarithmic x axis !............................................................................... subroutine exmp12 type(gpf):: gp integer, parameter :: n=70 real(wp):: x(n) real(wp):: y(n) ! 1. create data x=linspace(0.0d0,10.d0,n) y=10**(exp(-x/2.d0)*sin(2.d0*x)) !Annotation, set title, xlabel, ylabel call gp%title("Example 12: A semi-log x plot") call gp%xlabel("x,logarithmic scale") call gp%ylabel("y, normal scale") !Sample 1 call gp%semilogx(y,x) end subroutine exmp12 !............................................................................... ! Example 13: A simple matrix plot with logarithmic y axis !............................................................................... subroutine exmp13 type(gpf):: gp integer, parameter :: n=25 real(wp):: x(n) real(wp):: y(n) ! 1. create data x=linspace(0.1d0,10.d0,n) y=5.d0*x**3+4.d0*x**2+3.d0*x+1.d0 !Annotation, set title, xlabel, ylabel call gp%title("Example 13: A simple matrix plot with semi-log y") call gp%ylabel("y,logarithmic scale") call gp%xlabel("x, normal scale") ! plot a matrix against vector in logarithmic y axis with line specification call gp%semilogy(x,reshape([y,10.d0*y],[n,2]), 'with lines lt 8; with points pt 7') end subroutine exmp13 !............................................................................... ! Example 14: A simple plot with logarithmic xy axes !............................................................................... subroutine exmp14 type(gpf):: gp integer, parameter :: n=75 real(wp):: x(n) real(wp):: y(n) real(wp):: pi=4.d0*atan(1.d0) ! 1. create data x=exp(linspace(0.d0,2.d0*pi,n)) y=50.d0+exp( 3.d0* linspace(0.d0,2.d0*pi,n) ) ! 2. Annotation, set title, xlabel, ylabel call gp%title("Example 14: A loglog plot") call gp%xlabel("x,logarithmic scale") call gp%ylabel("y,logarithmic scale") ! 3. Set grid on call gp%options('set grid xtics ytics mxtics') ! 4. Call plot method call gp%loglog(x,y) end subroutine exmp14 !............................................................................... ! Example 15: Plotting a function !............................................................................... subroutine exmp15() type(gpf):: gp real(wp):: pi=4.d0*atan(1.d0) call gp%title("Example 15. Plotting a function using fplot") call gp%xlabel("x...") call gp%ylabel("y...") ! call fplot to plot a function in range of [a, b] with n points call gp%fplot(myfun,[0d0,15.d0*pi],150) end subroutine exmp15 function myfun(x) ! The function to be plotted ! see example 15 real(wp), intent(in) :: x real(wp):: myfun myfun=x*sin(x) end function myfun !............................................................................... ! Example 16: Save the gnuplot script into a file for future use !............................................................................... subroutine exmp16() type(gpf):: gp real(wp):: pi=4.d0*atan(1.d0) integer, parameter :: n=100 real(wp) :: x(n) real(wp) :: y(n) real(wp) :: z(n) ! create data x = linspace(-pi, 3.0d0*pi) y = sin(2.0d0*x)*exp(-x/5.0d0) z = cos(2.0d0*x)*exp(-x/5.0d0) ! several gnuplot optuons call gp%options('set border linewidth 1.5') call gp%options('set style line 1 lc rgb "#ad6009" lt 1 lw 2 pt 7 ps 1.5 # --- red like') call gp%options('set style line 2 lc rgb "#00ad09" lt 2 lw 2 pt 6 ps 1.5 # --- green like') call gp%options('unset key') call gp%options('set grid') call gp%options('set ytics 1') call gp%options('set tics scale 0.75') call gp%title("Example 16. Save the script into file for future use") call gp%xlabel("x...") call gp%ylabel("y...") ! save the script into a file call gp%filename("Example16.gp") call gp%plot(x, y, ls1='with lp ls 1', x2=x, y2=z, ls2='with lp ls 2') print* ! empty line print*, 'Plot commands were written in Example16.gp successfully' print*, 'Open gnuplot and load this script file to plot the results!' print* ! empty line end subroutine exmp16 !............................................................................... ! Example 17: Plot in two separate windows using script !............................................................................... subroutine exmp17() ! Script is used to create multi window plot ! Each "set term wxt " creates a new window type(gpf):: gp call gp%add_script('set term wxt 0 title "My first plot" size 640,480') call gp%add_script('set title "Example 17. Multi windows plot using script"') call gp%add_script('plot x*x+2*x+1') call gp%add_script('set term wxt 1 title "My second plot"') call gp%add_script('set ylabel "xsin(x)"') call gp%add_script('plot x*sin(x)') call gp%run_script() end subroutine exmp17 !............................................................................... ! Example 18: Running an external script file !............................................................................... subroutine exmp18() !Use gnuplot script !to send a special external script file to gnuplot !the file is an external file here is called "simple.plt" type(gpf):: gp ! add some options and commands call gp%title("Example 18. Running an external script file") call gp%add_script('load "sample_script.gp" ') ! run script call gp%run_script() end subroutine exmp18 !............................................................................... !Example 19: USE multiple linespec in plotting a matrix vs a vector !............................................................................... subroutine exmp19 ! see also example 8 type(gpf):: gp integer, parameter:: n=17 real(wp):: x(n) real(wp):: y(n,8) integer :: j ! Input data x=linspace(0.d0,10.d0,17) do j=1, 8 y(:,j)=dble(3*j) end do !Annotation, set title, xlabel, ylabel call gp%title('Example 19. Matrix plot with different line specification') call gp%xlabel('my x axis ...') call gp%ylabel('my y axis ...') call gp%options('set key bottom right') call gp%axis([-2.d0,20.d0,-2.d0,20.d0]) !Call Plot to draw a matrix against a vector of data call gp%plot(x,y,lspec='with linespoints lt 1 title "lt 1";& & with lp lt 2 title "lt 2";& & with lp lt 3 title "lt 3";& & with lp lt 4 title "lt 4";& & with lp lt 5 title "lt 5";& & with lp lt 6 title "lt 6";& & with lp lt 7 title "lt 7";& & with lp lt 8 title "lt 8"') end subroutine exmp19 !............................................................................... ! Example 20: Making a scatter plot !............................................................................... subroutine exmp20() type(gpf):: gp integer, parameter :: n=750 real(wp) :: x(n), y(n), ym(n), noise(n), d(n) real(wp) :: a, b ! generate data a = 00.0_wp b = 05.0_wp ! 1. generate the model data x = linspace(a,b,n) ym = sqrt(x) ! model data ! 2. generate the measured data with noise (ensembles the experimental data) call random_number(noise) ! generate noise in [0, 1] d = (b-a)/100.0_wp * (x-a)**2 ! define the deviation function d = 2.0_wp*(noise - 0.5_wp) * d ! distribute noise around y=0 y = ym + d call gp%title('Example 20. Scatter plot') call gp%xlabel('x,....') call gp%options('set key top left') call gp%options('set autoscale fix') call gp%options('set style line 1 lc rgb "blue" lt 1 lw 2 pt 6 ps 1.5') call gp%plot(x, y, 't "exp data" with points pt 6 ps 1.2 lc rgb "#ad2060"', & x2=x, y2=ym, ls2='t "mode: y=sqrt(x)" w lines lt 1 lw 3 lc "blue"') ! plot only the experimental data call gp%title('Example 20. Scatter plot: data with noise') call gp%plot(x,y,'w l lc "blue"', x2=x, y2=ym, ls2='w l lc "dark-red" lw 2') end subroutine exmp20 !............................................................................... ! Example 21: Making a stem plot !............................................................................... subroutine exmp21() type(gpf):: gp integer, parameter :: n=50 real(wp) :: x(n), y(n) real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) ! generate data x = linspace(0.0_wp, 4.0_wp*pi, n) y = exp(-x/4.0)*sin(x) call gp%title('Example 21. Stem plot') ! making plot call gp%plot(x,y, 'with impulses lw 2.5', & x2=x, y2=y, ls2='with points pt 7') end subroutine exmp21 !............................................................................... ! Example 22: Stem plot animation !............................................................................... subroutine exmp22() type(gpf):: gp integer, parameter :: n=50 real(wp) :: x(n), y(n) real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) integer :: i ! generate data x = linspace(0.0_wp, 4.0_wp*pi, n) y = exp(-x/4.0)*sin(x) ! important, set the xy axis range call gp%axis([0.0_wp, 4.0_wp*pi, -1.0_wp, 1.0_wp]) ! start animation call gp%animation_start(pause_seconds=1.) ! one second delay between frames do i=1,n ! add frames ! each plot command adds one frame call gp%plot(x(1:i), y(1:i), ls1='with impulses lw 2', & x2=x(1:i), y2=y(1:i), ls2='with points pt 6') end do ! finalize and show all frames in ornithological order with pause as ! set by animation_start call gp%animation_show() end subroutine exmp22 !............................................................................... ! Example 23: Another animation using matrix plot !............................................................................... subroutine exmp23() type(gpf):: gp integer, parameter :: n=55 real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) real(wp) :: x(n), y(n,2) integer :: i ! generate data x = linspace(0.0_wp, 4.0_wp*pi, n) y(:,1) = exp(-x/4.0)*sin(x) y(:,2) = exp(-x/8.0)*cos(x) call gp%axis([0.0_wp, 4.0*pi, -0.8_wp, 1.0_wp]) call gp%animation_start(1.) do i=1, n, 2 ! making plot: add frames call gp%plot(x(1:i),y(1:i, :), 'with lines lw 2') end do call gp%animation_show() end subroutine exmp23 !............................................................................... ! Example 24: Use of multiplot layout !............................................................................... subroutine exmp24() type(gpf):: gp integer, parameter :: n=25 real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) real(wp) :: x(n), y(n,2) x=linspace(-pi, pi, n) y(:,1) = sin(x)*exp(-x/2.0) y(:,2) = cos(x)*(1-exp(-x/5.0)) call gp%multiplot(2,1) ! create a 2x1 multiplot layout call gp%title('Example 24. Multiplot layout, first row') call gp%xlabel('x1, ...') call gp%ylabel('y1, ...') call gp%plot(x, y(:,1), 'pt 7 lw 2 lc "red"') ! plot in first row call gp%title('Example 24. Multiplot layout,second row') call gp%xlabel('x2, ...') call gp%ylabel('y2, ...') call gp%plot(x, y(:,2), 'pt 6 lw 2 lc "blue"') ! plot in the second end subroutine exmp24 !............................................................................... ! Example 25: Use multiplot followed by other plot command !............................................................................... subroutine exmp25() type(gpf):: gp integer, parameter :: n=25 real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) real(wp) :: x(n), y(n,4) integer :: i x=linspace(-pi, pi, n) y(:,1) = sin(x) y(:,2) = sin(x)*cos(x) y(:,3) = (1-x)*sin(x) y(:,4) = (1-x)*cos(x) ! general options call gp%options('set tics font ",8"') call gp%multiplot(2,2) do i=1, 4 call gp%plot(x, y(:,i), 'lt 4 pt 6') end do ! a new window will be started when all places in the multiplot ! layout is occupied. The multiplot window will be closed call gp%plot(x,y) end subroutine exmp25 !............................................................................... !Example 26: Plot matrix against matrix !............................................................................... subroutine exmp26 ! see also example 8 type(gpf):: gp integer, parameter:: n=35 integer, parameter:: m=3 real(wp) :: x(n,m) real(wp) :: y(n,m) ! create data x(:,1) = linspace(-3.15d0,3.15d0,n) x(:,2) = 3.15d0 + x(:,1) x(:,3) = 3.15d0 - x(:,1) y(:,1) =1.0d0 * sin(x(:,1)) * (1-x(:,1)) y(:,2) =2.0d0 * sin(x(:,1)) * (1-x(:,1)) y(:,3) =3.0d0 * sin(x(:,1)) * (1-x(:,1)) !Annotation, set title, xlabel, ylabel call gp%title('Example 26. Plot matrix vs. matrix') call gp%xlabel('my x axis ...') call gp%ylabel('my y axis ...') call gp%options('set key bottom left') !Call Plot to draw a matrix against a vector of data call gp%plot(x,y,lspec='t "y1" lw 2 ps 2 pt 6; t "y2" lw 2 ps 2 pt 7; t "y3" lw 2 ps 2 pt 9') end subroutine exmp26 !............................................................................... !Example 27: Using secondary y axis !............................................................................... subroutine exmp27() type(gpf):: gp integer, parameter:: n1=50, n2=75 real(wp):: x(n1), u(n1) real(wp):: t(n2), v(n2) ! Input data x = linspace(-5._wp,5._wp,n1) t = linspace(0._wp,15._wp,n2) u = sin(x) * cos(x) v = t*sin(t) ! Annotation: set title, xlabel, ylabel call gp%title('Example 27. Using secondary y axis') call gp%xlabel('primary x axis ...') call gp%ylabel('primary y axis ...') call gp%y2label('secondary y axis ...') ! turn on the y2 tics call gp%options('set y2tics') ! plot first data set with primary axes (defualt) ! and the second data set with secondary y axis call gp%plot(x, u, ls1= 't "primary y axis"', x2=t, y2=v, axes2='x1y2', ls2='t "secondary y axis"') end subroutine exmp27 !............................................................................... !Example 28: Using secondary x and secondary y axis !............................................................................... subroutine exmp28() ! exmp28 type(gpf):: gp integer, parameter:: n=50 real(wp):: t(n), v(n) ! Input data t = linspace(-3.1415d0, 3.1415d0, n) v = sin(t) * cos(t) ! Annotation: set title, xlabel, ylabel call gp%title ('Example 28. Plot using secondary x and y axis') call gp%xlabel ('primary x axis ...') call gp%ylabel ('primary y axis ...') call gp%x2label('secondary x axis ...') call gp%y2label('secondary y axis ...') ! use different color for secondary axis call gp%options('set x2tics tc "red"; set y2tics tc "red"') call gp%options('set xtics tc "blue"; set ytics tc "blue"') call gp%plot(t,v, axes1='x1y1', ls1='lc "blue" lw 2', x2=t, y2=t*t*v, axes2='x2y2', ls2='lc "red"') end subroutine exmp28 !............................................................................... !Example 29: Use color, font and size for labels !............................................................................... subroutine exmp29 type(gpf):: gp real(wp), dimension(100) :: x, y ! create data call random_number(x) call random_number(y) !Annotation, set title, xlabel, ylabel with color and font and rotation call gp%title('Example 29. Use color, font and size for labels', textcolor='blue', font_size=14) call gp%xlabel('rotated ...', textcolor='red', font_size=14, font_name='arial', rotate=10) call gp%ylabel('my y axis ...', textcolor='violet') call gp%options('set key bottom left') call gp%options('set style data points') !Call Plot to draw a matrix against a vector of data call gp%plot(x,y, 'lt 5 ps 1.25') end subroutine exmp29 !............................................................................... !Example 30: More on colors and size of labels !............................................................................... subroutine exmp30() ! exmp30 shows more customization on ogpf type(gpf) :: plt integer, parameter :: n=40 integer, parameter :: m=80 real(wp), dimension(n) :: t1, u1 real(wp), dimension(m) :: t2, u2 character(len=:), allocatable :: colorp, colors character(len=:), allocatable :: ls1, ls2 ! define rgb colors for primary and secondary axes colorp = '"#D95F02"' colors = '"#7570B3"' ! set the line specification and legends ls1='t "primary" lt 4 lw 1.25 ps 1.2 lc rgb ' // colorp ls2='t "secondary" lt 5 lw 1.25 ps 1.2 lc rgb ' // colors ! create data t1 = linspace(-10._wp, 10._wp, n) t2 = linspace(-3.14_wp, 3.14_wp, m) u1 = 0.5_wp * t1**2 u2 = exp(-t2)*sin(2.0*t2) ! turn on the second axes call plt%options('set xtics tc ' // colorp) call plt%options('set ytics tc ' // colorp) call plt%options('set x2tics tc ' // colors) call plt%options('set y2tics tc ' // colors) ! set labels and title call plt%title('Example 30. A customizes plot', textcolor='#E7298A', font_size = 15) call plt%xlabel('primary x', textcolor=colorp(2:8), font_size = 9) call plt%ylabel('primary y', textcolor=colorp(2:8), font_size = 9) call plt%x2label('secondary x', textcolor=colors(2:8), font_size = 12) call plt%y2label('secondary y', textcolor=colors(2:8), font_size = 12) ! plot data call plt%plot(t1,u1,ls1=ls1 , axes1='x1y1', x2=t2,y2=u2, ls2=ls2, axes2='x2y2') end subroutine exmp30 !------------------------------------------------------------------------------- ! 3D Plots !------------------------------------------------------------------------------- ! surface plot examples (gnuplot equivalent routine is splot) ! contour plot examples ! animation of 3D plots !............................................................................... !Example 101: A simple 3d plot !............................................................................... subroutine exmp101 type(gpf):: gp real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z(:,:) real(wp):: a=0.5d0 real(wp):: b=2.0d0 real(wp), allocatable :: xgrid(:) real(wp), allocatable :: ygrid(:) integer:: m integer:: n ! create 3D data m=55 ! number of grid points in y direction n=25 ! number of grid points in x direction allocate(xgrid,source=linspace(-10.0_wp, 10.0_wp, m)) ygrid=linspace(0.0_wp, 5.0_wp, n) allocate( z(m,n) ) call meshgrid(x, y, xgrid, ygrid) ! generate the 2D grid data z=(x**2/a - y**2/b) ! annotation call gp%title('Example 101: Simple 3D plot') call gp%xlabel('x-axis,...') call gp%ylabel('y-axis,...') call gp%zlabel('z-axis,...') !plot the 3D data call gp%surf(x, y, z, lspec='t "default color spec"' ) ! color palette: gnuplot default call gp%surf(x, y, z, lspec='t "Ann Schnider set1"', palette='set1' ) ! color palette: set1 call gp%surf(x, y, z, lspec='t "Matlab Jet"', palette='jet' ) ! color palette: Matlab jet end subroutine exmp101 !............................................................................... !Example 102: Another simple surface plot with legend and line color !............................................................................... subroutine exmp102() type(gpf):: gp real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z(:,:) integer:: m integer:: n ! generate data call meshgrid(x, y, linspace(-0.75_wp*pi, 0.75_wp*pi, 35) ) ! xgrid == ygrid m=size(x,1) n=size(x,2) allocate( z(m,n) ) !z= sin(x) * cos (y) where ((.not. x**2 + y**2 > 0.0_wp) .and. (.not. x**2 + y**2 < 0.0_wp)) z=1.0_wp elsewhere z=sin(x**2+y**2)/(x**2+y**2) end where call gp%title('Example 102: Simple 3D plot with color palette') call gp%xlabel('x-axis,...') call gp%ylabel('y-axis,...') !plot the 3D data CALL gp%surf(X,Y,Z, palette='jet') end subroutine exmp102 !............................................................................... !Example 103: A beautiful surface plot with hidden details !............................................................................... subroutine exmp103() type(gpf):: gp real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z(:,:) real(wp):: a=-0.5_wp real(wp):: b= 0.5_wp real(wp):: pi= 4.0_wp * atan(1.0_wp) integer:: m integer:: n ! create 3D data call meshgrid( x, y, linspace(a, b, 55) ) m=size(x,1) n=size(x,2) allocate( z(m,n) ) z= cos(2.0*pi*x) * sin(2.0*pi*y) ! annotation call gp%title('Example 103: A beautiful surface plot with hidden details') call gp%options('set hidden3d') call gp%options('set tics font ",8"') call gp%options('unset key') !plot the 3D data call gp%surf(x, y, z, palette='jet' ) ! color palette: Matlab jet ! contour call gp%contour(x,y,z, palette='set1') end subroutine exmp103 !............................................................................... !Example 104: Cylindrical mapping !............................................................................... subroutine exmp104() type(gpf):: gp integer, parameter :: m = 35 integer, parameter :: n = 15 real(wp) :: xv(m), yv(n) real(wp), dimension(:,:), allocatable:: x,y,z real(wp):: pi= 4.0_wp * atan(1.0_wp) xv = linspace(0.0_wp, pi, m) yv = linspace(0.0_wp, pi, n) call meshgrid(x,y, xv, yv) allocate( z(size(x,dim=1), size(x, dim=2)) ) z = sin(y) ! advanced options call gp%options('set mapping cylindrical') call gp%options('unset tics') call gp%options('unset border') call gp%options('set view 147,312') call gp%options('set hidden3d') ! call gp%title('Example 104. Cylindrical Mapping') call gp%surf(x,y,z) end subroutine exmp104 !............................................................................... !Example 105: contour plot !............................................................................... subroutine exmp105() type(gpf):: gp real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z(:,:) integer:: m integer:: n ! create the xyz data call meshgrid(x, y, linspace(-2.0_wp,2.0_wp, 65), linspace(-2.0_wp,3.0_wp, 65) ) m=size(x,1) n=size(x,2) allocate( z(m,n) ) z = x * exp(-x**2 - y**2) call gp%options('unset key') call gp%options('unset surface') call gp%axis([real(wp):: -2, 2, -2, 3]) !plot the contour call gp%options('unset border; unset tics') call gp%title('Example 105: Surface plot') call gp%surf(x,y,z, palette='accent') call gp%title('Example 105: Contour plot') call gp%contour(x,y,z, palette='jet') end subroutine exmp105 !............................................................................... !Example 106: Animation of surface plot !............................................................................... subroutine exmp106() type(gpf):: gp integer, parameter :: n=25, m=55 real(wp) :: xv(m), yv(n), t real(wp), allocatable :: x(:,:), y(:,:), z(:,:) real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) ! generate data xv = linspace(0.0_wp, 2.0_wp*pi, m) yv = linspace(0.0_wp, 2.0_wp*pi, n) call meshgrid(x, y, xv, yv) allocate(z, source = sin(x) + cos(y)) call gp%title('Example 106. Animation of surface plot') call gp%axis([0.0_wp, 2.0*pi, 0.0_wp, 2.0*pi]) call gp%options('unset colorbox') call gp%options('set ticslevel 0') call gp%axis([0.0_wp, 2.0*pi, 0.0_wp, 2.0*pi, -2.0_wp, 2.0_wp]) call gp%animation_start(1.) t=0.050_wp do ! add frames call gp%surf(x, y, sin(t*pi/2.0)*z, palette='jet') t=t+0.1_wp if (t > 1.0_wp) exit end do ! show frames in ornithological order with a pause set in ! animation_start call gp%animation_show() end subroutine exmp106 !............................................................................... !Example 107: Multiplot layout for 3D data !............................................................................... subroutine exmp107() type(gpf):: gp real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z1(:,:) real(wp), allocatable:: z2(:,:) integer:: m integer:: n real(wp), parameter :: pi=4.0_wp*atan(1.0_wp) ! create the xyz data call meshgrid(x, y, linspace(-pi,pi, 60) ) m=size(x,1) n=size(x,2) allocate( z1(m,n) ) allocate( z2(m,n) ) z1 = sin(x) + cos(y) z2 = sin(x) * cos(y) call gp%options('unset key') call gp%axis([-pi,pi,-pi,pi]) call gp%options('unset colorbox') call gp%options('set autoscale fix') call gp%options('unset tics') !plot the contour call gp%title('Example 107: surface plot') call gp%multiplot(1,2) call gp%surf(x,y,z1) call gp%surf(x,y,z2) call gp%multiplot(2,1) call gp%title('Example 107: Contour plot') call gp%options('set colorbox') call gp%options('set tics') call gp%options('set tics font ",8"') ! font size for tics call gp%contour(x,y,z1, palette='jet') call gp%contour(x,y,z2, palette='set1') end subroutine exmp107 !............................................................................... !Example 108: Plod a 2D grid !............................................................................... subroutine exmp108 type(gpf):: gp integer, parameter:: n=10 real(wp), allocatable :: x(:,:) real(wp), allocatable :: y(:,:), z(:,:) ! create data call meshgrid(x,y,linspace(1.0d0, 10.0d0, n)) allocate(z(n,n)) z=1.0d0 ! set gnuplot options call gp%options('unset border') ! turn off border line (axes) call gp%options('unset tics') ! turn off axes values (tics) call gp%options('set view map') ! set viewpoint top down ! plot using linespec call gp%surf(x,y,z,lspec='w lp ps 2 pt 6 lc "#99aa33') end subroutine exmp108 !............................................................................... !Example 109: Plot a 2D grid with random data, but use zlim to select a zrange !............................................................................... subroutine exmp109() type(gpf):: gp integer, parameter:: n=100 real(wp), allocatable:: x(:,:) real(wp), allocatable:: y(:,:) real(wp), allocatable:: z(:,:) ! create the xyz data call meshgrid(x,y,linspace(-1.5_wp,1.5_wp,n)) allocate(z(n,n)) ! fills with random numbers call random_number(z) ! make them between -1.0_wp and 1.0_wp z = z - 2.0_wp*z ! create regions outsize such range z = merge(-2.0_wp, z, x >= -.2_wp .and. x <= .2_wp) z = merge(-2.0_wp, z, y >= -.2_wp .and. y <= .2_wp) !plot the contour call gp%title('Example 109: Zlim Example') call gp%options('unset border') ! turn off border line (axes) call gp%options('set view map') ! Anything outside -1.0_wp and 1.0_wp will be cut off call gp%zlim([-1.0_wp,1.0_wp]) call gp%options('set cbrange[-1.0:1.0]') call gp%surf(x,y,z,palette='set1') end subroutine exmp109 end program demo ================================================ FILE: fpm.toml ================================================ name="ogpf" description = "Object Based Interface to GnuPlot from Fortran" version = "0.4.0" license = "MIT" author = "Mohammad Rahmani" copyright = "2020 Mohammad Rahmani" ================================================ FILE: meson.build ================================================ project('Ogpf', 'fortran') gnuplot = find_program('gnuplot', required: true) libogpf = library('ogpf', 'src/ogpf.f90', fortran_args: '-std=f2008') libogpf_dep = declare_dependency( link_with: libogpf) executable('demo', 'example/demo.f90', dependencies: libogpf_dep) ================================================ FILE: revision.txt ================================================ Rev 0.20 March 1st, 2018 ================================================ FILE: sample_script.gp ================================================ # https://linuxgazette.net/133/luana.html set size ratio -1 set nokey set noxtics set noytics set noborder set parametric # x(t) = (R-r)*cos(t) + p*cos((R-r)*t/r) y(t) = (R-r)*sin(t) - p*sin((R-r)*t/r) # # Greatest common divisor: gcd(x,y) = (x%y==0 ? y : gcd(y,x%y)) # change these integer parameters to get very nice drawings R = 100; r = 2; p = 70; res = 175 # rr = abs(r) nturns = rr / gcd(R,rr) samp = 1 + res * nturns set samples samp # plot [t=0:nturns*2*pi] x(t),y(t) ================================================ FILE: src/ogpf.f90 ================================================ !------------------------------------------------------------------------------- ! GnuPlot Interface !------------------------------------------------------------------------------- ! Purpose: Object Based Interface to GnuPlot from Fortran (ogpf) ! Platform: Windows XP/Vista/7/10 ! (It should work on other platforms, see the finalize_plot subroutine below) ! Language: Fortran 2003 and 2008 ! Requires: 1. Fortran 2003 compiler (e.g gfortran 5, IVF 12.1, ...) ! There is only two more features needs Fortran 2008 standard ! execute_command_line and passing internal function as argument. ! 2. gnuplot 5 and higher (other previous version can be used ! Author: Mohammad Rahmani ! Chem Eng Dep., Amirkabir Uni. of Tech ! Tehran, Ir ! url: aut.ac.ir/m.rahmani ! github: github.com/kookma ! email: m[dot]rahmani[at]aut[dot]ac[dot]ir ! ! ! Acknowledgement: ! Special thanks to Hagen Wierstorf (http://www.gnuplotting.org) ! For vluable codes and examples on using gnuplot ! Some examples and color palletes are provided by gnuplotting. ! ! Revision History ! Revision 0.22 ! Date: Mar 9th, 2018 ! - a new procedure called use_extra_configuration is used to set general gnuplot settings ! - new type for labels (xlabel, ylabel, zlabel, title,...) ! - all lables now accept text color, font name, font size, rorate by degree ! - Secondary axes can use different scale (linear or logarithmic) ! - subroutine plot2d_matrix_vs_matrix(xmat,ymat) ! now plots a matrix columns ymat aganist another matrix column xmat ! - added more examples ! Revision 0.21 ! Date: Mar 8th, 2018 ! - new axes to plot command to use secondary axes added! ! Revision: 0.20 ! Date: Feb 20th, 2018 ! - ogpf now supports animation for 2D and 3D plots ! - rewrite contour and surface plot ! - select_precision has been merged into ogpf ! - new add_script procedure replaced old script ! - new run_script procedure ! - writestring procedure removed ! - linespec for plor2d_matrix_vs_plot now is a single dynamic string ! - splot now uses datablok instead of inline data ! - meshgrid now support full grid vector ! - arange a numpy similar function to create a range in the form of [xa, xa+dx, xa+2*dx, ...] ! - new num2str routines ! Revision: 0.19 ! Date: Jan 15th, 2018 ! - new contour plot procedure ! Revision: 0.18 ! Date: Dec 22th, 2017 ! Major revision ! - The dynamic string allocation of Fortran 2003 is used (some old compilers ! does not support this capability) ! - Multiple windows plot now supported ! - Multiplot now supported ! - Gnuplot script file extension is changed from .plt to .gp ! - Default window size (canvas) changed to 640x480 ! - Persist set to on (true) by default ! - A separate subroutine is used now to create the output file for gnuplot commands ! - A separate subroutine is used now to finalize the output ! ! Revision: 0.17 ! Date: Dec 18th, 2017 ! Minor corrections ! - Correct the meshgrid for wrong dy calculation when ygv is sent by two elements. ! - Remove the subroutine ErrHandler (development postponed to future release) ! Revision: 0.16 ! Date: Feb 11th, 2016 ! Minor corrections ! Correct the lspec processing in plot2D_matrix_vs_vector ! Now, it is possible to send less line specification and gpf will cycle through lspec ! Revision: 0.15 ! Date: Apr 20th, 2012 ! Minor corrections ! Use of select_precision module and working precision: wp ! Revision: 0.14 ! Date: Mar 28th, 2012 ! Minor corrections ! Use of import keyboard and removing the Precision module ! Length of Title string increased by 80 chars ! Revision: 0.13 ! Date: Feb 12th, 2012 ! Minor corrections ! Added axis method which sets the axis limits for x-axis, y-axis and z-axis ! Added Precision module ! Version: 0.12 ! Date: Feb 9th, 2012 ! Minor corrections ! New semilogx, semilogy, loglog methods ! New options method, allow to be called several times to set the gnuplot options ! Version: 0.11 ! Date: Feb 9th, 2012 ! Minor corrections ! Use of NEWUINT specifier from Fortran 2008 ! Added configuration parameters ! Extra procedures have been removed ! Temporary file is now deleted using close(...,status='delete') ! ! Version: 0.1 ! Date: Jan 5th, 2012 ! First object-based version module ogpf implicit none private public arange, linspace, meshgrid, wp public num2str !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! select precision ! ! sp: kind for single precision ! dp: kind for double precision ! ! wp: kind for working precision (set to either sp or dp) integer, parameter :: sp = kind( 1.0 ) integer, parameter :: dp = kind( 1.0d0 ) integer, parameter :: wp = dp !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Library information character(len=*), parameter :: md_name = 'ogpf libray' character(len=*), parameter :: md_rev = 'Rev. 0.22 of March 9th, 2018' character(len=*), parameter :: md_lic = 'Licence: MIT' ! ogpf Configuration parameters ! The terminal and font have been set for Windows operating system ! Correct to meet the requirements on other OS like Linux and Mac. character(len=*), parameter :: gnuplot_term_type = 'wxt' ! Output terminal character(len=*), parameter :: gnuplot_term_font = 'verdana,10' ! font character(len=*), parameter :: gnuplot_term_size = '640,480' !'960,840' ! plot window size character(len=*), parameter :: gnuplot_output_filename='ogpf_temp_script.gp' ! temporary file for output ! extra configuration can be set using ogpf object ! module procedure interface num2str ! convert integer, real, double precision into string module procedure num2str_i4 module procedure num2str_r4 module procedure num2str_r8 end interface !> 0.22 ! tplabel is a structure for gnuplot labels including ! title, xlabel, x2label, ylabel, ... integer, parameter, private :: NOT_INITIALIZED = -32000 type tplabel logical :: has_label = .false. character(len=:), allocatable :: lbltext character(len=:), allocatable :: lblcolor character(len=:), allocatable :: lblfontname integer :: lblfontsize = NOT_INITIALIZED integer :: lblrotate = NOT_INITIALIZED end type tplabel type, public :: gpf ! the gpf class implement the object for using gnuplot from fortran in a semi-interactive mode! ! the fortran actually do the job and write out the commands and data in a single file and then ! calls the gnuplot by shell command to plot the data private !> 0.22 type(tplabel) :: tpplottitle type(tplabel) :: tpxlabel type(tplabel) :: tpx2label type(tplabel) :: tpylabel type(tplabel) :: tpy2label type(tplabel) :: tpzlabel character(len=:), allocatable :: txtoptions ! a long string to store all type of gnuplot options character(len=:), allocatable :: txtscript ! a long string to store gnuplot script character(len=:), allocatable :: txtdatastyle ! lines, points, linepoints logical :: hasxrange = .false. logical :: hasx2range = .false. logical :: hasyrange = .false. logical :: hasy2range = .false. logical :: haszrange = .false. logical :: hasoptions = .false. logical :: hasanimation = .false. logical :: hasfilename = .false. logical :: hasfileopen = .false. real(wp) :: xrange(2), yrange(2), zrange(2) real(wp) :: x2range(2), y2range(2) character(len=8) :: plotscale ! multiplot parameters logical :: hasmultiplot = .false. integer :: multiplot_rows integer :: multiplot_cols integer :: multiplot_total_plots ! animation real :: pause_seconds = 0 ! keep plot on screen for this value in seconds integer :: frame_number ! frame number in animation ! use for debugging and error handling character(len=:), allocatable :: msg !Message from plot procedures integer :: status=0 !Status from plot procedures ! integer :: file_unit ! file unit identifier character(len=:), allocatable :: txtfilename ! the name of physical file ! to write the gnuplot script ! ogpf preset configuration (kind of gnuplot initialization) logical :: preset_configuration = .true. contains private ! local private procedures procedure, pass, private :: preset_gnuplot_config procedure, pass, private :: plot2d_vector_vs_vector procedure, pass, private :: plot2d_matrix_vs_vector procedure, pass, private :: plot2d_matrix_vs_matrix procedure, pass, private :: semilogxv procedure, pass, private :: semilogxm procedure, pass, private :: semilogyv procedure, pass, private :: semilogym procedure, pass, private :: loglogv procedure, pass, private :: loglogm !> 0.22 procedure, pass, private :: set_label ! public procedures procedure, pass, public :: options => set_options procedure, pass, public :: title => set_plottitle procedure, pass, public :: xlabel => set_xlabel procedure, pass, public :: x2label => set_x2label procedure, pass, public :: ylabel => set_ylabel procedure, pass, public :: y2label => set_y2label procedure, pass, public :: zlabel => set_zlabel procedure, pass, public :: axis => set_axis procedure, pass, public :: axis_sc => set_secondary_axis procedure, pass, public :: xlim => set_xlim procedure, pass, public :: ylim => set_ylim procedure, pass, public :: zlim => set_zlim procedure, pass, public :: filename => set_filename procedure, pass, public :: reset => reset_to_defaults procedure, pass, public :: preset => use_preset_configuration procedure, pass, public :: multiplot => sub_multiplot generic, public :: plot => plot2d_vector_vs_vector, & plot2d_matrix_vs_vector, & plot2d_matrix_vs_matrix generic, public :: semilogx => semilogxv, semilogxm generic, public :: semilogy => semilogyv, semilogym generic, public :: loglog => loglogv, loglogm procedure, pass, public :: surf => splot ! 3D surface plot procedure, pass, public :: lplot => lplot3d ! 3D line plot procedure, pass, public :: contour => cplot ! contour plot procedure, pass, public :: fplot => function_plot procedure, pass, public :: add_script => addscript procedure, pass, public :: run_script => runscript procedure, pass, public :: animation_start => sub_animation_start procedure, pass, public :: animation_show => sub_animation_show end type gpf contains !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!> Section One: Set/Get Methods for ogpf object !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ subroutine use_preset_configuration(this,flag) !.............................................................................. !Set a flag to tell ogpf if the customized gnuplot configuration should !be used !.............................................................................. class(gpf):: this logical, intent(in) :: flag ! default is true this%preset_configuration = flag end subroutine use_preset_configuration subroutine set_filename(this,string) !.............................................................................. !Set a file name for plot command output !This file can be used later by gnuplot as an script file to reproduce the plot !.............................................................................. class(gpf):: this character(len=*), intent(in) :: string this%txtfilename = trim(string) this%hasfilename = .true. end subroutine set_filename subroutine set_options(this,stropt) !.............................................................................. ! Set the plot options. This is a very powerfull procedure accepts many types ! of gnuplot command and customization !.............................................................................. class(gpf):: this character(len=*), intent(in) :: stropt if(.not.allocated(this%txtoptions))this%txtoptions='' if (len_trim(this%txtoptions) == 0 ) then this%txtoptions = '' ! initialize string end if if ( len_trim(stropt)>0 ) then this%txtoptions = this%txtoptions // splitstr(stropt) end if this%hasoptions=.true. end subroutine set_options subroutine set_xlim(this,rng) !.............................................................................. !Set the x axis limits in form of [xmin, xmax] !.............................................................................. class(gpf):: this real(wp), intent(in) :: rng(2) this%hasxrange=.true. this%xrange=rng end subroutine subroutine set_ylim(this,rng) !.............................................................................. !Set the y axis limits in form of [ymin, ymax] !.............................................................................. class(gpf):: this real(wp), intent(in) :: rng(2) this%hasyrange=.true. this%yrange=rng end subroutine subroutine set_zlim(this,rng) !.............................................................................. !Set the z axis limits in form of [zmin, zmax] !.............................................................................. class(gpf):: this real(wp), intent(in) :: rng(2) this%haszrange=.true. this%zrange=rng end subroutine subroutine set_axis(this,rng) !.............................................................................. !Set the axes limits in form of [xmin, xmax, ymin, ymax, zmin, zmax] !.............................................................................. class(gpf):: this real(wp), intent(in) :: rng(:) integer :: n n=size(rng,dim=1) select case(n) case(2) !Only the range for x-axis has been sent this%hasxrange=.true. this%xrange=rng(1:2) case(4) this%hasxrange=.true. this%hasyrange=.true. this%xrange=rng(1:2) this%yrange=rng(3:4) case(6) this%hasxrange=.true. this%hasyrange=.true. this%haszrange=.true. this%xrange=rng(1:2) this%yrange=rng(3:4) this%zrange=rng(5:6) case default print*, 'gpf error: wrong axis range setting!' return end select end subroutine set_axis subroutine set_secondary_axis(this,rng) !.............................................................................. !Set the secondary axes limits in form of [x2min, x2max, y2min, y2max] !.............................................................................. class(gpf):: this real(wp), intent(in) :: rng(:) integer :: n n=size(rng,dim=1) select case(n) case(2) !Only the range for x2-axis has been sent this%hasx2range=.true. this%x2range=rng(1:2) case(4) this%hasx2range=.true. this%hasy2range=.true. this%x2range=rng(1:2) this%y2range=rng(3:4) case default print*, 'gpf error: wrong axis range setting!' return end select end subroutine set_secondary_axis subroutine set_plottitle(this, string, textcolor, font_size, font_name, rotate) !.............................................................................. !Set the plot title !.............................................................................. class(gpf):: this character(len=*), intent(in) :: string character(len=*), intent(in), optional :: textcolor integer, optional :: font_size character(len=*), intent(in), optional :: font_name integer, optional :: rotate call this%set_label('plot_title', string, textcolor, font_size, font_name, rotate) end subroutine set_plottitle subroutine set_xlabel(this, string, textcolor, font_size, font_name, rotate) !.............................................................................. !Set the xlabel !.............................................................................. class(gpf):: this character(len=*), intent(in) :: string character(len=*), intent(in), optional :: textcolor integer, optional :: font_size character(len=*), intent(in), optional :: font_name integer, optional :: rotate call this%set_label('xlabel', string, textcolor, font_size, font_name, rotate) end subroutine set_xlabel subroutine set_x2label(this, string, textcolor, font_size, font_name, rotate) !.............................................................................. !Set the x2label !.............................................................................. class(gpf):: this character(len=*), intent(in) :: string character(len=*), intent(in), optional :: textcolor integer, optional :: font_size character(len=*), intent(in), optional :: font_name integer, optional :: rotate call this%set_label('x2label', string, textcolor, font_size, font_name, rotate) end subroutine set_x2label subroutine set_ylabel(this, string, textcolor, font_size, font_name, rotate) !.............................................................................. !Set the ylabel !.............................................................................. class(gpf):: this character(len=*), intent(in) :: string character(len=*), intent(in), optional :: textcolor integer, optional :: font_size character(len=*), intent(in), optional :: font_name integer, optional :: rotate call this%set_label('ylabel', string, textcolor, font_size, font_name, rotate) end subroutine set_ylabel subroutine set_y2label(this, string, textcolor, font_size, font_name, rotate) !.............................................................................. !Set the y2label !.............................................................................. class(gpf):: this character(len=*), intent(in) :: string character(len=*), intent(in), optional :: textcolor integer, optional :: font_size character(len=*), intent(in), optional :: font_name integer, optional :: rotate call this%set_label('y2label', string, textcolor, font_size, font_name, rotate) end subroutine set_y2label subroutine set_zlabel(this, string, textcolor, font_size, font_name, rotate) !.............................................................................. !Set the zlabel !.............................................................................. class(gpf):: this character(len=*), intent(in) :: string character(len=*), intent(in), optional :: textcolor integer, optional :: font_size character(len=*), intent(in), optional :: font_name integer, optional :: rotate call this%set_label('zlabel', string, textcolor, font_size, font_name, rotate) end subroutine set_zlabel !> 0.22 subroutine set_label(this, lblname, lbltext, lblcolor, font_size, font_name, rotate) !.............................................................................. ! Set the text, color, font, size and rotation for labels including ! title, xlabel, x2label, ylabel, .... !.............................................................................. class(gpf):: this character(len=*), intent(in) :: lblname character(len=*), intent(in) :: lbltext character(len=*), intent(in), optional :: lblcolor character(len=*), intent(in), optional :: font_name integer, optional :: font_size integer, optional :: rotate ! local variable type(tplabel) :: label label%has_label = .true. label%lbltext = trim(lbltext) if (present(lblcolor)) then label%lblcolor = lblcolor end if if (present(font_name)) then label%lblfontname = font_name else if(.not.allocated(label%lblfontname))then label%lblfontname = '' endif end if if (present(font_size)) then label%lblfontsize = font_size end if if (present(rotate)) then label%lblrotate = rotate end if select case (lblname) case ('xlabel') this%tpxlabel = label case ('x2label') this%tpx2label = label case ('ylabel') this%tpylabel = label case ('y2label') this%tpy2label = label case ('zlabel') this%tpzlabel = label case ('plot_title') this%tpplottitle = label end select end subroutine set_label subroutine reset_to_defaults(this) !.............................................................................. !Reset all ogpf properties (params to their default values !............................................................................... class(gpf):: this this%preset_configuration = .true. this%txtfilename = gnuplot_output_filename if (allocated(this%txtoptions)) deallocate(this%txtoptions) if (allocated(this%txtscript)) deallocate(this%txtscript) if (allocated(this%txtdatastyle)) deallocate(this%txtdatastyle) if (allocated(this%msg)) deallocate(this%msg) this%hasoptions = .false. this%hasxrange = .false. this%hasx2range = .false. this%hasyrange = .false. this%hasy2range = .false. this%haszrange = .false. this%pause_seconds = 0.0 this%status = 0 this%hasanimation = .false. this%hasfileopen = .false. this%hasmultiplot = .false. this%plotscale = '' this%tpplottitle%has_label =.false. this%tpxlabel%has_label =.false. this%tpx2label%has_label =.false. this%tpylabel%has_label =.false. this%tpy2label%has_label =.false. this%tpzlabel%has_label =.false. end subroutine reset_to_defaults !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!> Section Two: Main Plotting Routines !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ subroutine sub_multiplot(this, rows, cols) !.............................................................................. ! This subroutine sets flag and number of rows and columns in case ! of multiplot layout !.............................................................................. class(gpf):: this integer, intent(in) :: rows integer, intent(in) :: cols ! ogpf does not support multiplot in animation mode if (this%hasanimation) then print*, md_name // ': ogpf does not support animation in multiplot mode' stop end if ! set multiplot cols and rows if (rows> 0 ) then this%multiplot_rows = rows else end if if (cols > 0 ) then this%multiplot_cols = cols else end if ! set the multiplot layout flag and plot numbers this%hasmultiplot = .true. this%multiplot_total_plots = 0 ! create the ouput file for writting gnuplot script call create_outputfile(this) end subroutine sub_multiplot subroutine plot2d_vector_vs_vector(this, x1, y1, ls1, axes1, & x2, y2, ls2, axes2, & x3, y3, ls3, axes3, & x4, y4, ls4, axes4 ) !.............................................................................. ! This procedure plots: ! 1. A vector against another vector (xy plot) ! 2. A vector versus its element indices (yi plot). ! 3. Can accept up to 4 data sets as x,y pairs! ! Arguments ! xi, yi vectors of data series, ! lsi a string maximum 80 characters containing the line specification, ! legends, ... ! axesi is the axes for plotting: secondary axes are x2, and y2 !.............................................................................. class(gpf):: this ! Input vector real(wp), intent(in) :: x1(:) ! vector of data for x real(wp), intent(in), optional :: y1(:) ! vector of data for y character(len=*), intent(in), optional :: ls1 ! line specification character(len=*), intent(in), optional :: axes1 real(wp), intent(in), dimension(:), optional :: x2 real(wp), intent(in), dimension(:), optional :: y2 character(len=*), intent(in), optional :: ls2 character(len=*), intent(in), optional :: axes2 real(wp), intent(in), dimension(:), optional :: x3 real(wp), intent(in), dimension(:), optional :: y3 character(len=*), intent(in), optional :: ls3 character(len=*), intent(in), optional :: axes3 real(wp), intent(in), dimension(:), optional :: x4 real(wp), intent(in), dimension(:), optional :: y4 character(len=*), intent(in), optional :: ls4 character(len=*), intent(in), optional :: axes4 ! Local variables !---------------------------------------------------------------------- integer:: nx1 integer:: ny1 integer:: nx2 integer:: ny2 integer:: nx3 integer:: ny3 integer:: nx4 integer:: ny4 integer:: number_of_plots character(len=3):: plottype integer:: i character(len=80) :: pltstring(4) ! Four 80 characters string !Initialize variables plottype = '' pltstring = '' ! Check the input nx1=size(x1) if ((present(y1) )) then ny1=size(y1) if (checkdim(nx1,ny1)) then plottype='xy1' number_of_plots=1 else print*, md_name // ':plot2d_vector_vs_vector:' // 'length of x1 and y1 does not match' return end if else !plot only x againest its element indices plottype='xi' number_of_plots=1 end if !Process line spec and axes set for first data set if present call process_linespec(1, pltstring(1), ls1, axes1) if (present(x2) .and. present (y2)) then nx2=size(x2) ny2=size(y2) if (checkdim(nx2,ny2)) then plottype='xy2' number_of_plots=2 else return end if !Process line spec for 2nd data set if present call process_linespec(2, pltstring(2), ls2, axes2) end if if (present(x3) .and. present (y3)) then nx3=size(x3) ny3=size(y3) if (checkdim(nx3,ny3)) then plottype='xy3' number_of_plots=3 else return end if !Process line spec for 3rd data set if present call process_linespec(3, pltstring(3), ls3, axes3) end if if (present(x4) .and. present (y4)) then nx4=size(x4) ny4=size(y4) if (checkdim(nx4,ny4)) then plottype='xy4' number_of_plots=4 else return end if !Process line spec for 4th data set if present call process_linespec(4, pltstring(4), ls4, axes4) end if call create_outputfile(this) ! Write plot title, axis labels and other annotations call processcmd(this) ! Write plot command and line styles and legend if any if (number_of_plots ==1) then write ( this%file_unit, '(a)' ) trim(pltstring(1)) else write ( this%file_unit, '(a)' ) ( trim(pltstring(i)) // ' \' , i=1, number_of_plots-1) write ( this%file_unit, '(a)' ) trim(pltstring(number_of_plots)) end if ! Write xy data into file select case (plottype) case ('xi') call write_xydata(this%file_unit,nx1,x1) case ('xy1') call write_xydata(this%file_unit,nx1,x1,y1) case ('xy2') call write_xydata(this%file_unit,nx1,x1,y1) call write_xydata(this%file_unit,nx2,x2,y2) case ('xy3') call write_xydata(this%file_unit,nx1,x1,y1) call write_xydata(this%file_unit,nx2,x2,y2) call write_xydata(this%file_unit,nx3,x3,y3) case ('xy4') call write_xydata(this%file_unit,nx1,x1,y1) call write_xydata(this%file_unit,nx2,x2,y2) call write_xydata(this%file_unit,nx3,x3,y3) call write_xydata(this%file_unit,nx4,x4,y4) end select !> Rev 0.2 ! if there is no animation finalize if (.not. (this%hasanimation)) then call finalize_plot(this) else write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds end if !: End of plot2D_vector_vs_vector end subroutine plot2d_vector_vs_vector subroutine plot2d_matrix_vs_vector(this, xv,ymat, lspec) !.............................................................................. ! plot2D_matrix_vs_vector accepts a vector xv and a matrix ymat and plots ! columns of ymat against xv. lspec is an optional array defines the line ! specification for each data series. If a single element array is sent for ! lspec then all series are plotted using the same linespec !.............................................................................. implicit none class(gpf):: this ! Input arrays real(wp), intent(in) :: xv(:) real(wp), intent(in) :: ymat(:,:) character(len=*), intent(in), optional :: lspec !---------------------------------------------------------------------- ! Local variables integer:: nx integer:: ny integer:: ns integer:: number_of_curves integer:: i integer:: j integer:: ierr character(len=80), allocatable :: pltstring(:), lst(:) ! !******************************************************************************* ! Check the input nx=size(xv) ny=size(ymat,dim=1) if (.not. checkdim(nx,ny)) then print*, md_name // ':plot2d_matrix_vs_vector:' // 'The length of arrays does not match' return end if ! create the outfile to write the gnuplot script call create_outputfile(this) ! Write titles and other annotations call processcmd(this) ! Write plot command and line styles and legend if any number_of_curves=size(ymat,dim=2) allocate(pltstring(number_of_curves), stat=ierr) if (ierr /=0) then print*, 'allocation error' return end if ! assume no linespec is available pltstring(1:number_of_curves) = '' if ( present(lspec) ) then call splitstring2array(lspec,lst,';') ns = size(lst, dim=1) if (ns == number_of_curves) then ! there is a linespec for each curve pltstring = lst elseif (ns < number_of_curves) then ! not enough linespec do i=1, ns pltstring(i) = lst(i) end do else ! ns > number_of curves print*, 'ogpf: plot2d_matrix_vs_vector: wrong number of linespec' print*, 'semicolon ";" acts as delimiter, check the linespec' end if end if if ( present(lspec) ) then call process_linespec(1,pltstring(1),lst(1)) ns=size(lst) ! gpf will cylce through line specification, if number of specification passed ! is less than number of plots do i=1, number_of_curves j=mod(i-1, ns) + 1 call process_linespec(i, pltstring(i), lst(j)) end do else !No lspec is available pltstring(1)=' plot "-" notitle,' pltstring(2:number_of_curves-1)='"-" notitle,' pltstring(number_of_curves)='"-" notitle' end if ! Write plot command and line styles and legend if any write ( this%file_unit, '(a)' ) ( trim(pltstring(i)) // ' \' , i=1, number_of_curves-1) write ( this%file_unit, '(a)' ) trim(pltstring(number_of_curves)) ! Write data into script file do j=1, number_of_curves do i = 1, nx write ( this%file_unit, * ) xv(i),ymat(i,j) end do write ( this%file_unit, '(a)' ) 'e' !end of jth set of data end do !> Rev 0.2 ! if there is no animation finalize if (.not. (this%hasanimation)) then call finalize_plot(this) else write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds end if !Release memory if (allocated(pltstring)) then deallocate(pltstring) end if !: End of plot2D_matrix_vs_vector end subroutine plot2d_matrix_vs_vector subroutine plot2d_matrix_vs_matrix(this, xmat,ymat, lspec) !.............................................................................. ! plot2D_matrix_vs_matrix accepts a matrix xmat and a matrix ymat and plots ! columns of ymat against columns of xmat. lspec is an optional array defines ! the line specification for each data series. If a single element array is ! sent for lspec then all series are plotted using the same linespec !.............................................................................. implicit none class(gpf):: this ! Input arrays real(wp), intent(in) :: xmat(:,:) real(wp), intent(in) :: ymat(:,:) character(len=*), intent(in), optional :: lspec !---------------------------------------------------------------------- ! Local variables integer:: mx, nx integer:: my, ny integer:: ns integer:: number_of_curves integer:: i integer:: j integer:: ierr character(len=80), allocatable :: pltstring(:), lst(:) ! !******************************************************************************* ! Check the input ! check number of rows mx=size(xmat,dim=1) my=size(ymat,dim=1) if (.not. checkdim(mx,my)) then print*, md_name // ':plot2d_matrix_vs_matrix:' // 'The length of arrays does not match' return end if ! check number of rows nx=size(xmat,dim=2) ny=size(ymat,dim=2) if (.not. checkdim(nx,ny)) then print*, 'gpf error: The number of columns are different, check xmat, ymat' return end if ! create the outfile to write the gnuplot script call create_outputfile(this) ! Write titles and other annotations call processcmd(this) ! Write plot command and line styles and legend if any number_of_curves=size(ymat,dim=2) allocate(pltstring(number_of_curves), stat=ierr) if (ierr /=0) then print*, 'allocation error' return end if ! assume no linespec is available pltstring(1:number_of_curves) = '' if ( present(lspec) ) then call splitstring2array(lspec,lst,';') ns = size(lst, dim=1) if (ns == number_of_curves) then ! there is a linespec for each curve pltstring = lst elseif (ns < number_of_curves) then ! not enough linespec do i=1, ns pltstring(i) = lst(i) end do else ! ns > number_of curves print*, md_name // ': plot2d_matrix_vs_matrix:'//' wrong number of linespec' print*, 'semicolon ";" acts as delimiter, check the linespec' end if end if if ( present(lspec) ) then call process_linespec(1,pltstring(1),lst(1)) ns=size(lst) ! gpf will cylce through line specification, if number of specification passed ! is less than number of plots do i=1, number_of_curves j=mod(i-1, ns) + 1 call process_linespec(i, pltstring(i), lst(j)) end do else !No lspec is available pltstring(1)=' plot "-" notitle,' pltstring(2:number_of_curves-1)='"-" notitle,' pltstring(number_of_curves)='"-" notitle' end if ! Write plot command and line styles and legend if any write ( this%file_unit, '(a)' ) ( trim(pltstring(i)) // ' \' , i=1, number_of_curves-1) write ( this%file_unit, '(a)' ) trim(pltstring(number_of_curves)) ! Write data into script file do j=1, number_of_curves do i = 1, mx write ( this%file_unit, * ) xmat(i,j),ymat(i,j) end do write ( this%file_unit, '(a)' ) 'e' !end of jth set of data end do !> Rev 0.2 ! if there is no animation finalize if (.not. (this%hasanimation)) then call finalize_plot(this) else write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds end if !Release memory if (allocated(pltstring)) then deallocate(pltstring) end if !: End of plot2D_matrix_vs_vector end subroutine plot2d_matrix_vs_matrix subroutine splot(this, x, y, z, lspec, palette) !.............................................................................. ! splot create a surface plot ! datablock is used instead of gnuplot inline file "-" !.............................................................................. class(gpf):: this ! Input vector real(wp), intent(in) :: x(:,:) real(wp), intent(in), optional :: y(:,:) real(wp), intent(in), optional :: z(:,:) character(len=*), intent(in), optional :: lspec character(len=*), intent(in), optional :: palette ! Local variables !---------------------------------------------------------------------- integer:: ncx integer:: nrx integer:: i integer:: j logical:: xyz_data character(len=80):: pltstring character(len=*), parameter :: datablock = '$xyz' pltstring='' ! Check the input data ncx=size(x,dim=2) nrx=size(x,dim=1) if (present(y) .and. present(z)) then xyz_data=.true. elseif (present(y)) then print*, "gpf error: Z matrix was not sent to 3D plot routine" return else xyz_data=.false. end if ! set default line style for 3D plot, can be overwritten this%txtdatastyle = 'lines' ! create the script file for writting gnuplot commands and data call create_outputfile(this) ! Write titles and other annotations call processcmd(this) ! Write xy data into file write ( this%file_unit, '(a)' ) '#data x y z' ! Rev 0.20 ! write the $xyz datablocks write( this%file_unit, '(a)' ) datablock // ' << EOD' if (xyz_data) then do j=1,ncx do i=1, nrx write ( this%file_unit, * ) x(i,j), y(i,j), z(i,j) enddo write( this%file_unit, '(a)' ) !put an empty line enddo write ( this%file_unit, '(a)' ) 'EOD' !end of datablock else !only Z has been sent (i.e. single matrix data) do j=1,ncx do i=1, nrx write ( this%file_unit, * ) i, j, x(i,j) enddo write( this%file_unit, '(a)' ) !put an empty line enddo write ( this%file_unit, '(a)' ) 'EOD' !end of datablock end if !write the color palette into gnuplot script file if (present(palette)) then write ( this%file_unit, '(a)' ) color_palettes(palette) write ( this%file_unit, '(a)' ) 'set pm3d' ! a conflict with lspec end if if ( present(lspec) ) then if (hastitle(lspec)) then pltstring='splot ' // datablock // ' ' // trim(lspec) else pltstring='splot ' // datablock // ' notitle '//trim(lspec) end if else pltstring='splot ' // datablock // ' notitle ' end if write ( this%file_unit, '(a)' ) trim(pltstring) !> Rev 0.2: animation ! if there is no animation finalize if (.not. (this%hasanimation)) then call finalize_plot(this) else write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds end if !: End of splot end subroutine splot subroutine cplot(this, x, y, z, lspec, palette) !.............................................................................. ! Rev 0.19 ! cplot creates a contour plot based on the three dimensional data !.............................................................................. class(gpf):: this ! Input vector real(wp), intent(in) :: x(:,:) real(wp), intent(in), optional :: y(:,:) real(wp), intent(in), optional :: z(:,:) character(len=*), intent(in), optional :: lspec character(len=*), intent(in), optional :: palette ! Local variables !---------------------------------------------------------------------- integer:: ncx integer:: nrx integer:: i integer:: j logical:: xyz_data character(len=80):: pltstring character(len=*), parameter :: datablock = '$xyz' ! character(len=*), parameter :: cntr_table = '$xyz_contour' pltstring='' ! Check the input data ncx=size(x,dim=2) nrx=size(x,dim=1) if (present(y) .and. present(z)) then xyz_data=.true. elseif (present(y)) then print*, "gpf error: Z matrix was not sent to 3D plot routine" return else xyz_data=.false. end if ! set default line style for 3D plot, can be overwritten this%txtdatastyle = 'lines' ! create the script file for writting gnuplot commands and data call create_outputfile(this) ! Write titles and other annotations call processcmd(this) ! Write xy data into file write ( this%file_unit, '(a)' ) '#data x y z' ! write the $xyz datablocks write( this%file_unit, '(a)' ) datablock // ' << EOD' if (xyz_data) then do j=1,ncx do i=1, nrx write ( this%file_unit, fmt=* ) x(i,j), y(i,j), z(i,j) enddo write( this%file_unit, '(a)' ) !put an empty line enddo write ( this%file_unit, '(a)' ) 'EOD' !end of datablock else !only Z has been sent (i.e. single matrix data) do j=1,ncx do i=1, nrx write ( this%file_unit, fmt=* ) i, j, x(i,j) enddo write( this%file_unit, '(a)' ) !put an empty line enddo write ( this%file_unit, '(a)' ) 'EOD' !end of datablock end if ! create the contour lines write ( this%file_unit, '(a)' ) ! empty line write ( this%file_unit, '(a)' ) '# create the contour' write ( this%file_unit, '(a)' ) 'set contour base' write ( this%file_unit, '(a)' ) 'set cntrparam levels 14' write ( this%file_unit, '(a)' ) 'unset surface' write ( this%file_unit, '(a)' ) 'set view map' !write the color palette into gnuplot script file if (present(palette)) then write ( this%file_unit, '(a)' ) color_palettes(palette) write ( this%file_unit, '(a)' ) 'set pm3d' ! a conflict with lspec end if write ( this%file_unit, '(a)' ) ! empty line if ( present(lspec) ) then if (hastitle(lspec)) then pltstring='splot ' // datablock // ' ' // trim(lspec) else pltstring='splot ' // datablock // ' notitle '//trim(lspec) end if else pltstring='splot ' // datablock // ' notitle ' end if write ( this%file_unit, '(a)' ) trim(pltstring) !> Rev 0.20 ! if there is no animation finalize if (.not. (this%hasanimation)) then call finalize_plot(this) else write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds end if !: End of cplot end subroutine cplot subroutine lplot3d(this, x, y, z, lspec, palette) !.............................................................................. ! lplot3d create a line plot in 3d ! datablock is used instead of gnuplot inline file "-" !.............................................................................. class(gpf):: this ! Input vector real(wp), intent(in) :: x(:) real(wp), intent(in), optional :: y(:) real(wp), intent(in), optional :: z(:) character(len=*), intent(in), optional :: lspec character(len=*), intent(in), optional :: palette ! Local variables !---------------------------------------------------------------------- integer:: nrx integer:: i logical:: xyz_data character(len=80):: pltstring character(len=*), parameter :: datablock = '$xyz' pltstring='' ! Check the input data nrx=size(x) if (present(y) .and. present(z)) then xyz_data=.true. elseif (present(y)) then print*, "gpf error: Z matrix was not sent to 3D plot routine" return else xyz_data=.false. end if ! set default line style for 3D plot, can be overwritten this%txtdatastyle = 'lines' ! create the script file for writing gnuplot commands and data call create_outputfile(this) ! Write titles and other annotations call processcmd(this) ! Write xy data into file write ( this%file_unit, '(a)' ) '#data x y z' ! Rev 0.20 ! write the $xyz datablocks write( this%file_unit, '(a)' ) datablock // ' << EOD' if (xyz_data) then do i=1, nrx write ( this%file_unit, * ) x(i), y(i), z(i) enddo write( this%file_unit, '(a)' ) !put an empty line write ( this%file_unit, '(a)' ) 'EOD' !end of datablock else !only Z has been sent (i.e. single matrix data) do i=1, nrx write ( this%file_unit, * ) i, x(i) enddo write( this%file_unit, '(a)' ) !put an empty line write ( this%file_unit, '(a)' ) 'EOD' !end of datablock end if !write the color palette into gnuplot script file if (present(palette)) then write ( this%file_unit, '(a)' ) color_palettes(palette) write ( this%file_unit, '(a)' ) 'set pm3d' ! a conflict with lspec end if if ( present(lspec) ) then if (hastitle(lspec)) then pltstring='splot ' // datablock // ' ' // trim(lspec) // 'with lines' else pltstring='splot ' // datablock // ' notitle '//trim(lspec) // 'with lines' end if else pltstring='splot ' // datablock // ' notitle with lines' end if write ( this%file_unit, '(a)' ) trim(pltstring) !> Rev 0.2: animation ! if there is no animation finalize if (.not. (this%hasanimation)) then call finalize_plot(this) else write(this%file_unit, '(a, F5.2)') 'pause ', this%pause_seconds end if !: End of lplot3d end subroutine lplot3d subroutine function_plot(this, func,xrange,np) !.............................................................................. ! fplot, plot a function in the range xrange=[xmin, xamx] with np points ! if np is not sent, then np=50 is assumed! ! func is the name of function to be plotted !.............................................................................. class(gpf):: this interface function func(x) import :: wp real(wp), intent(in) :: x real(wp) :: func end function func end interface real(wp), intent(in) :: xrange(2) integer, optional, intent(in):: np integer:: n integer:: i integer:: alloc_err real(wp), allocatable :: x(:) real(wp), allocatable :: y(:) if (present(np)) then n=np else n=50 end if allocate(x(1:n), y(1:n), stat=alloc_err) if (alloc_err /=0) then stop "Allocation error in fplot procedure..." end if !Create set of xy data x=linspace(xrange(1),xrange(2), n) y=[ (func(x(i)), i=1, n) ] call plot2d_vector_vs_vector(this,x,y) ! cleanup memory if (allocated(x)) deallocate(x) if (allocated(y)) deallocate(y) end subroutine function_plot subroutine semilogxv(this, x1, y1, ls1, axes1, & x2, y2, ls2, axes2, & x3, y3, ls3, axes3, & x4, y4, ls4, axes4 ) !.............................................................................. ! This procedure is the same as plotXY with logarithmic x1 and x2 axes !.............................................................................. class(gpf):: this ! Input vector real(wp), intent(in) :: x1(:) ! vector of data for x real(wp), intent(in), optional :: y1(:) ! vector of data for y character(len=*), intent(in), optional :: ls1 ! line specification character(len=*), intent(in), optional :: axes1 real(wp), intent(in), dimension(:), optional :: x2 real(wp), intent(in), dimension(:), optional :: y2 character(len=*), intent(in), optional :: ls2 character(len=*), intent(in), optional :: axes2 real(wp), intent(in), dimension(:), optional :: x3 real(wp), intent(in), dimension(:), optional :: y3 character(len=*), intent(in), optional :: ls3 character(len=*), intent(in), optional :: axes3 real(wp), intent(in), dimension(:), optional :: x4 real(wp), intent(in), dimension(:), optional :: y4 character(len=*), intent(in), optional :: ls4 character(len=*), intent(in), optional :: axes4 this%plotscale='semilogx' call plot2d_vector_vs_vector(this, & x1, y1, ls1, axes1, & x2, y2, ls2, axes2, & x3, y3, ls3, axes3, & x4, y4, ls4, axes4 ) ! Set the plot scale as linear. It means log scale is off this%plotscale='linear' end subroutine semilogxv !.............................................................................. subroutine semilogyv(this, x1, y1, ls1, axes1, & x2, y2, ls2, axes2, & x3, y3, ls3, axes3, & x4, y4, ls4,axes4 ) !.............................................................................. ! This procedure is the same as plotXY with logarithmic y1 and y2 axes !.............................................................................. class(gpf):: this ! Input vector real(wp), intent(in) :: x1(:) ! vector of data for x real(wp), intent(in), optional :: y1(:) ! vector of data for y character(len=*), intent(in), optional :: ls1 ! line specification character(len=*), intent(in), optional :: axes1 real(wp), intent(in), dimension(:), optional :: x2 real(wp), intent(in), dimension(:), optional :: y2 character(len=*), intent(in), optional :: ls2 character(len=*), intent(in), optional :: axes2 real(wp), intent(in), dimension(:), optional :: x3 real(wp), intent(in), dimension(:), optional :: y3 character(len=*), intent(in), optional :: ls3 character(len=*), intent(in), optional :: axes3 real(wp), intent(in), dimension(:), optional :: x4 real(wp), intent(in), dimension(:), optional :: y4 character(len=*), intent(in), optional :: ls4 character(len=*), intent(in), optional :: axes4 this%plotscale='semilogy' call plot2d_vector_vs_vector(this, & x1, y1, ls1, axes1, & x2, y2, ls2, axes2, & x3, y3, ls3, axes3, & x4, y4, ls4, axes4 ) ! Set the plot scale as linear. It means log scale is off this%plotscale='linear' end subroutine semilogyv subroutine loglogv(this, x1, y1, ls1, axes1, & x2, y2, ls2, axes2, & x3, y3, ls3, axes3, & x4, y4, ls4, axes4 ) !.............................................................................. ! This procedure is the same as plotXY with logarithmic x1, y1, x2, y2 axes !.............................................................................. class(gpf):: this ! Input vector real(wp), intent(in) :: x1(:) ! vector of data for x real(wp), intent(in), optional :: y1(:) ! vector of data for y character(len=*), intent(in), optional :: ls1 ! line specification character(len=*), intent(in), optional :: axes1 real(wp), intent(in), dimension(:), optional :: x2 real(wp), intent(in), dimension(:), optional :: y2 character(len=*), intent(in), optional :: ls2 character(len=*), intent(in), optional :: axes2 real(wp), intent(in), dimension(:), optional :: x3 real(wp), intent(in), dimension(:), optional :: y3 character(len=*), intent(in), optional :: ls3 character(len=*), intent(in), optional :: axes3 real(wp), intent(in), dimension(:), optional :: x4 real(wp), intent(in), dimension(:), optional :: y4 character(len=*), intent(in), optional :: ls4 character(len=*), intent(in), optional :: axes4 this%plotscale='loglog' call plot2d_vector_vs_vector(this, & x1, y1, ls1, axes1, & x2, y2, ls2, axes2, & x3, y3, ls3, axes3, & x4, y4, ls4, axes4 ) ! Set the plot scale as linear. It means log scale is off this%plotscale='linear' end subroutine loglogv subroutine semilogxm(this, xv, ymat, lspec) !.............................................................................. !Plots a matrix against a vector with logarithmic x-axis !For more information see plot2D_matrix_vs_vector procedure !Everything is the same except the x-axis scale !.............................................................................. implicit none class(gpf) :: this ! Input arrays real(wp), intent(in) :: xv(:) real(wp), intent(in) :: ymat(:,:) character(len=*), intent(in), optional :: lspec this%plotscale='semilogx' call plot2d_matrix_vs_vector(this, xv,ymat, lspec) ! Set the plot scale as linear. It means log scale is off this%plotscale='linear' end subroutine semilogxm subroutine semilogym(this, xv,ymat, lspec) !.............................................................................. !Plots a matrix against a vector with logarithmic y-axis !For more information see plot2D_matrix_vs_vector procedure !Everything is the same except the x-axis scale !.............................................................................. implicit none class(gpf) :: this ! Input arrays real(wp), intent(in) :: xv(:) real(wp), intent(in) :: ymat(:,:) character(len=*), intent(in), optional :: lspec this%plotscale='semilogy' call plot2d_matrix_vs_vector(this, xv,ymat, lspec) ! Set the plot scale as linear. It means log scale is off this%plotscale='linear' end subroutine semilogym subroutine loglogm(this, xv,ymat, lspec) !.............................................................................. !Plots a matrix against a vector with logarithmic x-axis and y-axis !For more information see plot2D_matrix_vs_vector procedure !Everything is the same except the axes scale !.............................................................................. implicit none class(gpf) :: this ! Input arrays real(wp), intent(in) :: xv(:) real(wp), intent(in) :: ymat(:,:) character(len=*), intent(in), optional :: lspec this%plotscale='loglog' call plot2d_matrix_vs_vector(this, xv,ymat, lspec) ! Set the plot scale as linear. It means log scale is off this%plotscale='linear' end subroutine loglogm !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!> Section Three: Animation Routines !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ subroutine sub_animation_start(this, pause_seconds) !------------------------------------------------------------------------------- ! sub_animation_start: set the setting to start an animation ! it simply set flags and open a script file to write data !------------------------------------------------------------------------------- class(gpf) :: this real, intent(in), optional :: pause_seconds ! ogpf does not support multiplot with animation at the same time if (this%hasmultiplot) then print*, md_name // ': does not support animation in multiplot mode!' stop end if if (present(pause_seconds)) then this%pause_seconds = pause_seconds else this%pause_seconds = 2 ! delay in second end if this%frame_number = 0 ! create the ouput file for writting gnuplot script call create_outputfile(this) this%hasfileopen = .true. this%hasanimation = .true. end subroutine sub_animation_start subroutine sub_animation_show(this) !------------------------------------------------------------------------------- ! sub_animation_show: simply resets the animation flags ! and finalize the plotting. !------------------------------------------------------------------------------- class(gpf) :: this this%frame_number = 0 this%hasanimation = .false. call finalize_plot(this) end subroutine sub_animation_show !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!> Section Four: Gnuplot direct scriptting !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ subroutine addscript(this,strcmd) !.............................................................................. ! addscript: accepts all type of gnuplot command as a string and store it ! in global txtscript to be later sent to gnuplot !.............................................................................. class(gpf) :: this character(len=*), intent(in) :: strcmd if (.not.allocated(this%txtscript)) this%txtscript='' if (len_trim(this%txtscript) == 0 ) then this%txtscript = '' ! initialize string end if if ( len_trim(strcmd)>0 ) then this%txtscript = this%txtscript // splitstr(strcmd) end if end subroutine addscript subroutine runscript(this) !.............................................................................. ! runscript sends the the script string (txtstring) into a script ! file to be run by gnuplot !.............................................................................. class(gpf):: this !REV 0.18: a dedicated subroutine is used to create the output file call create_outputfile(this) !write the script call processcmd(this) write(unit=this%file_unit, fmt='(a)') this%txtscript ! close the file and call gnuplot call finalize_plot(this) end subroutine runscript !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!> Section Five: gnuplot command processing and data writing to script file !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ subroutine process_axes_set(axes_set, axes) !.............................................................................. ! process_axesspec accepts the axes set and interpret it into ! a format to be sent to gnuplot. ! the axes set can be one of the following set ! x1y1, x1y2, x2y1, x2y2 !.............................................................................. character(len=*), intent(in) :: axes_set character(len=4), intent(out) :: axes if (len_trim (adjustl(axes_set)) == 0) then axes='' return end if select case ( lcase(trim (adjustl (axes_set) ) ) ) case ('x1y1') axes='x1y1' case ('x1y2') axes='x1y2' case ('x2y1') axes='x2y1' case ('x2y2') axes='x2y2' case default ! wrong strings print*, md_name // ':process_axes_set:' // ' wrong axes set is sent.'// new_line(' ') & // 'axes set can be on of: x1y1, x1y2, x2y1, x2y2' axes='' return end select end subroutine process_axes_set subroutine process_linespec(order, lsstring, lspec, axes_set) !.............................................................................. ! process_linespec accepts the line specification and interpret it into ! a format to be sent to gnuplot !.............................................................................. integer, intent(in) :: order !1 for the first data series character(len=*), intent(out) :: lsstring character(len=*), intent(in), optional :: lspec character(len=*), intent(in), optional :: axes_set !local variables character(len=4) :: axes character(len=10) :: axes_setting !check the axes set axes_setting = '' if ( present (axes_set)) then call process_axes_set(axes_set, axes) if (len(trim(axes))> 0 ) then axes_setting = ' axes ' // axes end if end if select case(order) case(1) if ( present(lspec) ) then if (hastitle(lspec)) then lsstring='plot "-" '//trim(lspec) // axes_setting else lsstring='plot "-" notitle '//trim(lspec) // axes_setting end if else lsstring='plot "-" notitle' // axes_setting end if case default !e.g. 2, 3, 4, ... if (present(lspec)) then if (hastitle(lspec)) then lsstring=', "-" '// trim(lspec) // axes_setting else lsstring=', "-" notitle '// trim(lspec) // axes_setting end if else lsstring=', "-" notitle' // axes_setting end if end select end subroutine process_linespec subroutine processcmd(this) !.............................................................................. ! This subroutine writes all the data into plot file ! to be read by gnuplot !.............................................................................. class(gpf) :: this ! write the plot style for data ! this is used only when 3D plots (splot, cplot) is used if (allocated(this%txtdatastyle)) then write ( this%file_unit, '("set style data ", a)' ) this%txtdatastyle write ( this%file_unit, '(a)' ) end if ! Write options if ( this%hasoptions ) then write ( this%file_unit, '(" ")' ) write ( this%file_unit, '("# options")' ) write ( this%file_unit, '(a)' ) this%txtoptions write ( this%file_unit, '(a)' ) end if ! Check with plot scale: i.e linear, logx, logy, or log xy write( this%file_unit, '(" ")' ) write( this%file_unit, '("# plot scale")' ) select case (this%plotscale) case ('semilogx') write ( this%file_unit, '("set logscale x")' ) case ('semilogy') write ( this%file_unit, '("set logscale y")' ) case ('loglog') write ( this%file_unit, '("set logscale xy")' ) case default !for no setting !pass end select !!>0.22 ! write annotation write ( this%file_unit, '(" ")' ) write ( this%file_unit, '("# Annotation: title and labels")' ) call write_label(this, 'plot_title') call write_label(this, 'xlabel' ) call write_label(this, 'x2label' ) call write_label(this, 'ylabel' ) call write_label(this, 'y2label' ) call write_label(this, 'zlabel' ) ! axes range write ( this%file_unit, '(" ")') write ( this%file_unit, '("# axes setting")') if (this%hasxrange) then write ( this%file_unit, '("set xrange [",G0,":",G0,"]")' ) this%xrange end if if (this%hasyrange) then write ( this%file_unit, '("set yrange [",G0,":",G0,"]")' ) this%yrange end if if (this%haszrange) then write ( this%file_unit, '("set zrange [",G0,":",G0,"]")' ) this%zrange end if ! secondary axes range if (this%hasx2range) then write ( this%file_unit, '("set x2range [",G0,":",G0,"]")' ) this%x2range end if if (this%hasy2range) then write ( this%file_unit, '("set y2range [",G0,":",G0,"]")' ) this%y2range end if ! finish by new line write ( this%file_unit, '(a)' ) ! emptyline end subroutine processcmd subroutine write_label(this, lblname) !.............................................................................. ! This subroutine writes the labels into plot file ! to be read by gnuplot !.............................................................................. ! write_label class(gpf) :: this character(len=*) :: lblname ! local var character(len=:), allocatable :: lblstring character(len=:), allocatable :: lblset type(tplabel) :: label select case (lblname) case ('xlabel') if (.not. (this%tpxlabel%has_label) ) then return ! there is no label end if lblset = 'set xlabel "' label = this%tpxlabel case ('x2label') if (.not. (this%tpx2label%has_label) ) then return ! there is no label end if lblset = 'set x2label "' label = this%tpx2label case ('ylabel') if (.not. (this%tpylabel%has_label) ) then return ! there is no label end if lblset = 'set ylabel "' label = this%tpylabel case ('y2label') if (.not. (this%tpy2label%has_label) ) then return ! there is no label end if lblset = 'set y2label "' label = this%tpy2label case ('zlabel') if (.not. (this%tpzlabel%has_label) ) then return ! there is no label end if lblset = 'set zlabel "' label = this%tpzlabel case ('plot_title') if (.not. (this%tpplottitle%has_label) ) then return ! there is no label end if lblset = 'set title "' label = this%tpplottitle end select lblstring = '' ! if there is a label continue to set it lblstring = lblstring // lblset // trim(label%lbltext)//'"' if (allocated(label%lblcolor)) then lblstring = lblstring // ' tc "' //trim(label%lblcolor) // '"' end if ! set font and size if (allocated(this%tpxlabel%lblfontname)) then lblstring = lblstring // ' font "'// trim(label%lblfontname) // ',' if (label%lblfontsize /= NOT_INITIALIZED) then lblstring = lblstring // num2str(label%lblfontsize) //'"' else lblstring = lblstring //'"' end if else ! check if only font size has been given if (label%lblfontsize /= NOT_INITIALIZED ) then lblstring = lblstring // ' font ",' // num2str(label%lblfontsize) //'"' end if end if ! set rotation if (label%lblrotate /= NOT_INITIALIZED ) then lblstring = lblstring // ' rotate by ' // num2str(label%lblrotate ) end if ! write to ogpf script file write ( this%file_unit, '(a)' ) lblstring end subroutine write_label function color_palettes(palette_name) result(str) !............................................................................... ! color_palettes create color palette as a ! string to be written into gnuplot script file ! the palettes credit goes to: Anna Schnider (https://github.com/aschn) and ! Hagen Wierstorf (https://github.com/hagenw) !............................................................................... character(len=*), intent(in) :: palette_name character(len=:), allocatable :: str ! local variables character(len=1) :: strnumber character(len=11) :: strblank integer :: j integer :: maxcolors ! define the color palettes character(len=:), allocatable :: pltname character(len=7) :: palette(9) ! palettes with maximum 9 colors maxcolors = 8 ! default number of discrete colors palette='' select case ( lcase(trim(adjustl(palette_name))) ) case ('set1') pltname='set1' palette(1:maxcolors)=[& "#E41A1C", "#377EB8", "#4DAF4A", "#984EA3", & "#FF7F00", "#FFFF33", "#A65628", "#F781BF" ] case ('set2') pltname='set2' palette(1:maxcolors)=[& "#66C2A5", "#FC8D62", "#8DA0CB", "#E78AC3", & "#A6D854", "#FFD92F", "#E5C494", "#B3B3B3" ] case ('set3') pltname='set3' palette(1:maxcolors)=[& "#8DD3C7", "#FFFFB3", "#BEBADA", "#FB8072", & "#80B1D3", "#FDB462", "#B3DE69", "#FCCDE5" ] case ('palette1') pltname='palette1' palette(1:maxcolors)=[& "#FBB4AE", "#B3CDE3", "#CCEBC5", "#DECBE4", & "#FED9A6", "#FFFFCC", "#E5D8BD", "#FDDAEC" ] case ('palette2') pltname='palette2' palette(1:maxcolors)=[& "#B3E2CD", "#FDCDAC", "#CDB5E8", "#F4CAE4", & "#D6F5C9", "#FFF2AE", "#F1E2CC", "#CCCCCC" ] case ('paired') pltname='paired' palette(1:maxcolors)=[& "#A6CEE3", "#1F78B4", "#B2DF8A", "#33A02C", & "#FB9A99", "#E31A1C", "#FDBF6F", "#FF7F00" ] case ('dark2') pltname='dark2' palette(1:maxcolors)=[& "#1B9E77", "#D95F02", "#7570B3", "#E7298A", & "#66A61E", "#E6AB02", "#A6761D", "#666666" ] case ('accent') pltname='accent' palette(1:maxcolors)=[& "#7FC97F", "#BEAED4", "#FDC086", "#FFFF99", & "#386CB0", "#F0027F", "#BF5B17", "#666666" ] case ('jet') ! Matlab jet palette maxcolors = 9 pltname='jet' palette(1:maxcolors)=[& '#000090', '#000fff', '#0090ff', '#0fffee', & '#90ff70', '#ffee00', '#ff7000', '#ee0000', '#7f0000' ] case default print*, md_name // ": color_palettes: wrong palette name" print*, 'gnuplot default palette will be used!' str=' ' ! empty palette is returned! return end select ! generate the gnuplot palette as a single multiline string str = '# Define the ' // pltname // ' pallete' // new_line(' ') str = str // 'set palette defined ( \' // new_line(' ') strblank = ' ' ! pad certain number of paces do j=1, maxcolors - 1 write(unit =strnumber, fmt='(I1)' ) j-1 str = str // strblank // strnumber // ' "' // palette(j) // '",\' // new_line(' ') end do j =maxcolors write(strnumber, fmt='(I1)') j str = str // strblank // strnumber // ' "' // palette(j) // '" )' // new_line(' ') end function color_palettes subroutine write_xydata(file_unit,ndata,x,y) !.............................................................................. ! Writes set of xy data into a file !.............................................................................. integer, intent(in) :: file_unit integer, intent(in) :: ndata real(wp), intent(in) :: x(:) real(wp), intent(in), optional :: y(:) integer:: i ! TODO (Mohammad#1#12/22/17): The format string shall be modified to write the ! number in more suitable form ! Rev 0.18 if (present(y) ) then !both x and y are present, data are xy set do i = 1, ndata write ( file_unit, * ) x(i), y(i) end do else !only x is passed, data are index-x set do i = 1, ndata write ( file_unit, * ) x(i) end do end if write ( file_unit, '(a)' ) 'e' !end of set of data end subroutine write_xydata subroutine create_outputfile(this) !.............................................................................. ! Create an output file, assign a file_unit ! for writing the gnuplot commands !.............................................................................. ! Rev 0.18 class(gpf), intent(inout) :: this if (this%hasfileopen) then ! there is nothing to do, file has been already open! return end if !> Rev 0.2 animation ! animation handling if (this%hasanimation ) then this%frame_number = this%frame_number + 1 ! for future use end if ! Open the output file if (.not. (this%hasfilename)) then ! check if no file has been set by user this%txtfilename=gnuplot_output_filename end if open ( newunit = this%file_unit, file = this%txtfilename, status = 'replace', iostat = this%status ) if (this%status /= 0 ) then print*, "md_helperproc, create_outputfile: cannot open file for output" stop end if ! Set the gnuplot terminal, write ogpf configuration (customized setting) ! Can be overwritten by options ! write signature write ( this%file_unit, '(a)' ) '# ' // md_name write ( this%file_unit, '(a)' ) '# ' // md_rev write ( this%file_unit, '(a)' ) '# ' // md_lic write ( this%file_unit, '(a)' ) ! emptyline ! write the global settings write ( this%file_unit, '(a)' ) '# gnuplot global setting' write(unit=this%file_unit, fmt='(a)') 'set term ' // gnuplot_term_type // & ' size ' // gnuplot_term_size // ' enhanced font "' // & gnuplot_term_font // '"' // & ' title "' // md_name // ': ' // md_rev //'"' ! library name and version ! write the preset configuration for gnuplot (ogpf customized settings) if (this%preset_configuration) then call this%preset_gnuplot_config() end if ! write multiplot setting if (this%hasmultiplot) then write(this%file_unit, fmt='(a, I2, a, I2)') 'set multiplot layout ', & this%multiplot_rows, ',', this%multiplot_cols end if ! set flag true for file is opened this%hasfileopen = .true. end subroutine create_outputfile subroutine preset_gnuplot_config(this) !.............................................................................. ! To write the preset configuration for gnuplot (ogpf customized settings) !.............................................................................. class(gpf) :: this write(this%file_unit, fmt='(a)') write(this%file_unit, fmt='(a)') '# ogpf extra configuration' write(this%file_unit, fmt='(a)') '# -------------------------------------------' ! color definition write(this%file_unit, fmt='(a)') '# color definitions' write(this%file_unit, fmt='(a)') 'set style line 1 lc rgb "#800000" lt 1 lw 2' write(this%file_unit, fmt='(a)') 'set style line 2 lc rgb "#ff0000" lt 1 lw 2' write(this%file_unit, fmt='(a)') 'set style line 3 lc rgb "#ff4500" lt 1 lw 2' write(this%file_unit, fmt='(a)') 'set style line 4 lc rgb "#ffa500" lt 1 lw 2' write(this%file_unit, fmt='(a)') 'set style line 5 lc rgb "#006400" lt 1 lw 2' write(this%file_unit, fmt='(a)') 'set style line 6 lc rgb "#0000ff" lt 1 lw 2' write(this%file_unit, fmt='(a)') 'set style line 7 lc rgb "#9400d3" lt 1 lw 2' write(this%file_unit, fmt='(a)') ! axes setting write(this%file_unit, fmt='(a)') '# Axes' write(this%file_unit, fmt='(a)') 'set border linewidth 1.15' write(this%file_unit, fmt='(a)') 'set tics nomirror' write(this%file_unit, fmt='(a)') write(this%file_unit, fmt='(a)') '# grid' write(this%file_unit, fmt='(a)') '# Add light grid to plot' write(this%file_unit, fmt='(a)') 'set style line 102 lc rgb "#d6d7d9" lt 0 lw 1' write(this%file_unit, fmt='(a)') 'set grid back ls 102' write(this%file_unit, fmt='(a)') ! set the plot style write(this%file_unit, fmt='(a)') '# plot style' write(this%file_unit, fmt='(a)') 'set style data linespoints' write(this%file_unit, fmt='(a)') write(this%file_unit, fmt='(a)') '# -------------------------------------------' write(this%file_unit, fmt='(a)') '' end subroutine preset_gnuplot_config subroutine finalize_plot(this) !.............................................................................. ! To finalize the writing of gnuplot commands/data and close the output file. !.............................................................................. class(gpf) :: this ! check for multiplots if (this%hasmultiplot) then if (this%multiplot_total_plots < this%multiplot_rows * this%multiplot_cols - 1 ) then ! increment the number of plots this%multiplot_total_plots = this%multiplot_total_plots + 1 return ! do not finalize plot, still there is places in multiplot else ! close multiplot write(this%file_unit, fmt='(a)') 'unset multiplot' ! reset multiplot flag this%hasmultiplot = .false. end if end if close ( unit = this%file_unit ) ! close the script file this%hasfileopen = .false. ! reset file open flag this%hasanimation = .false. ! Use shell command to run gnuplot if (get_os_type() == 1) then call execute_command_line ('wgnuplot -persist ' // this%txtfilename) ! Now plot the results else call execute_command_line ('gnuplot -persist ' // this%txtfilename) ! Now plot the results end if contains integer function get_os_type() result(r) !! Returns one of OS_WINDOWS, others !! At first, the environment variable `OS` is checked, which is usually !! found on Windows. !! Copy from fpm/fpm_environment: https://github.com/fortran-lang/fpm/blob/master/src/fpm_environment.f90 character(len=32) :: val integer :: length, rc integer, parameter :: OS_OTHERS = 0 integer, parameter :: OS_WINDOWS = 1 r = OS_OTHERS ! Check environment variable `OS`. call get_environment_variable('OS', val, length, rc) if (rc == 0 .and. length > 0 .and. index(val, 'Windows_NT') > 0) then r = OS_WINDOWS return end if end function end subroutine finalize_plot !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!> Section Six: Utility and helper procedures !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ function hastitle(string) !.............................................................................. ! check to see if the plot title (used as legend = key) !.............................................................................. character(len=*), intent(in) :: string logical:: hastitle integer:: idx1 integer:: idx2 idx1=index( lcase(string),'title') !Check if title is passed idx2=index(' ' // lcase(string),' t ') !Check if the abbreviated title 't' is passed. Extra space is added ! at the beginning of string to find starting 't' if (idx1 /=0 .or. idx2 /=0 ) then hastitle=.true. else hastitle=.false. end if end function hastitle function checkdim(nx,ny) !.............................................................................. ! checkdim checks the equality of dimensions of two vector !.............................................................................. integer, intent(in):: nx integer, intent(in):: ny logical:: checkdim if (nx/=ny) then checkdim=.false. else checkdim=.true. end if end function checkdim !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !> Section Seven: String utility Routines !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pure function splitstr(str) result(spstr) !.............................................................................. !splitstr, separate a string using ";" delimiters !.............................................................................. character(len=*), intent(in) :: str ! local variables character, parameter :: delimiter=';' character(len=:), allocatable :: spstr integer :: n integer :: m integer :: k k=len_trim(str) !length with removed trailing blanks n=scan(str,delimiter) if (n==0) then ! This is a single statement spstr = adjustl(str) // new_line(' ') return end if ! for two or more statements separated by ; spstr = '' m=1 do while (n/=0 .and. m=65 .and. n <= 90) then lcase(i:i)=char(n+32) else lcase(i:i)=chr end if end do end function lcase function num2str_i4(number_in) !.............................................................................. ! num2str_int: converts integer number to string !.............................................................................. integer(kind=kind(1)), intent(in) :: number_in character(len=:), allocatable :: num2str_i4 ! local variable character(len=range(number_in)) :: strnm write(unit=strnm, fmt='(I0)') number_in num2str_i4 = trim(strnm) end function num2str_i4 function num2str_r4(number_in, strfmt) !.............................................................................. ! num2str_r4: converts single precision real number to string ! strfmt is the optional format string !.............................................................................. real(kind=sp), intent(in) :: number_in character(len=*), intent(in), optional :: strfmt character(len=:), allocatable :: num2str_r4 ! local variable character(len=range(number_in)) :: strnm if (present(strfmt)) then write(unit=strnm, fmt= '('//trim(strfmt)//')' ) number_in else write(unit=strnm, fmt='(G0)') number_in end if num2str_r4 = trim(strnm) end function num2str_r4 function num2str_r8(number_in, strfmt) !.............................................................................. ! num2str_real: converts double precision real number to string ! strfmt is the optional format string !.............................................................................. real(kind=dp), intent(in) :: number_in character(len=*), intent(in), optional :: strfmt character(len=:), allocatable :: num2str_r8 ! local variable character(len=range(number_in)) :: strnm if (present(strfmt)) then write(unit=strnm, fmt= '('//trim(strfmt)//')' ) number_in else write(unit=strnm, fmt='(G0)') number_in end if num2str_r8 = trim(strnm) end function num2str_r8 !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!> Section Eight: Math helper function !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ function arange(xa, xb, dx) !.............................................................................. ! returns a vector in the form of [xa, xa+dx, xa+2*dx, ...] ! the number of elements is calculated as m = n+ 1, ! where n= int ( (xa-xb)/dx) ). ! arange is similar to colon in Matlab and arange in Python! ! ! NOTE: ! - If n calculated as zero, result is [xa] ! - If n calculated as Inf (dx=0), a fatal error will be raised ! - If n calculated as negative value (e.g xa 0.0 " stop end if else dxl = 1.0_wp end if if ( (xa < xb) .and. (dx < 0.0_wp) ) then print*, "arange procedure: Fatal Error: wrong dx, use a dx > 0.0 " stop end if n = int( (xb-xa)/ dxl) ! n+1 is the number of elements allocate(arange(n), stat=ierr) if (ierr /= 0) then print*, "arange procedure: Fatal Error, allocation failed in arange function" stop end if arange = [(xa + i*dxl, i=0, n)] end function arange function linspace(a,b,n_elements) !.............................................................................. ! returns a linearly spaced vector with n points in [a, b] ! if n is omitted, 100 points will be considered !.............................................................................. real(wp), intent(in) :: a real(wp), intent(in) :: b integer, intent(in), optional :: n_elements real(wp), allocatable :: linspace(:) ! Local vars real(wp) :: dx integer :: i integer :: n integer :: ierr if (present(n_elements)) then if (n_elements <=1 ) then print*, "linspace procedure: Error: wrong value of n_elements, use an n_elements > 1" stop end if n=n_elements else n=100 end if allocate(linspace(n), stat=ierr) if (ierr /= 0) then print*, "linspace procedure: Fatal Error, Allocation failed in linspace function" stop end if dx=(b-a)/real((n-1),wp) linspace=[(i*dx+a, i=0,n-1)] end function linspace subroutine meshgrid(x,y,xgv,ygv, ierr) !.............................................................................. !meshgrid generate mesh grid over a rectangular domain of [xmin xmax, ymin, ymax] ! Inputs: ! xgv, ygv are grid vectors in form of full grid data ! Outputs: ! X and Y are matrix each of size [ny by nx] contains the grid data. ! The coordinates of point (i,j) is [X(i,j), Y(i,j)] ! ierr: The error flag ! """ ! # Example ! # call meshgrid(X, Y, [0.,1.,2.,3.],[5.,6.,7.,8.]) ! # X ! # [0.0, 1.0, 2.0, 3.0, ! # 0.0, 1.0, 2.0, 3.0, ! # 0.0, 1.0, 2.0, 3.0, ! # 0.0, 1.0, 2.0, 3.0] ! # ! #Y ! #[ 5.0, 5.0, 5.0, 5.0, ! # 6.0, 6.0, 6.0, 6.0, ! # 7.0, 7.0, 7.0, 7.0, ! # 8.0, 8.0, 8.0, 8.0] !.............................................................................. ! Rev 0.2, Feb 2018 ! New feature added: xgv and ygv as full grid vector are accepted now ! Arguments real(wp), intent(out), allocatable :: x(:,:) real(wp), intent(out), allocatable :: y(:,:) real(wp), intent(in) :: xgv(:) ! x grid vector [start, stop, step] or [start, stop] real(wp), intent(in), optional :: ygv(:) ! y grid vector [start, stop, step] or [start, stop] integer, intent(out), optional :: ierr ! the error value ! Local variables integer:: sv integer:: nx integer:: ny logical:: only_xgv_available ! Initial setting only_xgv_available = .false. sv=0 !Assume no error nx=size(xgv, dim=1) if (present(ygv)) then ny = size(ygv, dim=1) else only_xgv_available=.true. ny=nx end if allocate(x(ny,nx),y(ny,nx),stat=sv) if (sv /=0) then print*, "allocataion erro in meshgrid" stop end if x(1,:) = xgv x(2:ny,:) = spread(xgv, dim=1, ncopies=ny-1) if (only_xgv_available) then y=transpose(x) else y(:,1) = ygv y(:,2:nx) = spread(ygv,dim=2,ncopies=nx-1) end if if (present(ierr)) then ierr=sv end if end subroutine meshgrid !End of ogpf end module ogpf