Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/ComputeCalvingNormal.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
37
!NB: This is just a local copy of ComputeNormalSolver, with modified keywords
38
! to allow proper normal computation on two adjacent boundaries.
39
SUBROUTINE ComputeCalvingNormalSolver( Model, Solver, dt, TransientSimulation )
40
!------------------------------------------------------------------------------
41
!******************************************************************************
42
!
43
! ARGUMENTS:
44
!
45
! TYPE(Model_t) :: Model,
46
! INPUT: All model information (mesh, materials, BCs, etc...)
47
!
48
! TYPE(Solver_t) :: Solver
49
! INPUT: Linear & nonlinear equation solver options
50
!
51
! REAL(KIND=dp) :: dt,
52
! INPUT: Timestep size for time dependent simulations
53
!
54
! LOGICAL :: TransientSimulation
55
! INPUT: Steady state or transient simulation
56
!
57
!Modification have been done to deal with problems where we don't want to compute
58
!the normal on all the boundaries (problem with the corners)
59
!
60
!Keywords are: ComputeAll = True/False computing / or not the normal on every boundary
61
! ComputeNormal = True to compute the normal on a given boundary
62
!******************************************************************************
63
USE DefUtils
64
65
IMPLICIT NONE
66
!------------------------------------------------------------------------------
67
TYPE(Solver_t), TARGET :: Solver
68
TYPE(Model_t) :: Model
69
70
REAL(KIND=dp) :: dt
71
LOGICAL :: TransientSimulation
72
73
!------------------------------------------------------------------------------
74
! Local variables
75
!------------------------------------------------------------------------------
76
TYPE(Mesh_t), POINTER :: Mesh
77
TYPE(Element_t), POINTER :: Element
78
TYPE(Variable_t), POINTER :: NormalSolution
79
TYPE(ValueList_t), POINTER :: SolverParams
80
81
INTEGER :: i, j, k, l, m, n, cnt, ierr, t, DIM
82
REAL(KIND=dp) :: u, v, w, s
83
REAL(KIND=dp), POINTER :: Nvector(:), PassNVector(:), RecvNVector(:)
84
INTEGER, POINTER :: Permutation(:), Neighbours(:)
85
INTEGER, ALLOCATABLE :: NeighbourPerm(:), PassCount(:), RecvCount(:),&
86
PassIndices(:,:), RecvIndices(:,:), LocalPerm(:)
87
INTEGER, DIMENSION(MPI_STATUS_SIZE) :: status
88
TYPE(Nodes_t), SAVE :: Nodes
89
REAL(KIND=dp) :: Bu, Bv, Normal(3)
90
91
LOGICAL :: Found, Parallel, MeActive=.TRUE.
92
LOGICAL, ALLOCATABLE :: Hit(:), PartActive(:)
93
94
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName = 'ComputeCalvingNormalSolver'
95
96
Parallel = (ParEnv % PEs > 1)
97
Mesh => Solver % Mesh
98
DIM = CoordinateSystemDimension()
99
100
!---------------------------------------
101
! Setup pointer to the current solution:
102
!---------------------------------------
103
NormalSolution => Solver % Variable
104
IF ( ASSOCIATED( NormalSolution ) ) THEN
105
Nvector => NormalSolution % Values
106
Permutation => NormalSolution % Perm
107
Nvector = 0.0_dp !wipe out previous
108
ELSE
109
PRINT *,'FATAL: Unable to set pointer to the current solution'
110
STOP
111
END IF
112
113
114
CALL INFO(SolverName, 'Computing Normal Vector for Nodes', level=3)
115
116
SolverParams => GetSolverParams()
117
118
!Check if current partition has anything to do
119
IF(Parallel) THEN
120
MeActive = .TRUE.
121
IF(Solver % NumberOfActiveElements <= 0) MeActive = .FALSE.
122
ALLOCATE(PartActive(ParEnv % PEs))
123
124
CALL MPI_ALLGATHER(MeActive,1,MPI_LOGICAL,&
125
PartActive,1,MPI_LOGICAL, ELMER_COMM_WORLD, ierr)
126
127
IF(.NOT. MeActive) RETURN
128
129
ALLOCATE(Hit(Mesh % NumberOfNodes), &
130
NeighbourPerm(ParEnv % PEs),&
131
PassCount(ParEnv % NumOfNeighbours),&
132
RecvCount(ParEnv % NumOfNeighbours),&
133
PassIndices(ParEnv % NumOfNeighbours, Mesh % NumberOfNodes),&
134
RecvIndices(ParEnv % NumOfNeighbours, Mesh % NumberOfNodes),&
135
LocalPerm( MAXVAL(Mesh % ParallelInfo % GlobalDOFs)))
136
137
NeighbourPerm = 0
138
LocalPerm = 0
139
Hit = .FALSE.
140
RecvCount = 0
141
PassCount = 0
142
PassIndices = 0
143
144
!Create a list of partitions with which we share nodes
145
cnt = 0
146
DO i=1,ParEnv % PEs
147
IF(ParEnv % MyPE == i-1) CYCLE
148
IF(.NOT. PartActive(i)) CYCLE
149
IF(.NOT. ParEnv % IsNeighbour(i)) CYCLE
150
cnt = cnt + 1
151
NeighbourPerm(i) = cnt
152
END DO
153
154
!Perm to get back from global to local node numbering
155
DO i=1, Mesh % NumberOfNodes
156
LocalPerm(Mesh % ParallelInfo % GlobalDOFs(i)) = i
157
END DO
158
159
END IF !Parallel
160
161
DO t = 1, Solver % NumberOfActiveElements
162
Element => GetActiveElement(t)
163
164
IF(Element % PartIndex /= ParEnv % MyPE) CYCLE
165
166
n = GetElementNOFNodes(Element)
167
IF (n == 1) CYCLE
168
169
CALL GetElementNodes( Nodes, Element )
170
171
DO i = 1,n
172
j = Element % NodeIndexes( i )
173
k = Permutation(j)
174
175
IF(k <= 0) CALL Fatal(SolverName, &
176
"Encountered invalid perm, this is a programming error")
177
178
Bu = Element % Type % NodeU(i)
179
IF ( Element % Type % Dimension > 1 ) THEN
180
Bv = Element % Type % NodeV(i)
181
ELSE
182
Bv = 0.0D0
183
END IF
184
Normal = NormalVector(Element, Nodes, Bu, Bv, .TRUE.)
185
Nvector(DIM*(k-1)+1:DIM*k) = Nvector(DIM*(k-1)+1:DIM*k) +&
186
Normal(1:DIM)
187
188
IF(Parallel) Hit(j) = .TRUE.
189
END DO
190
END DO
191
192
IF(Parallel) THEN
193
194
!Find nodes on partition boundaries
195
RecvCount = 0
196
PassCount = 0
197
PassIndices = 0
198
DO i=1,Model % Mesh % NumberOfNodes
199
IF(.NOT.Hit(i)) CYCLE !no normal computation
200
IF(.NOT. Mesh % ParallelInfo % GInterface(i)) CYCLE !no partition interface
201
Neighbours => Mesh % ParallelInfo % NeighbourList(i) % Neighbours
202
203
DO j=1,SIZE(Neighbours)
204
IF(Neighbours(j) == ParEnv % MyPE) CYCLE
205
IF(.NOT. PartActive(Neighbours(j)+1)) CYCLE
206
207
m = NeighbourPerm(Neighbours(j)+1)
208
PassCount(m) = PassCount(m) + 1
209
PassIndices(m, PassCount(m)) = i
210
END DO
211
END DO
212
213
!Send
214
DO i=1,ParEnv % PEs
215
IF(NeighbourPerm(i) == 0) CYCLE
216
m = NeighbourPerm(i)
217
218
!Send count
219
CALL MPI_BSEND(PassCount(m), 1, MPI_INTEGER, i-1, 200, ELMER_COMM_WORLD, ierr)
220
!Send (global) node numbers
221
CALL MPI_BSEND(Mesh % ParallelInfo % GlobalDOFs(PassIndices(m,1:PassCount(m))),&
222
PassCount(m), MPI_INTEGER, i-1, 201, ELMER_COMM_WORLD, ierr)
223
224
!Construct normal vector array to pass
225
ALLOCATE(PassNVector(PassCount(m) * DIM))
226
DO j=1, PassCount(m)
227
l = Permutation(PassIndices(m,j))
228
PassNVector(DIM*(j-1)+1:DIM*j) = NVector(DIM*(l-1)+1:DIM*l)
229
END DO
230
231
!Send normal vectors
232
CALL MPI_BSEND(PassNVector, PassCount(m)*DIM, MPI_DOUBLE_PRECISION, &
233
i-1, 202, ELMER_COMM_WORLD, ierr)
234
235
DEALLOCATE(PassNVector)
236
END DO
237
238
!Receive
239
DO i=1,ParEnv % PEs
240
241
IF(NeighbourPerm(i) == 0) CYCLE
242
m = NeighbourPerm(i)
243
244
!Receive count
245
CALL MPI_RECV(RecvCount(m), 1, MPI_INTEGER, i-1, 200, ELMER_COMM_WORLD, status, ierr)
246
247
!Receive (global) node numbers
248
CALL MPI_RECV(RecvIndices(m,1:RecvCount(m)), RecvCount(m), MPI_INTEGER, &
249
i-1, 201, ELMER_COMM_WORLD, status, ierr)
250
251
!Receive normal vectors
252
ALLOCATE(RecvNVector(RecvCount(m)*DIM))
253
CALL MPI_RECV(RecvNVector, RecvCount(m)*DIM, MPI_DOUBLE_PRECISION, &
254
i-1, 202, ELMER_COMM_WORLD, status, ierr)
255
256
DO j=1, RecvCount(m)
257
IF(.NOT. Hit(LocalPerm(RecvIndices(m,j)))) CYCLE !passed a halo node
258
k = Permutation(LocalPerm(RecvIndices(m,j)))
259
NVector(DIM*(k-1)+1:DIM*k) = NVector(DIM*(k-1)+1:DIM*k) + RecvNVector(DIM*(j-1)+1:DIM*j)
260
END DO
261
262
DEALLOCATE(RecvNVector)
263
END DO
264
265
END IF !Parallel
266
267
DO i=1,Model % NumberOfNodes
268
k = Permutation(i)
269
IF ( k > 0 ) THEN
270
s = SQRT( SUM( Nvector(DIM*(k-1)+1:DIM*k)**2 ) )
271
272
IF ( s /= 0.0D0 ) THEN
273
Nvector(DIM*(k-1)+1:DIM*k) = Nvector(DIM*(k-1)+1:DIM*k)/s
274
END IF
275
END IF
276
277
END DO
278
279
CALL INFO(SolverName, 'End', level=3)
280
281
!------------------------------------------------------------------------------
282
END SUBROUTINE ComputeCalvingNormalSolver
283
!------------------------------------------------------------------------------
284
285