Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/ComputeNormal.F90
5215 views
1
!/*****************************************************************************/
2
! *
3
! * Elmer/Ice, a glaciological add-on to Elmer
4
! * http://elmerice.elmerfem.org
5
! *
6
! *
7
! * This program is free software; you can redistribute it and/or
8
! * modify it under the terms of the GNU General Public License
9
! * as published by the Free Software Foundation; either version 2
10
! * of the License, or (at your option) any later version.
11
! *
12
! * This program is distributed in the hope that it will be useful,
13
! * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
! * GNU General Public License for more details.
16
! *
17
! * You should have received a copy of the GNU General Public License
18
! * along with this program (in file fem/GPL-2); if not, write to the
19
! * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
! * Boston, MA 02110-1301, USA.
21
! *
22
! *****************************************************************************/
23
! ******************************************************************************
24
! *
25
! * Authors: Olivier Gagliardini, Juha Ruokolainen
26
! * Email: Juha.Ruokolainen [at] csc.fi
27
! * Web: http://elmerice.elmerfem.org
28
! * Address: CSC - Scientific Computing Ltd.
29
! * Keilaranta 14
30
! * 02101 Espoo, Finland
31
! *
32
! * Original Date: 14 May 2007
33
! *
34
! *****************************************************************************
35
!> Module containing solver for computation of surface normals
36
SUBROUTINE ComputeNormalSolver( Model, Solver, dt, TransientSimulation )
37
!------------------------------------------------------------------------------
38
!******************************************************************************
39
!
40
! ARGUMENTS:
41
!
42
! TYPE(Model_t) :: Model,
43
! INPUT: All model information (mesh, materials, BCs, etc...)
44
!
45
! TYPE(Solver_t) :: Solver
46
! INPUT: Linear & nonlinear equation solver options
47
!
48
! REAL(KIND=dp) :: dt,
49
! INPUT: Timestep size for time dependent simulations
50
!
51
! LOGICAL :: TransientSimulation
52
! INPUT: Steady state or transient simulation
53
!
54
!Modification have been done to deal with problems where we don't want to compute
55
!the normal on all the boundaries (problem with the corners)
56
!
57
!Keywords are: ComputeAll = True/False computing / or not the normal on every boundary
58
! ComputeNormal = True to compute the normal on a given boundary
59
!******************************************************************************
60
USE DefUtils
61
62
IMPLICIT NONE
63
!------------------------------------------------------------------------------
64
TYPE(Solver_t), TARGET :: Solver
65
TYPE(Model_t) :: Model
66
67
REAL(KIND=dp) :: dt
68
LOGICAL :: TransientSimulation
69
70
!------------------------------------------------------------------------------
71
! Local variables
72
!------------------------------------------------------------------------------
73
TYPE(Mesh_t), POINTER :: Mesh
74
TYPE(Element_t), POINTER :: Element
75
TYPE(Variable_t), POINTER :: NormalSolution
76
TYPE(ValueList_t), POINTER :: BC, SolverParams
77
78
INTEGER :: i, j, k, l, m, n, cnt, ierr, t, DIM
79
REAL(KIND=dp) :: u, v, w, s
80
REAL(KIND=dp), POINTER :: Nvector(:), PassNVector(:), RecvNVector(:)
81
INTEGER, POINTER :: Permutation(:), Neighbours(:)
82
INTEGER, ALLOCATABLE :: NeighbourPerm(:), PassCount(:), RecvCount(:),&
83
PassIndices(:,:), RecvIndices(:,:), LocalPerm(:)
84
INTEGER, DIMENSION(MPI_STATUS_SIZE) :: status
85
TYPE(Nodes_t), SAVE :: Nodes
86
REAL(KIND=dp) :: Bu, Bv, Normal(3), NormalCond(4)
87
88
LOGICAL :: CompAll = .TRUE., CompBC = .TRUE., Found, Parallel, &
89
FirstTime = .TRUE.,UnFoundFatal=.TRUE.
90
LOGICAL, ALLOCATABLE :: Hit(:)
91
92
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName = 'ComputeNormalSolver'
93
94
SAVE :: NeighbourPerm, PassCount, RecvCount, PassIndices, &
95
RecvIndices, LocalPerm, Hit
96
97
Parallel = (ParEnv % PEs > 1)
98
Mesh => Solver % Mesh
99
DIM = CoordinateSystemDimension()
100
101
!---------------------------------------
102
! Setup pointer to the current solution:
103
!---------------------------------------
104
NormalSolution => VariableGet( Solver % Mesh % Variables, 'Normal Vector',UnFoundFatal=UnFoundFatal)
105
Nvector => NormalSolution % Values
106
Permutation => NormalSolution % Perm
107
NVector = 0.0_dp
108
109
CALL INFO(SolverName, 'Computing Normal Vector for Nodes', level=3)
110
111
SolverParams => GetSolverParams()
112
CompAll = GetLogical (SolverParams, 'ComputeAll', Found)
113
114
IF (.NOT.Found) THEN
115
WRITE(Message,'(A)') ('ComputeAll not found, Normal is computed for all the boundaries')
116
CALL INFO(SolverName, Message, level = 20)
117
CompAll = .TRUE.
118
CompBC = .TRUE.
119
ELSE
120
IF (.NOT.CompAll) CompBC = .FALSE.
121
IF (CompAll) CompBC = .TRUE.
122
END IF
123
124
IF((FirstTime .OR. Solver % MeshChanged) .AND. Parallel) THEN
125
126
IF(.NOT. FirstTime) THEN
127
DEALLOCATE(Hit, NeighbourPerm, PassCount, RecvCount, &
128
PassIndices, RecvIndices, LocalPerm)
129
END IF
130
131
ALLOCATE(Hit(Mesh % NumberOfNodes), &
132
NeighbourPerm(ParEnv % PEs),&
133
PassCount(ParEnv % NumOfNeighbours),&
134
RecvCount(ParEnv % NumOfNeighbours),&
135
PassIndices(ParEnv % NumOfNeighbours, Mesh % NumberOfNodes),&
136
RecvIndices(ParEnv % NumOfNeighbours, Mesh % NumberOfNodes),&
137
LocalPerm( MAXVAL(Mesh % ParallelInfo % GlobalDOFs)))
138
139
NeighbourPerm = 0
140
LocalPerm = 0
141
Hit = .FALSE.
142
RecvCount = 0
143
PassCount = 0
144
PassIndices = 0
145
146
!Create a list of partitions with which we share nodes
147
cnt = 0
148
DO i=1,ParEnv % PEs
149
IF(ParEnv % MyPE == i-1) CYCLE
150
IF(.NOT. ParEnv % IsNeighbour(i)) CYCLE
151
cnt = cnt + 1
152
NeighbourPerm(i) = cnt
153
END DO
154
155
!Perm to get back from global to local node numbering
156
DO i=1, Mesh % NumberOfNodes
157
LocalPerm(Mesh % ParallelInfo % GlobalDOFs(i)) = i
158
END DO
159
160
END IF !FirstTime
161
162
DO t = 1, Solver % Mesh % NumberOfBoundaryElements
163
Element => GetBoundaryElement(t)
164
165
!IF(Element % PartIndex /= ParEnv % MyPE) CYCLE
166
167
n = GetElementNOFNodes(Element)
168
BC => GetBC(Element)
169
IF (n == 1) CYCLE
170
171
CALL GetElementNodes( Nodes, Element )
172
173
CompBC = CompAll
174
IF (.NOT.CompAll) THEN
175
CompBC = GetLogical ( BC,'ComputeNormal',Found)
176
NormalCond = 0.0_dp
177
IF (.NOT.Found) THEN
178
NormalCond(1:n) = GetReal( BC, 'ComputeNormal Condition', Found )
179
180
! If at least one value in NormalCond > 0, then CompBC=.true.
181
IF (COUNT(NormalCond > 0.0) > 0) CompBC = .TRUE.
182
END IF
183
END IF
184
185
IF (CompBC) THEN
186
DO i = 1,n
187
IF (NormalCond(i) < 0) CYCLE
188
j = Element % NodeIndexes( i )
189
k = Permutation(j)
190
191
Bu = Element % Type % NodeU(i)
192
IF ( Element % Type % Dimension > 1 ) THEN
193
Bv = Element % Type % NodeV(i)
194
ELSE
195
Bv = 0.0D0
196
END IF
197
Normal = NormalVector(Element, Nodes, Bu, Bv, .TRUE.)
198
Nvector(DIM*(k-1)+1:DIM*k) = Nvector(DIM*(k-1)+1:DIM*k) +&
199
Normal(1:DIM)
200
201
IF(Parallel) Hit(j) = .TRUE.
202
END DO
203
END IF
204
END DO
205
206
IF(Parallel) THEN
207
208
IF(FirstTime .OR. Solver % MeshChanged) THEN
209
210
!Find nodes on partition boundaries
211
FirstTime = .FALSE.
212
RecvCount = 0
213
PassCount = 0
214
PassIndices = 0
215
DO i=1,Model % Mesh % NumberOfNodes
216
IF(.NOT.Hit(i)) CYCLE !no normal computation
217
IF(.NOT. Mesh % ParallelInfo % GInterface(i)) CYCLE !no partition interface
218
Neighbours => Mesh % ParallelInfo % NeighbourList(i) % Neighbours
219
220
DO j=1,SIZE(Neighbours)
221
IF(Neighbours(j) == ParEnv % MyPE) CYCLE
222
223
m = NeighbourPerm(Neighbours(j)+1)
224
PassCount(m) = PassCount(m) + 1
225
PassIndices(m, PassCount(m)) = i
226
END DO
227
END DO
228
END IF
229
230
!Send
231
DO i=1,ParEnv % PEs
232
IF(NeighbourPerm(i) == 0) CYCLE
233
m = NeighbourPerm(i)
234
235
!Send count
236
CALL MPI_BSEND(PassCount(m), 1, MPI_INTEGER, i-1, 200, ELMER_COMM_WORLD, ierr)
237
!Send (global) node numbers
238
CALL MPI_BSEND(Mesh % ParallelInfo % GlobalDOFs(PassIndices(m,1:PassCount(m))),&
239
PassCount(m), MPI_INTEGER, i-1, 201, ELMER_COMM_WORLD, ierr)
240
241
!Construct normal vector array to pass
242
ALLOCATE(PassNVector(PassCount(m) * DIM))
243
DO j=1, PassCount(m)
244
l = Permutation(PassIndices(m,j))
245
PassNVector(DIM*(j-1)+1:DIM*j) = NVector(DIM*(l-1)+1:DIM*l)
246
END DO
247
248
!Send normal vectors
249
CALL MPI_BSEND(PassNVector, PassCount(m)*DIM, MPI_DOUBLE_PRECISION, &
250
i-1, 202, ELMER_COMM_WORLD, ierr)
251
252
DEALLOCATE(PassNVector)
253
END DO
254
255
!Receive
256
DO i=1,ParEnv % PEs
257
258
IF(NeighbourPerm(i) == 0) CYCLE
259
m = NeighbourPerm(i)
260
261
!Receive count
262
CALL MPI_RECV(RecvCount(m), 1, MPI_INTEGER, i-1, 200, ELMER_COMM_WORLD, status, ierr)
263
264
!Receive (global) node numbers
265
CALL MPI_RECV(RecvIndices(m,1:RecvCount(m)), RecvCount(m), MPI_INTEGER, &
266
i-1, 201, ELMER_COMM_WORLD, status, ierr)
267
268
!Receive normal vectors
269
ALLOCATE(RecvNVector(RecvCount(m)*DIM))
270
CALL MPI_RECV(RecvNVector, RecvCount(m)*DIM, MPI_DOUBLE_PRECISION, &
271
i-1, 202, ELMER_COMM_WORLD, status, ierr)
272
273
DO j=1, RecvCount(m)
274
IF(.NOT. Hit(LocalPerm(RecvIndices(m,j)))) CYCLE !passed a halo node
275
k = Permutation(LocalPerm(RecvIndices(m,j)))
276
NVector(DIM*(k-1)+1:DIM*k) = NVector(DIM*(k-1)+1:DIM*k) + RecvNVector(DIM*(j-1)+1:DIM*j)
277
END DO
278
279
DEALLOCATE(RecvNVector)
280
END DO
281
282
END IF !Parallel
283
284
DO i=1,Model % NumberOfNodes
285
k = Permutation(i)
286
IF ( k > 0 ) THEN
287
s = SQRT( SUM( Nvector(DIM*(k-1)+1:DIM*k)**2 ) )
288
289
IF ( s /= 0.0D0 ) THEN
290
Nvector(DIM*(k-1)+1:DIM*k) = Nvector(DIM*(k-1)+1:DIM*k)/s
291
END IF
292
END IF
293
294
END DO
295
296
CALL INFO(SolverName, 'End', level=3)
297
298
!------------------------------------------------------------------------------
299
END SUBROUTINE ComputeNormalSolver
300
!------------------------------------------------------------------------------
301
302