Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/EPLSolver.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: Basile de Fleurian
26
! * Email: [email protected]; [email protected]
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date: 02 Jully 2013
30
! *
31
! *****************************************************************************
32
!> Limited solver to compute the water head in a sediment layer
33
!> Exported Variables EPLHead (dof=1)
34
!> The solver is treated on DIM-1, with DIM-2 boundary conditions
35
! *****************************************************************************
36
37
RECURSIVE SUBROUTINE EPLSolver( Model,Solver,Timestep,TransientSimulation )
38
!------------------------------------------------------------------------------
39
40
USE DiffuseConvective
41
USE DiffuseConvectiveGeneral
42
USE Differentials
43
USE MaterialModels
44
USE DefUtils
45
!------------------------------------------------------------------------------
46
IMPLICIT NONE
47
!------------------------------------------------------------------------------
48
!******************************************************************************
49
!
50
! Solve the diffusion equation in a porous layer within a domain given by a
51
! mask
52
!
53
! ARGUMENTS:
54
!
55
! TYPE(Model_t) :: Model,
56
! INPUT: All model information (mesh,materials,BCs,etc...)
57
!
58
! TYPE(Solver_t) :: Solver
59
! INPUT: Linear equation solver options
60
!
61
! REAL(KIND=dp) :: Timestep
62
! INPUT: Timestep size for time dependent simulations
63
!
64
! LOGICAL :: TransientSimulation
65
! INPUT: Steady state or transient simulation
66
!
67
!******************************************************************************
68
69
!------------------------------------------------------------------------------
70
! External variables
71
!------------------------------------------------------------------------------
72
TYPE(Model_t) :: Model
73
TYPE(Solver_t), TARGET :: Solver
74
REAL(KIND=dp) :: Timestep
75
LOGICAL :: TransientSimulation
76
!------------------------------------------------------------------------------
77
! Local variables
78
!------------------------------------------------------------------------------
79
TYPE(Matrix_t), POINTER :: Systemmatrix
80
TYPE(Element_t), POINTER :: Element
81
TYPE(Solver_t), POINTER :: PointerToSolver
82
TYPE(Variable_t), POINTER :: EPLHeadSol, Piping, IDSRes, VarEPLHead
83
TYPE(ValueList_t), POINTER :: Constants, SolverParams, Equation, &
84
Material, BodyForce, BC
85
TYPE(Nodes_t) :: ElementNodes
86
87
REAL(KIND=dp), POINTER :: EPLHead(:), OpenEPL(:), IDSResInput(:), &
88
ForceVector(:), Hwrk(:,:,:), EPLHeadHomologous(:)
89
REAL(KIND=dp), ALLOCATABLE :: Transmitivity(:,:,:)
90
REAL(KIND=dp), ALLOCATABLE :: g(:,:), Nochange(:,:), &
91
MASS(:,:), STIFF(:,:)
92
REAL(KIND=dp), ALLOCATABLE :: UpperLimit(:), EPLComp(:), &
93
Porosity(:), Gravity(:), EPLThick(:) , Density(:), &
94
StoringCoef(:), Viscosity(:), C0(:), C1(:), Zero(:), &
95
VNull(:), Work(:), Pressure(:), TransferCoeff(:), &
96
EPLHeadExt(:), OldValues(:), OldRHS(:),StiffVector(:), &
97
IDSHead(:), EPLToIDS(:),DummyRealArray(:), &
98
FORCE(:),LOAD(:), TimeForce(:)
99
REAL(KIND=dp) :: LinearTol, NonlinearTol, &
100
totat, totst, at, at0, st, &
101
WatComp, Norm, PrevNorm, RelativeChange
102
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName, VariableName, &
103
IDSHeadName, IDSResName
104
105
INTEGER, POINTER :: EPLHeadPerm(:), PipingPerm(:), &
106
IDSResPerm(:), HomolPerm(:)
107
INTEGER :: NonlinearIter, LocalNodes, &
108
PenIter, k, N, M, L, t, i, j, istat, &
109
body_id, material_id, bf_id, bc_id
110
111
LOGICAL, ALLOCATABLE :: ActiveEPL(:)
112
LOGICAL :: Found = .FALSE.,UnFoundFatal=.TRUE., &
113
Stabilize = .TRUE. ,&
114
UseBubbles = .FALSE., &
115
AllocationsDone = .FALSE., &
116
FluxBC = .FALSE., &
117
IsPeriodicBC = .FALSE., &
118
ApplyDirichlet = .FALSE., &
119
DummyLogical = .FALSE.
120
121
SAVE ElementNodes, &
122
Hwrk, &
123
Transmitivity, &
124
g, &
125
Nochange, &
126
MASS, &
127
STIFF, &
128
UpperLimit, &
129
EPLComp, &
130
Porosity, &
131
Gravity, &
132
EPLThick, &
133
Density, &
134
StoringCoef, &
135
Viscosity, &
136
C0, &
137
C1, &
138
Zero, &
139
VNull, &
140
Work, &
141
Pressure, &
142
TransferCoeff, &
143
EPLHeadExt, &
144
OldValues, &
145
OldRHS, &
146
StiffVector, &
147
IDSHead, &
148
EPLToIDS, &
149
DummyRealArray, &
150
FORCE, &
151
LOAD, &
152
TimeForce, &
153
ActiveEPL, &
154
SolverName, &
155
VariableName, &
156
LinearTol, &
157
NonlinearTol, &
158
AllocationsDone, &
159
DummyLogical
160
161
162
SystemMatrix => Solver % Matrix
163
ForceVector => Solver % Matrix % RHS
164
165
!------------------------------------------------------------------------------
166
! Get variables needed for solution
167
!------------------------------------------------------------------------------
168
SolverName = 'EPLSolver ('// TRIM(Solver % Variable % Name) // ')'
169
VariableName = TRIM(Solver % Variable % Name)
170
171
IF ( .NOT. ASSOCIATED( Solver % Matrix ) ) RETURN
172
PointerToSolver => Solver
173
174
EPLHeadSol => Solver % Variable
175
EPLHeadPerm => EPLHeadSol % Perm
176
EPLHead => EPLHeadSol % Values
177
178
LocalNodes = COUNT( EPLHeadPerm .GT. 0 )
179
IF ( LocalNodes .LE. 0 ) RETURN
180
181
!------------------------------------------------------------------------------
182
! Allocate some permanent storage, this is done first time only
183
!------------------------------------------------------------------------------
184
IF ( .NOT. AllocationsDone .OR. Solver % Mesh % Changed ) THEN
185
N = Solver % Mesh % MaxElementNodes
186
M = Model % Mesh % NumberOfNodes
187
K = SIZE( SystemMatrix % Values )
188
L = SIZE( SystemMatrix % RHS )
189
190
IF ( AllocationsDone ) THEN
191
DEALLOCATE( &
192
Transmitivity, &
193
g, &
194
Nochange, &
195
MASS, &
196
STIFF, &
197
UpperLimit, &
198
EPLComp, &
199
Porosity, &
200
Gravity, &
201
EPLThick, &
202
Density, &
203
StoringCoef, &
204
Viscosity, &
205
C0, &
206
C1, &
207
Zero, &
208
VNull, &
209
Work, &
210
Pressure, &
211
TransferCoeff, &
212
EPLHeadExt, &
213
OldValues, &
214
OldRHS, &
215
StiffVector, &
216
IDSHead, &
217
EPLToIDS, &
218
DummyRealArray, &
219
FORCE, &
220
LOAD, &
221
TimeForce, &
222
ActiveEPL, &
223
ElementNodes % x, &
224
ElementNodes % y, &
225
ElementNodes % z)
226
END IF
227
ALLOCATE( &
228
Transmitivity( 3,3,N ),&
229
g( 3,N ), &
230
Nochange( 3,N ), &
231
MASS( 2*N,2*N ), &
232
STIFF( 2*N,2*N ), &
233
UpperLimit( M ), &
234
EPLComp( N ), &
235
Porosity( N ), &
236
Gravity( N ), &
237
EPLThick( N ), &
238
Density( N ), &
239
StoringCoef( N ), &
240
Viscosity( N ), &
241
C0( N ), &
242
C1( N ), &
243
Zero( N ), &
244
VNull( N ), &
245
Work( N ), &
246
Pressure( N ), &
247
TransferCoeff( N ), &
248
EPLHeadExt( N ), &
249
OldValues( K ), &
250
OldRHS( L ), &
251
StiffVector( L ), &
252
IDSHead( N ), &
253
EPLToIDS( N ), &
254
DummyRealArray( N ), &
255
FORCE( 2*N ), &
256
LOAD( N ), &
257
TimeForce( 2*N ), &
258
ActiveEPL( M ), &
259
ElementNodes % x( N ), &
260
ElementNodes % y( N ), &
261
ElementNodes % z( N ), &
262
STAT=istat )
263
264
IF ( istat .NE. 0 ) THEN
265
CALL FATAL( SolverName, 'Memory allocation error in EPL Solve' )
266
ELSE
267
CALL INFO(SolverName, 'Memory allocation done in EPL Solve', level=1 )
268
END IF
269
AllocationsDone = .TRUE.
270
ActiveEPL = .FALSE.
271
END IF
272
273
!------------------------------------------------------------------------------
274
! Say hello
275
!------------------------------------------------------------------------------
276
WRITE(Message,'(A,A)')&
277
'Limited diffusion Solver for variable ', VariableName
278
CALL INFO(SolverName,Message,Level=1)
279
!------------------------------------------------------------------------------
280
! Read Iteration related constants
281
!------------------------------------------------------------------------------
282
SolverParams => GetSolverParams()
283
284
Stabilize = GetLogical( SolverParams,'Stabilize', Found )
285
IF (.NOT. Found) THEN
286
Stabilize = .FALSE.
287
END IF
288
289
UseBubbles = GetLogical( SolverParams,'Bubbles', Found )
290
IF ( .NOT.Found ) THEN
291
UseBubbles = .FALSE.
292
END IF
293
294
LinearTol = GetConstReal( SolverParams, &
295
'Linear System Convergence Tolerance', Found )
296
IF ( .NOT.Found ) THEN
297
CALL FATAL(SolverName, 'No >Linear System Convergence Tolerance< found')
298
END IF
299
300
NonlinearIter = GetInteger( SolverParams, &
301
'Nonlinear System Max Iterations', Found )
302
IF ( .NOT.Found ) THEN
303
NonlinearIter = 1
304
END IF
305
306
NonlinearTol = GetConstReal( SolverParams, &
307
'Nonlinear System Convergence Tolerance', Found )
308
IF ( .NOT.Found ) THEN
309
NonlinearTol = 1e-6
310
END IF
311
312
!------------------------------------------------------------------------------
313
! Read Physical constants
314
!------------------------------------------------------------------------------
315
Constants => GetConstants()
316
317
WatComp = GetConstReal( Constants, &
318
'Water Compressibility', Found)
319
IF ( .NOT.Found ) THEN
320
WatComp = 5.04e-4
321
END IF
322
323
totat = 0.0d0
324
totst = 0.0d0
325
326
!Variable for the sediment Residual
327
!----------------------------------
328
IDSResName = GetString(SolverParams,'IDS Residual Name', Found)
329
IF (.NOT.Found) THEN
330
WRITE(Message,'(a)') 'No Keyword >IDS Residual Name< defined. Using >IDSHead Residual< as default. '
331
CALL INFO(SolverName, Message, level=10)
332
WRITE(IDSResName,'(A)') 'IDSHead Residual'
333
ELSE
334
WRITE(Message,'(a,a)') 'Variable Name for IDS Water Head Residual: ', IDSResName
335
CALL INFO(SolverName,Message,Level=12)
336
END IF
337
338
IDSRes => VariableGet( Model % Mesh % Variables,IDSResName,UnFoundFatal=UnFoundFatal)
339
IDSResInput => IDSRes % Values
340
IDSResPerm => IDSRes % Perm
341
342
VarEPLHead => VariableGet( Model % Mesh % Variables, TRIM(Solver % Variable % Name) // ' Homologous',UnFoundFatal=UnFoundFatal)
343
EPLHeadHomologous => VarEPLHead % Values
344
HomolPerm => VarEPLHead % Perm
345
346
!Mask Variable
347
!----------------------------------------
348
Piping => VariableGet( Model % Mesh % Variables,'Open EPL',UnFoundFatal=UnFoundFatal)
349
PipingPerm => Piping % Perm
350
OpenEPL => Piping % Values
351
352
!------------------------------------------------------------------------------
353
! Do we use limiters
354
!------------------------------------------------------------------------------
355
SolverParams => GetSolverParams()
356
ApplyDirichlet = GetLogical( SolverParams, &
357
'Apply Dirichlet', Found)
358
IF ( .NOT.Found ) THEN
359
ApplyDirichlet = .FALSE.
360
END IF
361
IF (.NOT.ApplyDirichlet) THEN
362
ActiveEPL = .FALSE.
363
END IF
364
365
!-----------------------------------------------------------------------------
366
! Get Names for imported variables
367
!-----------------------------------------------------------------------------
368
IDSHeadName = GetString(SolverParams,'IDS Head Name', Found)
369
IF (.NOT.Found) THEN
370
WRITE(Message,'(a)') 'No Keyword >IDS Head Name< defined. Using >IDSHead< as default. '
371
CALL INFO(SolverName, Message, level=10)
372
WRITE(IDSHeadName,'(A)') 'IDSHead'
373
ELSE
374
WRITE(Message,'(a,a)') 'Variable Name for IDS Water Head: ', IDSHeadName
375
CALL INFO(SolverName,Message,Level=12)
376
END IF
377
378
!------------------------------------------------------------------------------
379
! non-linear system iteration loop
380
!------------------------------------------------------------------------------
381
DO Peniter=1,NonlinearIter
382
383
!------------------------------------------------------------------------------
384
! print out some information
385
!------------------------------------------------------------------------------
386
at = CPUTime()
387
at0 = RealTime()
388
CALL Info( SolverName, ' ', Level=4 )
389
CALL Info( SolverName, ' ', Level=4 )
390
CALL Info( SolverName, '-------------------------------------',Level=4 )
391
WRITE( Message,'(A,A,I3,A,I3)') &
392
TRIM(Solver % Variable % Name), ' iteration no.', Peniter,' of ',NonlinearIter
393
CALL Info( SolverName, Message, Level=4 )
394
CALL Info( SolverName, '-------------------------------------',Level=4 )
395
CALL Info( SolverName, ' ', Level=4 )
396
CALL Info( SolverName, 'Starting Assembly...', Level=4 )
397
398
!------------------------------------------------------------------------------
399
! lets start
400
!------------------------------------------------------------------------------
401
CALL DefaultInitialize()
402
403
!------------------------------------------------------------------------------
404
! write some info on max/min values
405
!------------------------------------------------------------------------------
406
WRITE(Message,'(a,e13.6,a,e13.6)') &
407
'Max/min values of EPL Water Head: ', MAXVAL(EPLHead(:)), &
408
'/',MINVAL(EPLHead(:))
409
CALL INFO(SolverName,Message,Level=4)
410
411
!------------------------------------------------------------------------------
412
body_id = -1
413
NULLIFY(Material)
414
415
!------------------------------------------------------------------------------
416
! Check if new nodes are activated and update the force vector accordingly
417
!------------------------------------------------------------------------------
418
DO i=1,Model % Mesh % NumberofNodes
419
IF ((EPLHeadPerm(i).GT.0).AND.&
420
(IDSResPerm(i).GT.0).AND.&
421
(PipingPerm(i).GT.0)) THEN
422
ForceVector(EPLHeadPerm(i)) = -IDSResInput(IDSResPerm(i))
423
424
!Dealing with Mask Values
425
!------------------------
426
IF (IDSResInput(IDSResPerm(i)).LT.0.0)THEN
427
OpenEPL(PipingPerm(i)) = -1.0
428
ELSEIF(ABS(OpenEPL(PipingPerm(i))).LT.1.0)THEN
429
OpenEPL(PipingPerm(i)) = 1.0
430
END IF
431
END IF
432
END DO
433
434
!------------------------------------------------------------------------------
435
! Bulk elements Loop
436
!------------------------------------------------------------------------------
437
DO t=1,Solver % NumberOfActiveElements
438
439
!------------------------------------------------------------------------------
440
! Check if this element belongs to a body where scalar equation
441
! should be calculated
442
!------------------------------------------------------------------------------
443
Element => GetActiveElement(t,Solver)
444
N = GetElementNOFNodes(Element)
445
CALL GetElementNodes( ElementNodes,Element )
446
447
IF (.NOT.ASSOCIATED(Element)) CYCLE
448
449
IF ( Element % BodyId .NE. body_id ) THEN
450
Equation => GetEquation()
451
IF (.NOT.ASSOCIATED(Equation)) THEN
452
WRITE (Message,'(A,I3)') 'No Equation found for boundary element no. ', t
453
CALL FATAL(SolverName,Message)
454
END IF
455
456
Material => GetMaterial()
457
IF (.NOT.ASSOCIATED(Material)) THEN
458
WRITE (Message,'(A,I3)') 'No Material found for boundary element no. ', t
459
CALL FATAL(SolverName,Message)
460
ELSE
461
material_id = GetMaterialId( Element, Found)
462
IF(.NOT.Found) THEN
463
WRITE (Message,'(A,I3)') 'No Material ID found for boundary element no. ', t
464
CALL FATAL(SolverName,Message)
465
END IF
466
END IF
467
END IF
468
469
!------------------------------------------------------------------------------
470
! Get element material parameters
471
!------------------------------------------------------------------------------
472
EPLComp(1:N) = listGetReal( Material,'EPL Compressibility', N, Element % NodeIndexes, Found,&
473
UnFoundFatal=UnFoundFatal)
474
! Previous default value: EPLComp(1:N) = 1.0D-2
475
476
Porosity(1:N) = listGetReal( Material,'EPL Porosity', N, Element % NodeIndexes, Found,&
477
UnFoundFatal=UnFoundFatal)
478
! Previous default value: Porosity(1:N) = 0.4D00
479
480
BodyForce => GetBodyForce()
481
IF ( ASSOCIATED( BodyForce ) ) THEN
482
bf_id = GetBodyForceId()
483
g = 0.0_dp
484
g(1,1:N) = GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 1',Found)
485
g(2,1:N) = GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 2',Found)
486
g(3,1:N) = GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 3',Found)
487
Gravity(1:N) = SQRT(SUM(g**2.0/N))
488
END IF
489
490
EPLThick(1:N) = listGetReal( Material,'EPL Thickness', N, Element % NodeIndexes, Found,&
491
UnFoundFatal=UnFoundFatal)
492
! Previous default value: EPLThick(1:N) = 1.0D00
493
494
Density(1:N) = ListGetReal( Material, 'Water Density', N, Element % NodeIndexes, Found,&
495
UnFoundFatal=UnFoundFatal)
496
! Previous default value: Density(1:N) = 1.0055D-18
497
498
!-----------------------------------------------------------------------------
499
! Get Upper limit:
500
!-----------------------------------------------------------------------------
501
IF (ApplyDirichlet)THEN
502
UpperLimit(Element % Nodeindexes(1:n)) = ListGetReal(Material,TRIM(VariableName) // &
503
' Upper Limit',n,Element % NodeIndexes, Found)
504
505
IF (.NOT. Found) THEN
506
WRITE(Message,'(a,i10)') 'No upper limit of solution for element no. ', t
507
CALL INFO(SolverName, Message, level=10)
508
END IF
509
END IF
510
!------------------------------------------------------------------------------
511
! add water contribution from transfer from EPL to sediment
512
!------------------------------------------------------------------------------
513
LOAD = 0.0D00
514
515
IF (ASSOCIATED(BodyForce)) THEN
516
bf_id = GetBodyForceId()
517
EPLToIDS(1:N) = ListGetReal( BodyForce, 'EPLToIDS Transfer', &
518
N, Element % NodeIndexes(1:N),Found,UnFoundFatal=UnFoundFatal)
519
! Previous default value: EPLToIDS(1:N) = 0.0
520
END IF
521
522
LOAD(1:N) = - EPLToIDS(1:N)
523
524
!Computing the Storing coefficient and transmitivity of the equivalent porous layer
525
!----------------------------------------------------------------------------------
526
CALL ListGetRealArray( Material,'EPL Transmitivity',Hwrk,N, Element % NodeIndexes,Found)
527
IF(.NOT.Found) THEN
528
WRITE (Message,'(A)') 'A EPL Transmitivity is needed'
529
CALL FATAL(SolverName,Message)
530
ELSE
531
Transmitivity = 0.0D0
532
IF ( SIZE(Hwrk,1) == 1 ) THEN
533
DO i=1,3
534
Transmitivity( i,i,1:N ) = Hwrk( 1,1,1:N)
535
END DO
536
ELSE
537
WRITE(Message,'(a,a,a)') 'Keyword >EPL Transmitivity< should be isotrop '
538
CALL INFO(SolverName,Message,Level=4)
539
END IF
540
END IF
541
542
StoringCoef(1:N) = EPLThick(1:N) * &
543
Gravity(1:N) * Porosity(1:N) * Density(1:N) * &
544
(WatComp + EPLComp(1:N)/Porosity(1:N))
545
546
!------------------------------------------------------------------------------
547
! dummy input array for faking heat capacity, density, temperature,
548
! enthalpy and viscosity
549
! Also faking the velocities to compute the Water load
550
!------------------------------------------------------------------------------
551
Work = 1.0d00
552
Zero = 0.0D00
553
VNull = 0.0D00
554
Nochange = 0.0D00
555
556
!------------------------------------------------------------------------------
557
! no contribution proportional to Water load by default
558
! No convection by default give C1 equal 0
559
! Viscosity is a dummy
560
!------------------------------------------------------------------------------
561
C0 = 0.0d00
562
C1 = 0.0d00
563
Viscosity = 0.0D00
564
565
!------------------------------------------------------------------------------
566
! Get element local matrices, and RHS vectors
567
!------------------------------------------------------------------------------
568
MASS = 0.0d00
569
STIFF = 0.0d00
570
FORCE = 0.0D00
571
572
! cartesian coords
573
!----------------
574
IF ( CurrentCoordinateSystem() == Cartesian ) THEN
575
CALL DiffuseConvectiveCompose( MASS, STIFF, FORCE, LOAD, &
576
StoringCoef, C0, C1(1:N), Transmitivity, &
577
.FALSE., Zero, Zero, VNull, VNull, VNull, &
578
Nochange(1,1:N),Nochange(2,1:N),Nochange(3,1:N),&
579
Viscosity, Density, Pressure, Zero, Zero,&
580
.FALSE., Stabilize, UseBubbles, Element, N, ElementNodes )
581
582
! special coords (account for metric)
583
!-----------------------------------
584
ELSE
585
CALL DiffuseConvectiveGenCompose( &
586
MASS, STIFF, FORCE, LOAD, &
587
StoringCoef, C0, C1(1:N), Transmitivity, &
588
.FALSE., Zero, Zero, VNull, VNull, VNull, &
589
Nochange(1,1:N),Nochange(2,1:N),Nochange(3,1:N), Viscosity,&
590
Density, Pressure, Zero, Zero,.FALSE.,&
591
Stabilize, Element, N, ElementNodes )
592
END IF
593
594
!------------------------------------------------------------------------------
595
! If time dependent simulation add mass matrix to stiff matrix
596
!------------------------------------------------------------------------------
597
TimeForce = FORCE
598
IF ( TransientSimulation ) THEN
599
IF ( UseBubbles ) FORCE = 0.0d0
600
CALL Default1stOrderTime( MASS,STIFF,FORCE )
601
END IF
602
603
!------------------------------------------------------------------------------
604
! Update global matrices from local matrices
605
!------------------------------------------------------------------------------
606
IF ( UseBubbles ) THEN
607
CALL Condensate( N, STIFF, FORCE, TimeForce )
608
IF (TransientSimulation) CALL DefaultUpdateForce( TimeForce )
609
END IF
610
CALL DefaultUpdateEquations( STIFF, FORCE )
611
612
END DO ! Bulk elements
613
CALL DefaultFinishBulkAssembly()
614
615
!------------------------------------------------------------------------------
616
! Neumann & Newton boundary conditions
617
!------------------------------------------------------------------------------
618
DO t=1, Solver % Mesh % NumberOfBoundaryElements
619
620
! get element information
621
Element => GetBoundaryElement(t)
622
623
IF ( .NOT.ActiveBoundaryElement() ) CYCLE
624
n = GetElementNOFNodes()
625
626
BC => GetBC()
627
bc_id = GetBCId( Element )
628
CALL GetElementNodes( ElementNodes,Element )
629
630
IF ( ASSOCIATED( BC ) ) THEN
631
632
!Initialize and check that we are on the correct boundary part!
633
STIFF=0.0D00
634
FORCE=0.0D00
635
MASS=0.0D00
636
LOAD=0.0D00
637
TransferCoeff = 0.0D00
638
EPLHeadExt = 0.0D00
639
FluxBC = .FALSE.
640
FluxBC = GetLogical(BC,TRIM(Solver % Variable % Name) // ' Flux BC', Found)
641
642
IF (FluxBC) THEN
643
644
!BC: -k@Hw/@n = a(Hw - HwExt)
645
!Check it if you want to use it this would represent a flux through a leaking media
646
!Checking of equations, parameters or units have not been done
647
!----------------------------------------------------------------------------------
648
TransferCoeff(1:n) = GetReal( BC, TRIM(Solver % Variable % Name) // ' Transfer Coefficient', Found )
649
IF ( ANY(TransferCoeff(1:n).NE.0.0d0) ) THEN
650
EPLHeadExt(1:n) = GetReal( BC, TRIM(Solver % Variable % Name) // ' External Value', Found )
651
DO j=1,n
652
LOAD(j) = LOAD(j) + TransferCoeff(j) * EPLHeadExt(j)
653
END DO
654
END IF
655
656
!---------------
657
!BC: -k@T/@n = q
658
!---------------
659
LOAD(1:n) = LOAD(1:n) + &
660
GetReal( BC, TRIM(Solver % Variable % Name) // ' Water Flux', Found )
661
662
!-------------------------------------
663
! set boundary due to coordinate system
664
! -------------------------------------
665
IF ( CurrentCoordinateSystem() == Cartesian ) THEN
666
CALL DiffuseConvectiveBoundary( STIFF,FORCE, &
667
LOAD,TransferCoeff,DummyLogical,DummyRealArray,&
668
DummyRealArray,Element,n,ElementNodes )
669
ELSE
670
CALL DiffuseConvectiveGenBoundary(STIFF,FORCE,&
671
LOAD,TransferCoeff,Element,n,ElementNodes )
672
END IF
673
END IF
674
END IF
675
676
!------------------------------------------------------------------------------
677
! Update global matrices from local matrices
678
!------------------------------------------------------------------------------
679
IF ( TransientSimulation ) THEN
680
MASS = 0.d0
681
CALL Default1stOrderTime( MASS, STIFF, FORCE )
682
END IF
683
CALL DefaultUpdateEquations( STIFF, FORCE )
684
END DO ! Neumann & Newton BCs
685
686
CALL DefaultFinishAssembly()
687
CALL DefaultDirichletBCs()
688
689
OldValues = SystemMatrix % Values
690
OldRHS = ForceVector
691
692
!------------------------------------------------------------------------------
693
! Dirichlet method - matrix and force-vector manipulation
694
!------------------------------------------------------------------------------
695
IF (ApplyDirichlet) THEN
696
697
!dealing with EPL spreading
698
!------------------------------
699
DO t=1,Solver % NumberOfActiveElements
700
701
Element => GetActiveElement(t)
702
N = GetElementNOFNodes(Element)
703
CALL GetElementNodes( ElementNodes,Element )
704
705
!Spreading is needed if one node of the element have a water head equal
706
! or above the upper limit and if one node of the element is still closed
707
!------------------------------------------------------------------------
708
IF ((ANY(ActiveEPL(Element % NodeIndexes(1:N))))&
709
.AND.(ANY(OpenEPL(PipingPerm(Element % NodeIndexes(1:N))).LT.0.0)))THEN
710
711
!Get the inefficient layer water head
712
!------------------------------------
713
CALL GetScalarLocalSolution(IDSHead,IDSHeadName,Element)
714
DO i=1,N
715
!The node to be activated is the one with the lower inefficient
716
!water head
717
!---------------------------------------------------------------
718
IF((IDSHead(i).EQ.MINVAL(IDSHead(1:N))).AND.&
719
(OpenEPL(PipingPerm(Element % NodeIndexes(i))).GT.0.0))&
720
OpenEPL(PipingPerm(Element % NodeIndexes(i))) = -1.0
721
END DO
722
END IF
723
END DO
724
END IF
725
726
CALL Info( TRIM(SolverName) // ' EPL Solver', 'Assembly done', Level=4 )
727
728
!------------------------------------------------------------------------------
729
! Solve the system
730
!------------------------------------------------------------------------------
731
at = CPUTime() - at
732
st = CPUTime()
733
734
PrevNorm = Solver % Variable % Norm
735
Norm = DefaultSolve()
736
737
SystemMatrix % Values = OldValues
738
ForceVector = OldRHS
739
740
!-------------------------------------------------------------------------------
741
! determine "active" nodes set, the node for which the EPL Water head is above
742
! the upper limit
743
!-------------------------------------------------------------------------------
744
DO i=1,Model % Mesh % NumberOfNodes
745
k = HomolPerm(i)
746
l = EPLHeadPerm(i)
747
748
IF ( (k.LE.0).OR.(l.LE.0)) CYCLE
749
EPLHeadHomologous(k) = EPLHead(l) - UpperLimit(i)
750
751
!----------------------------------------------------------
752
! if upper limit is exceeded, flag the node
753
!----------------------------------------------------------
754
IF ((ApplyDirichlet).AND.(EPLHeadHomologous(k).GE.0.0 )) THEN
755
ActiveEPL(i) = .TRUE.
756
EPLHeadHomologous(k) = LinearTol
757
END IF
758
END DO
759
760
!------------------------------------------
761
! special treatment for periodic boundaries
762
!------------------------------------------
763
DO t=1, Solver % Mesh % NumberOfBoundaryElements
764
765
! get element information
766
Element => GetBoundaryElement(t)
767
IF ( .NOT.ActiveBoundaryElement() ) CYCLE
768
n = GetElementNOFNodes()
769
BC => GetBC()
770
bc_id = GetBCId( Element )
771
772
CALL GetElementNodes( ElementNodes,Element )
773
774
IF ( ASSOCIATED( BC ) ) THEN
775
IsPeriodicBC = GetLogical(BC,'Periodic BC ' // TRIM(Solver % Variable % Name), Found)
776
IF (.NOT.Found) IsPeriodicBC = .FALSE.
777
IF (IsPeriodicBC) THEN
778
DO i=1,N
779
IF (ActiveEPL(Element % NodeIndexes(i))) THEN
780
ActiveEPL(Element % NodeIndexes(i)) = .FALSE.
781
END IF
782
END DO
783
END IF
784
END IF
785
END DO
786
Norm = Solver % Variable % Norm
787
788
!Checking for convergence
789
!------------------------
790
st = CPUTime()-st
791
totat = totat + at
792
totst = totst + st
793
WRITE(Message,'(a,i4,a,F8.2,F8.2)') 'iter: ',Peniter,' Assembly tot: (s)', at, totat
794
CALL Info( SolverName, Message, Level=4 )
795
WRITE(Message,'(a,i4,a,F8.2,F8.2)') 'iter: ',Peniter,' Solve: (s)', st, totst
796
CALL Info( SolverName, Message, Level=4 )
797
798
IF ((PrevNorm + Norm).NE.0.0d0 ) THEN
799
RelativeChange = 2.0d0 * ABS( PrevNorm-Norm ) / (PrevNorm + Norm)
800
ELSE
801
RelativeChange = 0.0d0
802
END IF
803
804
WRITE( Message, * ) 'Result Norm : ',Norm
805
CALL Info( SolverName, Message, Level=4 )
806
WRITE( Message, * ) 'Relative Change : ',RelativeChange
807
CALL Info( SolverName, Message, Level=4 )
808
809
IF (RelativeChange.LT.NonlinearTol) THEN
810
EXIT
811
END IF
812
813
IF((PenIter.EQ.NonlinearIter).AND.(RelativeChange.GT.NonlinearTol))THEN
814
Write(*,*)'NOT CONVERGED'
815
STOP
816
END IF
817
END DO
818
819
END SUBROUTINE EPLSolver
820
821