Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/ComputeNormal.F90
3204 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
IF (.NOT.CompAll) THEN
174
CompBC = GetLogical ( BC,'ComputeNormal',Found)
175
IF (.NOT.Found) THEN
176
NormalCond = 0.0
177
NormalCond(1:n) = GetReal( BC, 'ComputeNormal Condition', Found )
178
179
! If at least one value in NormalCond > 0, then CompBC=.true.
180
IF (COUNT(NormalCond > 0.0) > 0) CompBC = .TRUE.
181
END IF
182
END IF
183
184
IF (CompBC) THEN
185
DO i = 1,n
186
IF (NormalCond(i) .LT. 0) CYCLE
187
j = Element % NodeIndexes( i )
188
k = Permutation(j)
189
190
Bu = Element % Type % NodeU(i)
191
IF ( Element % Type % Dimension > 1 ) THEN
192
Bv = Element % Type % NodeV(i)
193
ELSE
194
Bv = 0.0D0
195
END IF
196
Normal = NormalVector(Element, Nodes, Bu, Bv, .TRUE.)
197
Nvector(DIM*(k-1)+1:DIM*k) = Nvector(DIM*(k-1)+1:DIM*k) +&
198
Normal(1:DIM)
199
200
IF(Parallel) Hit(j) = .TRUE.
201
END DO
202
END IF
203
END DO
204
205
IF(Parallel) THEN
206
207
IF(FirstTime .OR. Solver % MeshChanged) THEN
208
209
!Find nodes on partition boundaries
210
FirstTime = .FALSE.
211
RecvCount = 0
212
PassCount = 0
213
PassIndices = 0
214
DO i=1,Model % Mesh % NumberOfNodes
215
IF(.NOT.Hit(i)) CYCLE !no normal computation
216
IF(.NOT. Mesh % ParallelInfo % GInterface(i)) CYCLE !no partition interface
217
Neighbours => Mesh % ParallelInfo % NeighbourList(i) % Neighbours
218
219
DO j=1,SIZE(Neighbours)
220
IF(Neighbours(j) == ParEnv % MyPE) CYCLE
221
222
m = NeighbourPerm(Neighbours(j)+1)
223
PassCount(m) = PassCount(m) + 1
224
PassIndices(m, PassCount(m)) = i
225
END DO
226
END DO
227
END IF
228
229
!Send
230
DO i=1,ParEnv % PEs
231
IF(NeighbourPerm(i) == 0) CYCLE
232
m = NeighbourPerm(i)
233
234
!Send count
235
CALL MPI_BSEND(PassCount(m), 1, MPI_INTEGER, i-1, 200, ELMER_COMM_WORLD, ierr)
236
!Send (global) node numbers
237
CALL MPI_BSEND(Mesh % ParallelInfo % GlobalDOFs(PassIndices(m,1:PassCount(m))),&
238
PassCount(m), MPI_INTEGER, i-1, 201, ELMER_COMM_WORLD, ierr)
239
240
!Construct normal vector array to pass
241
ALLOCATE(PassNVector(PassCount(m) * DIM))
242
DO j=1, PassCount(m)
243
l = Permutation(PassIndices(m,j))
244
PassNVector(DIM*(j-1)+1:DIM*j) = NVector(DIM*(l-1)+1:DIM*l)
245
END DO
246
247
!Send normal vectors
248
CALL MPI_BSEND(PassNVector, PassCount(m)*DIM, MPI_DOUBLE_PRECISION, &
249
i-1, 202, ELMER_COMM_WORLD, ierr)
250
251
DEALLOCATE(PassNVector)
252
END DO
253
254
!Receive
255
DO i=1,ParEnv % PEs
256
257
IF(NeighbourPerm(i) == 0) CYCLE
258
m = NeighbourPerm(i)
259
260
!Receive count
261
CALL MPI_RECV(RecvCount(m), 1, MPI_INTEGER, i-1, 200, ELMER_COMM_WORLD, status, ierr)
262
263
!Receive (global) node numbers
264
CALL MPI_RECV(RecvIndices(m,1:RecvCount(m)), RecvCount(m), MPI_INTEGER, &
265
i-1, 201, ELMER_COMM_WORLD, status, ierr)
266
267
!Receive normal vectors
268
ALLOCATE(RecvNVector(RecvCount(m)*DIM))
269
CALL MPI_RECV(RecvNVector, RecvCount(m)*DIM, MPI_DOUBLE_PRECISION, &
270
i-1, 202, ELMER_COMM_WORLD, status, ierr)
271
272
DO j=1, RecvCount(m)
273
IF(.NOT. Hit(LocalPerm(RecvIndices(m,j)))) CYCLE !passed a halo node
274
k = Permutation(LocalPerm(RecvIndices(m,j)))
275
NVector(DIM*(k-1)+1:DIM*k) = NVector(DIM*(k-1)+1:DIM*k) + RecvNVector(DIM*(j-1)+1:DIM*j)
276
END DO
277
278
DEALLOCATE(RecvNVector)
279
END DO
280
281
END IF !Parallel
282
283
DO i=1,Model % NumberOfNodes
284
k = Permutation(i)
285
IF ( k > 0 ) THEN
286
s = SQRT( SUM( Nvector(DIM*(k-1)+1:DIM*k)**2 ) )
287
288
IF ( s /= 0.0D0 ) THEN
289
Nvector(DIM*(k-1)+1:DIM*k) = Nvector(DIM*(k-1)+1:DIM*k)/s
290
END IF
291
END IF
292
293
END DO
294
295
CALL INFO(SolverName, 'End', level=3)
296
297
!------------------------------------------------------------------------------
298
END SUBROUTINE ComputeNormalSolver
299
!------------------------------------------------------------------------------
300
301