|
| 1 | +!!----------------------------------------------------------------------------* |
| 2 | +!! *** Program MESH_GENERATOR *** * |
| 3 | +!! * |
| 4 | +!! This module generates a basic square 2D traingular mesh. The * |
| 5 | +!! geometry of this mesh is kept simple by placing nodes in a * |
| 6 | +!! regular pattern, as demonstrated below (note the arrangment * |
| 7 | +!! of the node and element IDs). * |
| 8 | +!! * |
| 9 | +!! 21._____22._____23._____24._____25. * |
| 10 | +!! | / | / | / | / | * |
| 11 | +!! | 29/ 25| 30/ 26| 31/ 27| 32/ 28| * |
| 12 | +!! | / | / | / | / | * |
| 13 | +!! 16._____17._____18._____19._____20. * |
| 14 | +!! | / | / | / | / | * |
| 15 | +!! | 21/ 17| 22/ 18| 23/ 19| 24/ 20| * |
| 16 | +!! | / | / | / | / | * |
| 17 | +!! 11._____12._____13._____14._____15. * |
| 18 | +!! | / | / | / | / | * |
| 19 | +!! | 13/ 9| 14/ 10| 15/ 11| 16/ 12| * |
| 20 | +!! | / | / | / | / | * |
| 21 | +!! 6.______7.______8.______9._____10. * |
| 22 | +!! | / | / | / | / | * |
| 23 | +!! | 5/ 1| 6/ 2| 7/ 3| 8/ 4| * |
| 24 | +!! | / | / | / | / | * |
| 25 | +!! 1.______2.______3.______4.______5. * |
| 26 | +!! * |
| 27 | +!! The size of the output square and its elements is determined * |
| 28 | +!! by two inputs, box_size (the length of each side of the * |
| 29 | +!! square) and edge_size (the length of a single elements * |
| 30 | +!! boundary edge). Therefore, the above mesh would be generated * |
| 31 | +!! by inputs that satisfy - box_size / edge_size = 4. * |
| 32 | +!! * |
| 33 | +!!----------------------------------------------------------------------------* |
| 34 | +module mesh_generator |
| 35 | + use, intrinsic :: iso_fortran_env |
| 36 | + implicit none |
| 37 | + |
| 38 | +contains |
| 39 | + |
| 40 | + subroutine calculate_mesh_parameters(box_size, edge_size, num_edges_per_boundary, num_nodes, num_boundary_nodes, num_elements) |
| 41 | + implicit none |
| 42 | + integer(kind=int64), intent(in) :: box_size |
| 43 | + real(kind=real64), intent(in) :: edge_size |
| 44 | + integer(kind=int64), intent(out) :: num_edges_per_boundary, num_nodes, num_boundary_nodes, num_elements |
| 45 | + |
| 46 | + num_edges_per_boundary = floor(box_size / edge_size) |
| 47 | + num_nodes = (num_edges_per_boundary + 1)**2 |
| 48 | + num_boundary_nodes = (num_edges_per_boundary) * 4 |
| 49 | + num_elements = 2 * (num_edges_per_boundary)**2 |
| 50 | + |
| 51 | + ! write(*,*) "** Mesh Parameters **" |
| 52 | + ! write(*,*) " num_edges_per_boundary:", num_edges_per_boundary |
| 53 | + ! write(*,*) " num_nodes:", num_nodes |
| 54 | + ! write(*,*) " num_boundary_nodes:", num_boundary_nodes |
| 55 | + ! write(*,*) " num_elements:", num_elements |
| 56 | + end subroutine calculate_mesh_parameters |
| 57 | + |
| 58 | + subroutine calculate_mesh(num_edges_per_boundary, num_nodes, num_elements, num_boundary_nodes, nodes, elements, boundary_edges) |
| 59 | + implicit none |
| 60 | + integer(kind=int64), intent(in) :: num_edges_per_boundary, num_nodes, num_boundary_nodes, num_elements |
| 61 | + integer(kind=int64), dimension(3, num_elements), intent(inout) :: elements |
| 62 | + integer(kind=int64), dimension(3, num_boundary_nodes), intent(inout) :: boundary_edges |
| 63 | + real(kind=real64), dimension(2, num_nodes), intent(inout) :: nodes |
| 64 | + |
| 65 | + integer :: num_nodes_per_boundary, bottom_left_node, counter, i, j |
| 66 | + |
| 67 | + num_nodes_per_boundary = num_edges_per_boundary + 1 |
| 68 | + |
| 69 | + counter = 1 |
| 70 | + do i = 1, num_nodes_per_boundary |
| 71 | + do j = 1, num_nodes_per_boundary |
| 72 | + nodes(1, counter) = i |
| 73 | + nodes(2, counter) = j |
| 74 | + counter = counter + 1 |
| 75 | + end do |
| 76 | + end do |
| 77 | + |
| 78 | + counter = 1 |
| 79 | + do i = 1, num_edges_per_boundary |
| 80 | + do j = 1, num_edges_per_boundary |
| 81 | + bottom_left_node = j + (i - 1) * num_nodes_per_boundary |
| 82 | + |
| 83 | + elements(1, counter) = bottom_left_node |
| 84 | + elements(2, counter) = bottom_left_node + 1 |
| 85 | + elements(3, counter) = bottom_left_node + 1 + num_nodes_per_boundary |
| 86 | + |
| 87 | + elements(1, counter + num_edges_per_boundary) = bottom_left_node |
| 88 | + elements(2, counter + num_edges_per_boundary) = bottom_left_node + num_nodes_per_boundary + 1 |
| 89 | + elements(3, counter + num_edges_per_boundary) = bottom_left_node + num_nodes_per_boundary |
| 90 | + |
| 91 | + counter = counter + 1 |
| 92 | + end do |
| 93 | + counter = counter + num_edges_per_boundary |
| 94 | + end do |
| 95 | + |
| 96 | + ! If we are along the bottom boundary |
| 97 | + do i = 1, num_edges_per_boundary |
| 98 | + ! bottom boundary |
| 99 | + boundary_edges(1, i) = i ! left node |
| 100 | + boundary_edges(2, i) = i + 1 ! right node |
| 101 | + boundary_edges(3, i) = i*2 - 1 ! element |
| 102 | + |
| 103 | + ! right boundary |
| 104 | + boundary_edges(1, i + num_edges_per_boundary) = i * num_nodes_per_boundary |
| 105 | + boundary_edges(2, i + num_edges_per_boundary) = (i + 1) * num_nodes_per_boundary |
| 106 | + boundary_edges(3, i + num_edges_per_boundary) = (2*i - 1) * num_edges_per_boundary |
| 107 | + |
| 108 | + ! top boundary |
| 109 | + boundary_edges(1, i + num_edges_per_boundary * 2) = num_nodes - i + 1 |
| 110 | + boundary_edges(2, i + num_edges_per_boundary * 2) = num_nodes - i |
| 111 | + boundary_edges(2, i + num_edges_per_boundary * 2) = num_elements - i + 1 |
| 112 | + |
| 113 | + ! left boundary |
| 114 | + boundary_edges(1, i + num_edges_per_boundary * 3) = (num_nodes_per_boundary - i) * num_nodes_per_boundary + 1 |
| 115 | + boundary_edges(2, i + num_edges_per_boundary * 3) = (num_nodes_per_boundary - 1 - i) * num_nodes_per_boundary + 1 |
| 116 | + boundary_edges(3, i + num_edges_per_boundary * 3) = num_elements - (num_edges_per_boundary - 1) - (2 * (i - 1) * num_edges_per_boundary) |
| 117 | + end do |
| 118 | + |
| 119 | + end subroutine calculate_mesh |
| 120 | + |
| 121 | + subroutine write_mesh_to_file(num_nodes, num_elements, num_boundary_nodes, nodes, elements, boundary_edges) |
| 122 | + implicit none |
| 123 | + integer(kind=int64), intent(in) :: num_nodes, num_elements, num_boundary_nodes |
| 124 | + integer(kind=int64), dimension(3, num_elements), intent(inout) :: elements |
| 125 | + integer(kind=int64), dimension(3, num_boundary_nodes), intent(inout) :: boundary_edges |
| 126 | + real(kind=real64), dimension(2, num_nodes), intent(inout) :: nodes |
| 127 | + |
| 128 | + character*11 :: file_name |
| 129 | + integer :: file_io |
| 130 | + integer :: iostat |
| 131 | + integer :: i, num_sets, num_dirichlet_boundary_conditions, num_neumann_boundary_conditions |
| 132 | + |
| 133 | + ! Baked in defaults |
| 134 | + num_sets = 1 |
| 135 | + num_dirichlet_boundary_conditions = 1 |
| 136 | + num_neumann_boundary_conditions = 0 |
| 137 | + |
| 138 | + file_name = "square_mesh" |
| 139 | + file_io = 100 |
| 140 | + |
| 141 | + ! Write outpout |
| 142 | + open (unit=file_io, & |
| 143 | + file=file_name, & |
| 144 | + status="replace", & |
| 145 | + IOSTAT=iostat) |
| 146 | + |
| 147 | + if( iostat .ne. 0) then |
| 148 | + write(*,'(a)') ' *** Error when opening '//trim(file_name) |
| 149 | + else |
| 150 | + write(*,'(/,a)') ' *** '//trim(file_name)//' opened' |
| 151 | + end if |
| 152 | + |
| 153 | + write(file_io,*) "! num_nodes, num_elements, num_boundary_points, num_sets, num_dirichlet_boundary_conditions, num_neumann_boundary_conditions" |
| 154 | + write(file_io,*) num_nodes, num_elements, num_boundary_nodes, num_sets, num_dirichlet_boundary_conditions, num_neumann_boundary_conditions |
| 155 | + |
| 156 | + write(file_io,*) "! jb,vb(1,jb),vb(2,jb),vb(3,jb) - as many lines as num_sets" |
| 157 | + write(file_io,*) 1, 1, 1, 1 |
| 158 | + |
| 159 | + write(file_io,*) "! jb,vb1(jb) - as many lines as num_dirichlet_boundary_conditions" |
| 160 | + write(file_io,*) 1, 0 |
| 161 | + |
| 162 | + write(file_io,*) "! jb,vb2(jb) - as many lines as num_neumann_boundary_conditions" |
| 163 | + |
| 164 | + write(file_io,*) "! jp,coordinates(1,jp),coordinates(2,jp) - as many lines as num_nodes" |
| 165 | + do i = 1, num_nodes |
| 166 | + write(file_io,*) i, nodes(1, i), nodes(2, i) |
| 167 | + end do |
| 168 | + |
| 169 | + write(file_io,*) "! je,element_to_node(1,je),element_to_node(2,je),element_to_node(3,je),vb_index(je) - as many lines as num_elements" |
| 170 | + do i = 1, num_elements |
| 171 | + write(file_io,*) i, elements(1, i), elements(2, i), elements(3, i), 1 |
| 172 | + end do |
| 173 | + |
| 174 | + write(file_io,*) "! boundary_node_num(1,ib),boundary_node_num(2,ib) - as many lines as num_boundary_points" |
| 175 | + do i = 1, num_boundary_nodes |
| 176 | + write(file_io,*) i, 1 |
| 177 | + end do |
| 178 | + |
| 179 | + write(file_io,*) "! num_side_nodes(1,ib),num_side_nodes(2,ib),num_side_nodes(3,ib),num_side_nodes(4,ib) - as many lines as num_boundary_points" |
| 180 | + do i = 1, num_boundary_nodes |
| 181 | + write(file_io,*) boundary_edges(1, i), boundary_edges(2, i), boundary_edges(3, i), 0 |
| 182 | + end do |
| 183 | + end subroutine write_mesh_to_file |
| 184 | + |
| 185 | +end module mesh_generator |
0 commit comments