Well the point in polygon approach should work regardless of the type of quadrilateral.
I pulled a few bits and pieces from a few programs to create VTK output which can be visualized in Paraview. Consider this only as an untested prototype which should be adapted further to your needs. I was using the XY-coordinates, but to maintain notation cleanliness probably X and Z should be used. Also I wasnât sure what reference frame you have for spatial coordinates.
module precision
implicit none
public
!> Working-precision real kind
integer, parameter :: wp = kind(1.0e0)
end module
module vtk_format
use precision, only: wp
implicit none
public :: FMT_REAL, FMT_VECTOR
!> Format string for single precision real numbers
character(*), parameter :: FMT_SP = '(ES15.8E2)'
!> Format string for double precision real numbers
character(*), parameter :: FMT_DP = '(ES24.16E3)'
!> Format string for working-precision real kind
character(*), parameter :: FMT_REAL = &
trim(merge(FMT_SP//' ', FMT_DP, wp == kind(1.0e0)))
!> Format string for a vector triplet
character(*), parameter :: FMT_VECTOR = '(3'//FMT_REAL//')'
end module
module grid
use precision, only: wp
use vtk_format, only: FMT_REAL, FMT_VECTOR
implicit none
private
public :: output_vtk_structuredPoints
contains
subroutine output_vtk_structuredPoints(filename,nx,ny,hx,hy,rho,description)
character(len=*), intent(in) :: filename
!> Output file name
integer, intent(in) :: nx, ny
!> Mesh dimensions, number of cells in each direction
!> the number of grid points is nx + 1, ny + 1
real(wp), intent(in) :: hx, hy
!> Grid spacing, must be larger than 0
real(wp), intent(in) :: rho(:,:)
!> A scalar field defined at the grid points
character(len=*), intent(in), optional :: description
!> Optionally, single-line description of the data
integer :: unit, i, j
open(newunit=unit,file=filename)
write(unit, '(A)') "# vtk DataFile Version 3.0"
if (present(description)) then
write(unit, '(A)') description
else
write(unit, '(A)') "scalar_field"
end if
write(unit, '(A)') "ASCII"
write(unit, '(A)') "DATASET STRUCTURED_POINTS"
write(unit, '(A,3(I0,:,1X))') "DIMENSIONS ", nx + 1, ny + 1, 1
write(unit, '(A,'// FMT_VECTOR //')') "ORIGIN ", 0.0_wp, 0.0_wp, 0.0_wp
write(unit, '(A,'// FMT_VECTOR //')') "SPACING ", &
hx, hy, min(hx, hy)
!
! Dataset attributes
!
write(unit, *)
write(unit, '(A,I0)') "POINT_DATA ", (nx + 1)*(ny + 1)*1
write(unit, '(A)') "SCALARS rho float 1"
write(unit, '(A)') "LOOKUP_TABLE default"
do j = 1, ny + 1
do i = 1, nx + 1
write(unit, FMT_REAL) rho(i,j)
end do
end do
close(unit)
end subroutine output_vtk_structuredPoints
end module
module polygons
use precision, only: wp
use vtk_format, only: FMT_REAL, FMT_VECTOR
implicit none
private
public :: point, polygon, polygon_to_vtk
type :: point
real(wp) :: x, y
end type
type :: polygon
integer :: nvert
real(wp), allocatable :: x(:), y(:)
end type
interface polygon
module procedure :: new_polygon
end interface
contains
function new_polygon(points) result(res)
type(point) :: points(:)
type(polygon) :: res
integer :: i
res%nvert = size(points)
associate(n => res%nvert)
allocate(res%x(n),res%y(n))
do i = 1, n
res%x(i) = points(i)%x
res%y(i) = points(i)%y
end do
end associate
end function
subroutine polygon_to_vtk(filename,poly)
character(len=*), intent(in) :: filename
type(polygon), intent(in) :: poly
integer, parameter :: VTK_POLYGON = 7
integer :: unit, i
open(newunit=unit,file=filename)
write(unit, '(A)') "# vtk DataFile Version 3.0"
write(unit, '(A)') ""
write(unit, '(A)') "ASCII"
write(unit, '(A)') "DATASET UNSTRUCTURED_GRID"
write(unit, '(A, I0, A)') "POINTS ", poly%nvert, " float"
do i = 1, poly%nvert
write(unit, '('// FMT_VECTOR //')') poly%x(i), poly%y(i), 0.0_wp
end do
write(unit, '(A, 2(I0,:,2X))') "CELLS ", 1, 1+poly%nvert
write(unit, '(*(I0,:,1X))') poly%nvert, (i-1, i = 1, poly%nvert)
write(unit, '(A, I0)') "CELL_TYPES ", 1
write(unit, '(I0)') VTK_POLYGON
end subroutine
end module
program test
use precision, only: wp
use grid, only: output_vtk_structuredPoints
use polygons
implicit none
integer, parameter :: nx = 101, nz = 51
real(wp) :: hx, hz
real(wp), allocatable :: rho(:,:)
type(polygon) :: obstacle
hx = 1.0_wp
hz = 1.0_wp
allocate(rho(nx,nz))
rho = 1.0_wp
call output_vtk_structuredPoints("test.vtk",nx-1,nz-1,hx,hz,rho,"rho")
obstacle = polygon([point(40._wp, 10._wp), &
point(60._wp, 10._wp), &
point(70._wp, 30._wp), &
point(50._wp, 30._wp)])
call to_vtk("obstacle.vtk",obstacle)
end program