File: t20.f90

package info (click to toggle)
gmsh 4.13.1%2Bds1-6
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 96,160 kB
  • sloc: cpp: 434,242; ansic: 114,885; f90: 15,323; python: 13,442; yacc: 7,299; java: 3,491; lisp: 3,191; lex: 630; perl: 571; makefile: 497; sh: 439; xml: 414; javascript: 113; pascal: 35; modula3: 32
file content (137 lines) | stat: -rw-r--r-- 4,889 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
! ------------------------------------------------------------------------------
!
!  Gmsh Fortran tutorial 20
!
!  STEP import and manipulation, geometry partitioning
!
! ------------------------------------------------------------------------------

! The OpenCASCADE CAD kernel allows to import STEP files and to modify them. In
! this tutorial we will load a STEP geometry and partition it into slices.

program t20

use, intrinsic :: iso_c_binding
use gmsh

implicit none

type(gmsh_t) :: gmsh
integer(c_int) :: i, n
integer(c_int), allocatable :: rm(:), tags(:,:), s(:,:), dels(:,:), v(:,:), tmp(:,:), tmp_map(:,:)
integer(c_size_t), allocatable :: tmp_map_n(:)
real(c_double) :: h, tx, ty, tz, eps
real(c_double) :: xmin, ymin, zmin, xmax, ymax, zmax, dx, dy, dz, L, xx, yy, zz
character(len=GMSH_API_MAX_STR_LEN) :: cmd, dir
logical :: surf

call gmsh%initialize()

call gmsh%model%add("t20")

! Load a STEP file (using `importShapes' instead of `merge' allows to directly
! retrieve the tags of the highest dimensional imported entities):
call gmsh%model%occ%importShapes('../t20_data.step', v)

! If we had specified
!
! call gmsh%option%setString('Geometry.OCCTargetUnit', 'M')
!
! before merging the STEP file, OpenCASCADE would have converted the units to
! meters (instead of the default, which is millimeters).

! Get the bounding box of the volume:
call gmsh%model%occ%getBoundingBox(v(1,1), v(2,1), xmin, ymin, zmin, xmax, ymax, zmax)

! We want to slice the model into N slices, and either keep the volume slices
! or just the surfaces obtained by the cutting:

N = 5  ! Number of slices
dir = 'X' ! Direction: 'X', 'Y' or 'Z'
surf = .false.  ! Keep only surfaces?

dx = (xmax - xmin)
dy = (ymax - ymin)
dz = (zmax - zmin)
L = dz; if (trim(dir) /= 'X') L = dx
H = dz; if (trim(dir) /= 'X') L = dy

! Create the first cutting plane:
s = reshape([2, gmsh%model%occ%addRectangle(xmin, ymin, zmin, L, H)], [2, 1])

if (trim(dir) == 'X') then
    call gmsh%model%occ%rotate(s, xmin, ymin, zmin, 0d0, 1d0, 0d0, -M_PI/2)
else if (trim(dir) == 'Y') then
    call gmsh%model%occ%rotate(s, xmin, ymin, zmin, 1d0, 0d0, 0d0, M_PI/2)
end if
tx = dx / N; if (dir /= 'X') tx = 0
ty = dy / N; if (dir /= 'Y') ty = 0
tz = dz / N; if (dir /= 'Z') tz = 0
call gmsh%model%occ%translate(s, tx, ty, tz)

! Create the other cutting planes:
do i = 1, N-2
    call gmsh%model%occ%copy(reshape(s(:, 1), [2, 1]), tags)
    s = reshape([s, tags], [2, size(s, 2) + size(tags, 2)])
    call gmsh%model%occ%translate(reshape(s(:,size(s,2)), [2,1]), i * tx, i * ty, i * tz)
    deallocate(tags)
end do

! Fragment (i.e. intersect) the volume with all the cutting planes:
call gmsh%model%occ%fragment(v, s, tmp, tmp_map, tmp_map_n)
deallocate(tmp, tmp_map, tmp_map_n)

! Now remove all the surfaces (and their bounding entities) that are not on the
! boundary of a volume, i.e. the parts of the cutting planes that "stick out" of
! the volume:
call gmsh%model%occ%getEntities(tags, 2)
call gmsh%model%occ%remove(tags, .true.); deallocate(tags)

call gmsh%model%occ%synchronize()

if (surf) then
    ! If we want to only keep the surfaces, retrieve the surfaces in bounding
    ! boxes around the cutting planes...
    eps = 1e-4
    if (allocated(s)) deallocate(s)
    s = reshape([integer(c_int) ::], [2,0])
    do i = 1, N-1
        xx = xmin; if (dir /= 'X') xx = xmax
        yy = ymin; if (dir /= 'Y') yy = ymax
        zz = zmin; if (dir /= 'Z') zz = zmax
        call gmsh%model%getEntitiesInBoundingBox( &
            xmin - eps + i * tx, ymin - eps + i * ty, zmin - eps + i * tz, &
            xx + eps + i * tx, yy + eps + i * ty, zz + eps + i * tz, tags, 2)
        s = reshape([s, tags], [2, size(s,2) + size(tags,2)])
    end do
    ! ...and remove all the other entities (here directly in the model, as we
    ! won't modify any OpenCASCADE entities later on):
    call gmsh%model%getEntities(dels, 2)
    ! This removal is not entirely accurate, it misses the 1-6 tuple values
    ! but it works good enough for this example:
    rm = pack(dels, dels /= s)
    dels = reshape(rm, [2, size(rm)/2])

    if (allocated(tmp)) deallocate(tmp)
    call gmsh%model%getEntities(tmp, 3)
    call gmsh%model%removeEntities(tmp); deallocate(tmp)
    call gmsh%model%removeEntities(dels); deallocate(dels)
    call gmsh%model%getEntities(tmp, 1)
    call gmsh%model%removeEntities(tmp); deallocate(tmp)
    call gmsh%model%getEntities(tmp, 0)
    call gmsh%model%removeEntities(tmp); deallocate(tmp)
end if

! Finally, let's specify a global mesh size and mesh the partitioned model:
call gmsh%option%setNumber("Mesh.MeshSizeMin", 3d0)
call gmsh%option%setNumber("Mesh.MeshSizeMax", 3d0)
call gmsh%model%mesh%generate(3)
call gmsh%write("t20.msh")

! Launch the GUI to see the results:
call get_command(cmd)
if (index(cmd, "-nopopup") == 0) call gmsh%fltk%run()

call gmsh%finalize()

end program t20