Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/GMValid.F90
3204 views
1
!*****************************************************************************/
2
! *
3
! * Elmer, A Finite Element Software for Multiphysical Problems
4
! *
5
! * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
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
! * An improved version of the routine to calculate basal melt rates on
24
! * ungrounded ice, producing a validity mask instead (1 = ungrounded area
25
! * connected to the ice front; 0 = isolated patch).
26
! ******************************************************************************
27
! *
28
! * Authors: Samuel Cook
29
! * Email: [email protected]
30
! * Web: http://www.csc.fi/elmer
31
! * Address: CSC - IT Center for Science Ltd.
32
! * Keilaranta 14
33
! * 02101 Espoo, Finland
34
! *
35
! * Original Date: 08.2019
36
! *
37
! ****************************************************************************/
38
39
SUBROUTINE GMValid (Model, Solver, dt, TransientSimulation)
40
USE Types
41
USE CoordinateSystems
42
USE DefUtils
43
USE ElementDescription
44
USE CalvingGeometry
45
46
IMPLICIT NONE
47
48
TYPE(Model_t) :: Model
49
TYPE(Solver_t) :: Solver
50
REAL(KIND=dp) :: dt
51
LOGICAL :: TransientSimulation
52
!-----------------------------------
53
TYPE(Mesh_t), POINTER :: Mesh
54
TYPE(Matrix_t), POINTER :: Matrix
55
TYPE(Variable_t), POINTER :: Var, GroundedVar
56
TYPE(ValueList_t), POINTER :: Params
57
TYPE(CrevasseGroup3D_t), POINTER :: FloatGroups, CurrentGroup, DelGroup
58
TYPE(Element_t), POINTER :: Element
59
TYPE(Nodes_t) :: ElementNodes
60
TYPE(GaussIntegrationPoints_t) :: IntegStuff
61
62
REAL(KIND=dp) :: GMCheck, SMeltRate, WMeltRate, SStart, SStop, &
63
TotalArea, TotalBMelt, ElemBMelt, s, t, season,&
64
SqrtElementMetric,U,V,W,Basis(Model % MaxElementNodes)
65
INTEGER :: DIM, NoNodes, i,j,n, FaceNodeCount, GroupNodeCount, county, &
66
Active, ierr, k, FoundNew, AllFoundNew
67
INTEGER, PARAMETER :: FileUnit = 75
68
INTEGER, POINTER :: Perm(:), InvPerm(:), FrontPerm(:)=>NULL(), Neighbours(:,:), &
69
NeighbourHolder(:), NoNeighbours(:), NodeIndexes(:)
70
INTEGER, ALLOCATABLE :: AllGroupNodes(:), PartNodeCount(:), AllPartGroupNodes(:), &
71
disps(:)
72
LOGICAL :: Found, OutputStats, Visited=.FALSE., Debug, stat, Summer
73
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName, GMaskVarName, FrontMaskName, OutfileName, mode
74
75
Debug = .FALSE.
76
77
SolverName = "GMValidator"
78
Params => Solver % Values
79
Mesh => Solver % Mesh
80
81
DIM = CoordinateSystemDimension()
82
IF(DIM /= 3) CALL Fatal(SolverName, "This solver only works in 3D!")
83
84
!Identify nodes on the front
85
FrontMaskName = "Calving Front Mask"
86
CALL MakePermUsingMask( Model, Solver, Mesh, FrontMaskName, &
87
.FALSE., FrontPerm, FaceNodeCount)
88
89
!Need the matrix for finding neighbours
90
Matrix => Solver % Matrix
91
92
Var => Solver % Variable
93
IF(.NOT. ASSOCIATED(Var)) CALL Fatal(SolverName, "Solver needs a variable!")
94
Perm => Var % Perm
95
Var % Values = 0.0_dp
96
97
NoNodes = COUNT(Perm > 0)
98
99
GMaskVarName = ListGetString(Params, "GroundedMask Variable", Found)
100
IF(.NOT. Found) GMaskVarName = "GroundedMask"
101
GroundedVar => VariableGet(Mesh % Variables, GMaskVarName, .TRUE., UnfoundFatal=.TRUE.)
102
103
GMCheck = 1.0_dp
104
105
!Set up inverse perm for FindNodeNeighbours
106
InvPerm => CreateInvPerm(Matrix % Perm) !Create inverse perm for neighbour search
107
ALLOCATE(Neighbours(Mesh % NumberOfNodes, 10), NoNeighbours(Mesh % NumberOfNodes))
108
Neighbours = 0
109
110
!Find neighbours for each node on the bed
111
DO i=1, Mesh % NumberOfNodes
112
IF(Perm(i) <= 0) CYCLE
113
114
NeighbourHolder => FindNodeNeighbours(i, Matrix, &
115
Matrix % Perm, 1, InvPerm)
116
117
Neighbours(i,1:SIZE(NeighbourHolder)) = NeighbourHolder
118
NoNeighbours(i) = SIZE(NeighbourHolder)
119
DEALLOCATE(NeighbourHolder)
120
END DO
121
122
!Reuse some old calving code
123
!Find groups of connected floating nodes on the base
124
FloatGroups => NULL()
125
CALL FindCrevasseGroups(Mesh, GroundedVar, Neighbours, &
126
-0.5_dp, FloatGroups)
127
128
!Check groups are valid (connected to front)
129
CurrentGroup => FloatGroups
130
DO WHILE(ASSOCIATED(CurrentGroup))
131
132
CurrentGroup % FrontConnected = .FALSE.
133
DO i=1, CurrentGroup % NumberOfNodes
134
135
IF(FrontPerm(CurrentGroup % NodeNumbers(i)) > 0) THEN
136
CurrentGroup % FrontConnected = .TRUE.
137
EXIT
138
END IF
139
END DO
140
CurrentGroup => CurrentGroup % Next
141
END DO
142
143
DO k=1,1000
144
FoundNew = 0
145
!Count and gather nodes from all valid groups
146
GroupNodeCount = 0
147
county = 0
148
DO i=1,2
149
IF(i==2) ALLOCATE(AllGroupNodes(GroupNodeCount))
150
151
CurrentGroup => FloatGroups
152
DO WHILE(ASSOCIATED(CurrentGroup))
153
IF(CurrentGroup % FrontConnected) THEN
154
155
IF(i==1) THEN
156
GroupNodeCount = GroupNodeCount + CurrentGroup % NumberOfNodes
157
ELSE
158
DO j=1, CurrentGroup % NumberOfNodes
159
county = county + 1
160
AllGroupNodes(county) = Mesh % ParallelInfo % GlobalDOFs(CurrentGroup % NodeNumbers(j))
161
END DO
162
END IF
163
END IF
164
CurrentGroup => CurrentGroup % Next
165
END DO
166
END DO
167
168
!Distribute info to/from all partitions about groups connected to front
169
ALLOCATE(PartNodeCount(ParEnv % PEs))
170
171
CALL MPI_ALLGATHER(GroupNodeCount, 1, MPI_INTEGER, PartNodeCount, 1, &
172
MPI_INTEGER, MPI_COMM_WORLD, ierr)
173
174
ALLOCATE(AllPartGroupNodes(SUM(PartNodeCount)), disps(ParEnv % PEs))
175
disps(1) = 0
176
DO i=2,ParEnv % PEs
177
disps(i) = disps(i-1) + PartNodeCount(i-1)
178
END DO
179
180
CALL MPI_ALLGATHERV(AllGroupNodes, GroupNodeCount, MPI_INTEGER, &
181
AllPartGroupNodes, PartNodeCount, disps, MPI_INTEGER, MPI_COMM_WORLD, ierr)
182
183
!Cycle unconnected groups, looking for partition boundary in connected groups
184
CurrentGroup => FloatGroups
185
DO WHILE(ASSOCIATED(CurrentGroup))
186
IF(.NOT. CurrentGroup % FrontConnected) THEN
187
DO i=1,CurrentGroup % NumberOfNodes
188
189
IF(ANY(Mesh % ParallelInfo % GlobalDOFs(CurrentGroup % NodeNumbers(i)) == &
190
AllPartGroupNodes)) THEN
191
CurrentGroup % FrontConnected = .TRUE.
192
FoundNew = 1
193
END IF
194
195
END DO
196
END IF
197
CurrentGroup => CurrentGroup % Next
198
END DO
199
CALL MPI_ALLREDUCE(FoundNew, AllFoundNew, 1, MPI_INTEGER, MPI_MAX, ELMER_COMM_WORLD, ierr)
200
IF(AllFoundNew == 1) THEN
201
DEALLOCATE(AllGroupNodes, PartNodeCount, AllPartGroupNodes, disps)
202
ELSE
203
EXIT
204
END IF
205
END DO !k
206
207
!Cycle all connected groups, setting melt rate
208
CurrentGroup => FloatGroups
209
DO WHILE(ASSOCIATED(CurrentGroup))
210
IF(CurrentGroup % FrontConnected) THEN
211
DO i=1,CurrentGroup % NumberOfNodes
212
Var % Values(Var % Perm(CurrentGroup % NodeNumbers(i))) = GMCheck
213
END DO
214
END IF
215
CurrentGroup => CurrentGroup % Next
216
END DO
217
218
!Deallocate floatgroups linked list
219
CurrentGroup => FloatGroups
220
DO WHILE(ASSOCIATED(CurrentGroup))
221
DelGroup => CurrentGroup
222
CurrentGroup => CurrentGroup % Next
223
224
IF(ASSOCIATED(DelGroup % NodeNumbers)) DEALLOCATE(DelGroup % NodeNumbers)
225
IF(ASSOCIATED(DelGroup % FrontNodes)) DEALLOCATE(DelGroup % FrontNodes)
226
IF(ASSOCIATED(DelGroup % BoundaryNodes)) DEALLOCATE(DelGroup % BoundaryNodes)
227
DEALLOCATE(DelGroup)
228
END DO
229
230
DEALLOCATE(Neighbours, NoNeighbours, FrontPerm, InvPerm)
231
END SUBROUTINE GMValid
232
233