1
!/*****************************************************************************
3
! * Elmer, A Finite Element Software for Multiphysical Problems
5
! * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
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.
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.
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.
22
! *****************************************************************************/
24
!/******************************************************************************
26
! * Subroutines for moving and renormalizing the level set function,
27
! * and computing the curvature of the level set field.
29
! ******************************************************************************
31
! * Authors: Juha Ruokolainen, Peter Rļæ½back
32
! * Email: Peter.Raback@csc.fi
33
! * Web: http://www.csc.fi/elmer
34
! * Address: CSC - IT Center for Science Ltd.
36
! * 02101 Espoo, Finland
38
! * Original Date: 16.11.2005
40
! *****************************************************************************/
44
!------------------------------------------------------------------------------
45
SUBROUTINE LevelSetSolver( Model,Solver,Timestep,TransientSimulation )
46
!------------------------------------------------------------------------------
47
!******************************************************************************
49
! Solve the advection equation for the Levelset-function using stabilization
50
! or bubbless. For the accuracy it is advisable to use 2nd order time-stepping
51
! and courant number smaller than one.
55
! TYPE(Model_t) :: Model,
56
! INPUT: All model information (mesh, materials, BCs, etc...)
58
! TYPE(Solver_t) :: Solver
59
! INPUT: Linear equation solver options
61
! REAL(KIND=dp) :: Timestep,
62
! INPUT: Timestep size for time dependent simulations
64
! LOGICAL :: TransientSimulation
65
! INPUT: Steady state or transient simulation
67
!******************************************************************************
75
!------------------------------------------------------------------------------
77
TYPE(Model_t), TARGET :: Model
78
TYPE(Solver_t) :: Solver
79
REAL(KIND=dp) :: Timestep
80
LOGICAL :: TransientSimulation
82
!------------------------------------------------------------------------------
84
!------------------------------------------------------------------------------
85
INTEGER :: i,j,k,n,t,iter,istat,bf_id,CoordinateSystem
87
TYPE(Matrix_t),POINTER :: StiffMatrix
88
TYPE(Nodes_t) :: ElementNodes
89
TYPE(Element_t),POINTER :: CurrentElement
90
TYPE(ValueList_t), POINTER :: Material
92
REAL(KIND=dp) :: Norm,RelativeChange
93
LOGICAL :: Stabilize = .FALSE., GotIt, AllocationsDone = .FALSE.
94
INTEGER, POINTER :: SurfPerm(:), NodeIndexes(:)
95
REAL(KIND=dp), POINTER :: Surface(:), ForceVector(:), Surf(:), PrevSurface(:)
96
REAL(KIND=dp), ALLOCATABLE :: LocalMassMatrix(:,:),&
97
LocalStiffMatrix(:,:),Load(:),LocalForce(:),TimeForce(:)
98
INTEGER :: NSDOFs,NonlinearIter,body_id,mat_id,dim
99
REAL(KIND=dp) :: NonlinearTol,dt, r, ct, DsMax
100
REAL(KIND=dp), ALLOCATABLE :: ElemVelo(:,:), SurfaceFlux(:)
102
SAVE LocalMassMatrix,LocalStiffMatrix,Load, &
103
TimeForce, LocalForce, ElementNodes,AllocationsDone, &
104
ElemVelo, Surf, SurfaceFlux
106
REAL(KIND=dp) :: at,totat,st,totst,CPUTime
109
!------------------------------------------------------------------------------
110
! Get variables needed for solution
111
!------------------------------------------------------------------------------
113
CALL Info( 'LevelSetSolver','-------------------------------------', Level=4 )
114
CALL Info( 'LevelSetSolver', 'Solving for the levelset function', Level=4 )
115
CALL Info( 'LevelSetSolver','-------------------------------------', Level=4 )
118
IF ( .NOT. ASSOCIATED( Solver % Matrix ) ) RETURN
120
CoordinateSystem = CurrentCoordinateSystem()
121
dim = CoordinateSystemDimension()
123
Surface => Solver % Variable % Values
124
IF ( SIZE( Surface ) == 0 ) RETURN
125
SurfPerm => Solver % Variable % Perm
126
PrevSurface => Solver % Variable % PrevValues(:,1)
128
StiffMatrix => Solver % Matrix
129
ForceVector => StiffMatrix % RHS
130
Norm = Solver % Variable % Norm
132
!------------------------------------------------------------------------------
133
! Allocate some permanent storage, this is done first time only
134
!------------------------------------------------------------------------------
135
IF ( .NOT. AllocationsDone ) THEN
136
N = Solver % Mesh % MaxElementNodes
138
ALLOCATE( ElemVelo(3, N), &
139
ElementNodes % x( N ), &
140
ElementNodes % y( N ), &
141
ElementNodes % z( N ), &
144
LocalMassMatrix( 2*N,2*N ), &
145
LocalStiffMatrix( 2*N,2*N ), &
150
IF ( istat /= 0 ) THEN
151
CALL Fatal( 'LevelSetSolver', 'Memory allocation error.' )
154
AllocationsDone = .TRUE.
156
!------------------------------------------------------------------------------
157
! Do some additional initialization, and go for it
158
!------------------------------------------------------------------------------
160
Stabilize = ListGetLogical( Solver % Values,'Stabilize',GotIt )
162
NonlinearTol = ListGetConstReal( Solver % Values, &
163
'Nonlinear System Convergence Tolerance',GotIt )
165
NonlinearIter = ListGetInteger( Solver % Values, &
166
'Nonlinear System Max Iterations',GotIt )
167
IF ( .NOT.GotIt ) NonlinearIter = 1
171
!------------------------------------------------------------------------------
176
CALL Info( 'LevelSetSolver','-------------------------------------', Level=4 )
177
CALL Info( 'LevelSetSolver', 'Updating the levelset function', Level=4 )
178
CALL Info( 'LevelSetSolver','-------------------------------------', Level=4 )
180
DO iter = 1, NonlinearIter
184
!------------------------------------------------------------------------------
185
CALL InitializeToZero( StiffMatrix, ForceVector )
186
!------------------------------------------------------------------------------
188
!------------------------------------------------------------------------------
189
! Do the assembly for bulk elements
190
!------------------------------------------------------------------------------
192
DO t=1,Solver % NumberOfActiveElements
194
CurrentElement => Solver % Mesh % Elements(Solver % ActiveElements(t))
195
body_id = CurrentElement % Bodyid
196
mat_id = ListGetInteger( Model % Bodies( body_id ) % Values, 'Material' )
197
Material => Model % Materials(mat_id) % Values
199
!------------------------------------------------------------------------------
200
! Set the current element pointer in the model structure to
201
! reflect the element being processed
202
!------------------------------------------------------------------------------
203
Model % CurrentElement => CurrentElement
204
n = CurrentElement % TYPE % NumberOfNodes
205
NodeIndexes => CurrentElement % NodeIndexes
207
!------------------------------------------------------------------------------
208
! Get element nodal coordinates
209
!------------------------------------------------------------------------------
210
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
211
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
212
ElementNodes % z(1:n) = Solver % Mesh % Nodes % z(NodeIndexes)
214
Surf = Surface( SurfPerm(NodeIndexes) )
216
!------------------------------------------------------------------------------
217
! Computed velocity field
218
!------------------------------------------------------------------------------
220
ElemVelo(1,1:n) = ListGetReal( Material,'Levelset Velocity 1',n,NodeIndexes,GotIt)
221
ElemVelo(2,1:n) = ListGetReal( Material,'Levelset Velocity 2',n,NodeIndexes,GotIt)
222
IF(dim == 3) ElemVelo(3,1:n) = ListGetReal( Material,'Levelset Velocity 3',n,NodeIndexes,GotIt)
224
!------------------------------------------------------------------------------
226
!------------------------------------------------------------------------------
227
bf_id = ListGetInteger( Model % Bodies(CurrentElement % BodyId) % &
228
Values, 'Body Force', GotIt )
230
SurfaceFlux(1:n) = ListGetReal( Model % BodyForces(bf_id) % Values, &
231
'Levelset Flux',n,NodeIndexes,gotIt )
233
SurfaceFlux(1:n) = 0.0d0
236
!------------------------------------------------------------------------------
237
CALL LocalMatrix( LocalMassMatrix, LocalStiffMatrix, LocalForce, Surf, &
238
SurfaceFlux, ElemVelo, Stabilize, CurrentElement, n, ElementNodes )
240
!------------------------------------------------------------------------------
241
! If time dependent simulation add mass matrix to stiff matrix
242
!------------------------------------------------------------------------------
244
IF ( TransientSimulation ) THEN
245
!------------------------------------------------------------------------------
246
! NOTE: This will replace LocalStiffMatrix and LocalForce with the
247
! combined information...
248
!------------------------------------------------------------------------------
249
CALL Add1stOrderTime( LocalMassMatrix, LocalStiffMatrix, &
250
LocalForce, dt, n, 1, SurfPerm(NodeIndexes), Solver )
252
!------------------------------------------------------------------------------
253
! Update global matrix and rhs vector from local matrix & vector
254
!------------------------------------------------------------------------------
255
IF ( .NOT.Stabilize ) THEN
256
CALL Condensate( N, LocalStiffMatrix, LocalForce, TimeForce )
259
CALL UpdateGlobalEquations( StiffMatrix, LocalStiffMatrix, &
260
ForceVector, LocalForce, n, 1, SurfPerm(NodeIndexes) )
262
END DO ! Of ActiveElements
265
!------------------------------------------------------------------------------
266
! FinishAssemebly must be called after all other assembly steps, but before
267
! Dirichlet boundary settings. Actually no need to call it except for
268
! transient simulations.
269
!------------------------------------------------------------------------------
270
CALL FinishAssembly( Solver,ForceVector )
271
!------------------------------------------------------------------------------
272
! Dirichlet boundary conditions
273
!------------------------------------------------------------------------------
274
CALL SetDirichletBoundaries( Model, StiffMatrix, ForceVector, &
275
ComponentName(Solver % Variable),1,1,SurfPerm )
276
!------------------------------------------------------------------------------
277
CALL Info( 'LevelSetSolver', 'Assembly done', Level=4 )
281
!------------------------------------------------------------------------------
282
! Solve the system and check for convergence
283
!------------------------------------------------------------------------------
286
CALL SolveSystem( StiffMatrix, ParMatrix, ForceVector, &
287
Surface, Norm, 1, Solver )
288
RelativeChange = Solver % Variable % NonlinChange
293
IF(NonlinearIter > 1) THEN
294
WRITE( Message, * ) 'Iteration : ',iter
295
CALL Info( 'LevelSetSolver', Message, Level=4 )
297
WRITE( Message, * ) 'Result Norm : ',Norm
298
CALL Info( 'LevelSetSolver', Message, Level=4 )
299
WRITE( Message, * ) 'Relative Change : ',RelativeChange
300
CALL Info( 'LevelSetSolver', Message, Level=4 )
302
IF(RelativeChange < NonlinearTol) EXIT
304
!------------------------------------------------------------------------------
305
END DO ! of the nonlinear iteration
306
!------------------------------------------------------------------------------
308
WRITE(Message,'(a,F8.2)') 'Assembly done in time (s):',totat
309
CALL Info( 'LevelsetSolver',Message, Level=4 )
311
WRITE(Message,'(a,F8.2)') 'Solution done in time (s):',totst
312
CALL Info( 'LevelsetSolver',Message, Level=4 )
314
DsMax = MAXVAL( ABS(Surface - PrevSurface) )
315
WRITE(Message,'(a,ES12.3)') 'Maximum Levelset Change',dsmax
316
CALL Info( 'LevelSetSolver',Message, Level=4 )
317
CALL ListAddConstReal(Model % Simulation,'res: LevelSet Max Change',dsmax)
320
!------------------------------------------------------------------------------
324
SUBROUTINE LocalMatrix( MassMatrix,StiffMatrix,ForceVector, &
325
Surf, Flux, NodalVelo, Stabilize,Element,n,Nodes )
326
!------------------------------------------------------------------------------
328
REAL(KIND=dp), DIMENSION(:) :: ForceVector,Surf,Flux
329
REAL(KIND=dp), DIMENSION(:,:) :: MassMatrix,StiffMatrix,NodalVelo
332
TYPE(Nodes_t) :: Nodes
333
TYPE(Element_t), POINTER :: Element
335
!------------------------------------------------------------------------------
337
!------------------------------------------------------------------------------
339
REAL(KIND=dp) :: ddBasisddx(n,3,3)
340
REAL(KIND=dp) :: Basis(2*n)
341
REAL(KIND=dp) :: dBasisdx(2*n,3),SQRTElementMetric
342
REAL(KIND=dp) :: Velo(3),Force,Grad(3),GradAbs
343
REAL(KIND=dp) :: A,M,Load, FL
344
REAL(KIND=dp) :: VNorm,hK,mK
345
REAL(KIND=dp) :: Lambda=1.0,Pe,Pe1,Pe2,Tau,x,y,z
347
INTEGER :: i,j,k,c,p,q,t,dim,N_Integ,NBasis
348
REAL(KIND=dp) :: s,u,v,w
349
TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff
350
REAL(KIND=dp) :: SU(n),SW(n)
351
REAL(KIND=dp), DIMENSION(:), POINTER :: U_Integ,V_Integ,W_Integ,S_Integ
353
LOGICAL :: stat,Bubbles
355
!------------------------------------------------------------------------------
357
dim = CoordinateSystemDimension()
368
IF ( .NOT. Stabilize ) THEN
373
!------------------------------------------------------------------------------
375
!------------------------------------------------------------------------------
377
IntegStuff = GaussPoints( element, Element % TYPE % GaussPoints2 )
379
IntegStuff = GaussPoints( element )
381
U_Integ => IntegStuff % u
382
V_Integ => IntegStuff % v
383
W_Integ => IntegStuff % w
384
S_Integ => IntegStuff % s
385
N_Integ = IntegStuff % n
387
!------------------------------------------------------------------------------
388
! Stabilization parameters: hK, mK (take a look at Franca et.al.)
389
! If there is no convection term we don t need stabilization.
390
!------------------------------------------------------------------------------
391
IF ( Stabilize ) THEN
393
mK = element % StabilizationMK
396
!------------------------------------------------------------------------------
397
! Now we start integrating
398
!------------------------------------------------------------------------------
405
!------------------------------------------------------------------------------
406
! Basis function values & derivatives at the integration point
407
!------------------------------------------------------------------------------
408
stat = ElementInfo( Element,Nodes,u,v,w,SQRTElementMetric, &
409
Basis,dBasisdx,ddBasisddx,Stabilize,Bubbles )
411
s = SQRTElementMetric * S_Integ(t)
412
!------------------------------------------------------------------------------
413
! Coordinatesystem dependent info
414
!------------------------------------------------------------------------------
415
IF ( Coordinates == AxisSymmetric .OR. &
416
Coordinates == CylindricSymmetric ) THEN
417
s = s * SUM( Nodes % x(1:n)*Basis(1:n) )
420
!------------------------------------------------------------------------------
422
FL = SUM( Flux(1:n) * Basis(1:n) )
425
Grad(i) = SUM( dBasisdx(1:n,i) * Surf(1:n) )
427
GradAbs = SQRT( SUM( Grad(1:dim) * Grad(1:dim) ) )
428
IF ( GradAbs > 10*AEPS ) THEN
429
Grad = Grad / GradAbs
432
!------------------------------------------------------------------------------
433
! Velocity from previous iteration at the integration point
434
!------------------------------------------------------------------------------
437
Velo(1) = SUM( NodalVelo(1,1:n)*Basis(1:n) )
438
Velo(2) = SUM( NodalVelo(2,1:n)*Basis(1:n) )
439
IF ( dim > 2 ) Velo(3) = SUM( NodalVelo(3,1:n)*Basis(1:n) )
442
IF ( Stabilize ) THEN
443
!------------------------------------------------------------------------------
444
! Stabilization parameter Tau
445
!------------------------------------------------------------------------------
446
VNorm = SQRT( SUM(Velo(1:dim)**2) ) + FL
449
IF ( VNorm /= 0.0 ) THEN
450
Tau = hK * Pe / (2 * VNorm)
451
Tau = 1.0d0 / SQRT( (2.0d0 / dt)**2 + 1.0d0/Tau**2 )
456
!------------------------------------------------------------------------------
457
! Compute residual & stablization vectors
458
!------------------------------------------------------------------------------
462
SU(p) = SU(p) + dBasisdx(p,i) * (Velo(i) + FL * Grad(i) )
467
SW(p) = SW(p) + dBasisdx(p,i) * (Velo(i) + FL * Grad(i) )
473
!------------------------------------------------------------------------------
474
! Loop over basis functions of both unknowns and weights
475
!------------------------------------------------------------------------------
478
!------------------------------------------------------------------------------
480
!------------------------------------------------------------------------------
482
M = Basis(q) * Basis(p)
485
IF(GradAbs > AEPS) THEN
487
A = A + FL * (Grad(i) / GradAbs) * dBasisdx(q,i) * Basis(p)
491
!------------------------------------------------------------------------------
492
! The convection term
493
!------------------------------------------------------------------------------
496
A = A + Velo(i) * dBasisdx(q,i) * Basis(p)
498
!------------------------------------------------------------------------------
499
! Next we add the stabilization...
500
!------------------------------------------------------------------------------
501
IF ( Stabilize ) THEN
502
A = A + Tau * SU(q) * SW(p)
503
M = M + Tau * Basis(q) * SW(p)
506
StiffMatrix(p,q) = StiffMatrix(p,q) + s * A
507
MassMatrix(p,q) = MassMatrix(p,q) + s * M
512
!------------------------------------------------------------------------------
513
! The righthand side...
514
!------------------------------------------------------------------------------
519
IF ( Stabilize ) Load = Load + Tau * SW(p)
520
ForceVector(p) = ForceVector(p) + s * Force * Load
524
!------------------------------------------------------------------------------
525
END SUBROUTINE LocalMatrix
526
!------------------------------------------------------------------------------
529
!------------------------------------------------------------------------------
530
END SUBROUTINE LevelSetSolver
531
!------------------------------------------------------------------------------
536
!------------------------------------------------------------------------------
537
SUBROUTINE LevelSetDistance( Model,Solver,Timestep,TransientSimulation )
538
!------------------------------------------------------------------------------
539
!******************************************************************************
541
! Renormalizes the levelset function using straight-forward geometric search
542
! Also includes an option to do the covection at the same time as an alternavtive
543
! for using a separate solver for the advection.
545
!******************************************************************************
552
!------------------------------------------------------------------------------
554
TYPE(Model_t), TARGET :: Model
555
TYPE(Solver_t) :: Solver
556
REAL(KIND=dp) :: Timestep
557
LOGICAL :: TransientSimulation
559
!------------------------------------------------------------------------------
561
!------------------------------------------------------------------------------
562
TYPE(Nodes_t) :: ElementNodes
563
TYPE(Element_t),POINTER :: CurrentElement, Element
564
TYPE(ValueList_t), POINTER :: Material
565
TYPE(Variable_t), POINTER :: SurfSol, DistanceSol
567
INTEGER :: i,j,k,l,n,t,iter,istat,body_id,mat_id,bf_id,&
568
CoordinateSystem, TimesVisited = 0
569
REAL(KIND=dp) :: Norm,x,y,s,a,b,c,d,x0,x1,y0,y1
570
INTEGER, POINTER :: NodeIndexes(:)
571
LOGICAL :: GotIt, Convect, ExtractAllocated = .FALSE., DistanceAllocated=.FALSE.
572
INTEGER, POINTER :: SurfPerm(:)
573
REAL(KIND=dp), POINTER :: Surface(:),Distance(:), Surf(:)
574
REAL(KIND=dp), ALLOCATABLE :: ZeroNodes(:,:,:), Direction(:)
575
INTEGER, POINTER :: DistancePerm(:)
576
INTEGER :: ZeroLevels, ReinitializeInterval, ExtractInterval
577
LOGICAL :: Reinitialize, Extrct
578
REAL(KIND=dp) :: Relax, dt, r, NarrowBand, DsMax
579
REAL(KIND=dp), ALLOCATABLE :: ElemVelo(:,:), SurfaceFlux(:)
580
REAL(KIND=dp) :: at,totat,st,totst,CPUTime
581
CHARACTER(LEN=MAX_NAME_LEN) :: LevelSetVariableName
583
SAVE ElementNodes, ElemVelo, Direction, ZeroNodes, TimesVisited, &
584
Distance, DistancePerm, ExtractAllocated, DistanceAllocated
586
!------------------------------------------------------------------------------
587
! Get variables needed for solution
588
!------------------------------------------------------------------------------
590
TimesVisited = TimesVisited + 1
591
ReinitializeInterval = ListGetInteger(Solver % Values,&
592
'Reinitialize Interval',GotIt)
593
IF(.NOT. GotIt) ReinitializeInterval = 1
595
ExtractInterval = ListGetInteger(Solver % Values,&
596
'Extract Interval',GotIt)
597
IF(.NOT. GotIt) ExtractInterval = ReinitializeInterval
599
IF( ReinitializeInterval == 0) THEN
600
Reinitialize = .FALSE.
602
Reinitialize = ( MOD(TimesVisited, ReinitializeInterval) == 0 )
605
IF( ExtractInterval == 0) THEN
606
Extrct = Reinitialize
608
Extrct = Reinitialize .OR. ( MOD(TimesVisited, ExtractInterval) == 0 )
611
IF(.NOT. Extrct) THEN
612
CALL Info( 'LevelSetDistance','--------------------------------------', Level=4 )
613
CALL Info( 'LevelSetDistance','Doing nothing this time', Level=4 )
614
CALL Info( 'LevelSetDistance','--------------------------------------', Level=4 )
618
! The variable that should be reinitialized
619
LevelSetVariableName = ListGetString(Solver % Values,'LevelSet Variable',GotIt)
620
IF(.NOT. GotIT) LevelSetVariableName = 'Surface'
621
SurfSol => VariableGet( Solver % Mesh % Variables, TRIM(LevelSetVariableName) )
622
IF(ASSOCIATED(SurfSol)) THEN
623
Surface => SurfSol % Values
624
SurfPerm => SurfSol % Perm
626
CALL Warn('LevelSetDistance','SurfSol does not exist: '//TRIM(LevelSetVariableName))
630
CoordinateSystem = CurrentCoordinateSystem()
631
Convect = ListGetLogical(Solver % Values,'Levelset Convect',GotIt)
632
NarrowBand = ListGetConstReal(Solver % Values,'Narrow Band',GotIt)
633
IF(.NOT. GotIt) NarrowBand = HUGE(NarrowBand)
638
!------------------------------------------------------------------------------
639
! Allocate some permanent storage, this is done first time only
640
!------------------------------------------------------------------------------
641
IF ( .NOT. ExtractAllocated ) THEN
642
N = Solver % Mesh % MaxElementNodes
643
ALLOCATE( ElementNodes % x( N ), ElementNodes % y( N ), ElementNodes % z( N ), &
644
ElemVelo( 2, N), ZeroNodes(Solver % Mesh % NumberOfBulkElements,2,2), &
646
IF ( istat /= 0 ) THEN
647
CALL Fatal( 'LevelSetDistance', 'Memory allocation error 1.' )
650
ALLOCATE( Direction( Solver % Mesh % NumberOfBulkElements), STAT=istat )
652
IF ( istat /= 0 ) THEN
653
CALL Fatal( 'RerormalizeSolver', 'Memory allocation error 2.' )
655
ExtractAllocated = .TRUE.
658
!------------------------------------------------------------------------------
659
! Extract the zero levelset
660
!------------------------------------------------------------------------------
662
CALL Info( 'LevelSetDistance','--------------------------------------', Level=4 )
663
CALL Info( 'LevelSetDistance','Extracting the zero levelset', Level=4 )
664
CALL Info( 'LevelSetDistance','--------------------------------------', Level=4 )
668
CALL ExtractZeroLevel()
671
WRITE(Message,'(a,F8.2)') 'Zero level extracted in time (s):',st
672
CALL Info( 'LevelSetDistance',Message, Level=4 )
674
IF( ZeroLevels == 0) THEN
675
CALL Warn('LevelSetDistance','The does not seem to be a zero level-set present, exiting...')
679
IF(.NOT. Reinitialize) THEN
680
CALL Info('LevelSetDistance','Exiting without reinitialization')
684
CALL Info( 'LevelSetDistance','--------------------------------------', Level=4 )
685
CALL Info( 'LevelSetDistance','Computing the signed distance function', Level=4 )
686
CALL Info( 'LevelSetDistance','--------------------------------------', Level=4 )
688
!------------------------------------------------------------------------------
689
! Allocate some permanent storage for computing the signed distance
690
!------------------------------------------------------------------------------
691
IF ( .NOT. DistanceAllocated ) THEN
693
! The variable for computing the distance
694
DistanceSol => Solver % Variable
695
IF(ASSOCIATED(DistanceSol)) THEN
696
DistancePerm => DistanceSol % Perm
697
Distance => DistanceSol % Values
699
ALLOCATE(Distance (SIZE(Surface)),STAT=istat)
700
IF ( istat /= 0 ) THEN
701
CALL Fatal( 'LevelSetDistance', 'Memory allocation error 1.' )
703
DistancePerm => SurfPerm
705
DistanceAllocated = .TRUE.
708
!------------------------------------------------------------------------------
709
! Compute the signed distance
710
!------------------------------------------------------------------------------
713
DO i=1,Solver % Mesh % NumberOfNodes
714
Distance(DistancePerm(i)) = ComputeDistanceWithDirection( Solver % Mesh % Nodes % x(i), &
715
Solver % Mesh % Nodes % y(i), 0.0d0, Surface(i) )
718
DO i=1,Solver % Mesh % NumberOfNodes
719
Distance(DistancePerm(i)) = ComputeDistance( Solver % Mesh % Nodes % x(i), &
720
Solver % Mesh % Nodes % y(i), 0.0d0 )
722
WHERE( Surface < 0 ) Distance = -Distance
725
n = Solver % Mesh % NumberOfNodes
726
Solver % Variable % Norm = SQRT( SUM(Distance**2)/n )
728
!------------------------------------------------------------------------------
729
! Apply the reinitialization to the primary levelset field
730
!------------------------------------------------------------------------------
732
IF( ListGetLogical(Solver % Values,'Reinitialize Passive',GotIt) ) THEN
733
CALL Info('LevelSetDistance','Reinitialization not applied to Levelset function')
735
! Update also the previous timesteps so that the differentials remain
736
! unchanged. Otherwise spurious effects are introduced.
737
IF(ASSOCIATED(SurfSol % PrevValues)) THEN
738
j = MIN(2, SIZE(SurfSol % PrevValues,2) )
739
IF( ReinitializeInterval > j) THEN
741
SurfSol % PrevValues(:,i) = SurfSol % PrevValues(:,i) + Distance - Surface
749
WRITE(Message,'(a,F8.2)') 'Reinitialization done in time (s):',st
750
CALL Info( 'LevelSetNormalize',Message, Level=4 )
753
WRITE(Message,'(a,ES12.3)') 'Maximum Levelset Change',dsmax
754
CALL Info( 'LevelSetDistance',Message, Level=4 )
755
CALL ListAddConstReal(Model % Simulation,'res: LevelSet Max Change',dsmax)
758
!------------------------------------------------------------------------------
763
!------------------------------------------------------------------------------
764
SUBROUTINE ExtractZeroLevel()
765
!------------------------------------------------------------------------------
767
INTEGER :: i,j,k,n,div,onetwo,corners, &
768
TriangleIndexes(3), mat_id, body_id, LocalInd(3)
769
TYPE(Variable_t), POINTER :: Var
770
INTEGER, POINTER :: NodeIndexes(:)
771
TYPE(Element_t), POINTER :: Element
772
REAL(KIND=dp) :: x0,y0,x1,y1,t,nx(3),ny(3),nz(3),srf(3),w0(3),w1(3),Value,dt, &
773
r1x, r1y, r2x, r2y, aid, Maxsrf, ds1, ds2
774
LOGICAL :: FileCreated = .FALSE., FileAppend, GotIt, FileSave, Found
775
TYPE(ValueList_t),POINTER :: Material
776
CHARACTER(LEN=MAX_NAME_LEN) :: Filename, Filename2
779
!------------------------------------------------------------------------------
781
Filename = ListGetString(Solver % Values,'Filename',FileSave )
784
IF(.NOT. FileCreated) THEN
785
OPEN (10, FILE=TRIM(Filename)//TRIM(".names") )
786
WRITE(10,'(A,A)') 'Variables in file: ',TRIM(Filename)
788
WRITE(10,'(I3,": ",A)') j,'timestep'
790
Var => Model % Variables
791
DO WHILE( ASSOCIATED( Var ) )
792
IF ( .NOT. Var % Output .OR. SIZE(Var % Values) == 1 .OR. (Var % DOFs /= 1) ) THEN
797
WRITE(10,'(I3,": ",A)') j,TRIM(Var % Name)
803
FileAppend = ListGetLogical(Solver % Values,'File Append',GotIt)
804
IF(FileCreated .AND. FileAppend) THEN
805
OPEN (10, FILE=Filename,POSITION='APPEND')
807
OPEN (10,FILE=Filename)
812
Surface => SurfSol % Values
813
SurfPerm => SurfSol % Perm
816
DO i=1,Solver % Mesh % NumberOfBulkElements
818
Element => Solver % Mesh % Elements(i)
819
n = Element % TYPE % NumberOfNodes
820
NodeIndexes => Element % NodeIndexes
822
IF ( ALL( Surface(SurfPerm(NodeIndexes)) < 0) .OR. &
823
ALL( Surface(SurfPerm(NodeIndexes)) > 0) ) CYCLE
825
corners = Element % TYPE % ElementCode / 100
826
IF(corners < 3 .OR. corners > 4) THEN
827
CALL Warn('ExtractZeroLevel','Implemented only for triangles and quads')
831
Model % CurrentElement => Element
833
body_id = Element % BodyId
834
mat_id = ListGetInteger( Model % Bodies(body_id) % Values, 'Material', &
835
minv=1, maxv=Model % NumberOfMaterials )
836
Material => Model % Materials(mat_id) % Values
838
ElemVelo(1,1:n) = ListGetReal( Material,'Levelset Velocity 1',n,NodeIndexes,GotIt)
839
ElemVelo(2,1:n) = ListGetReal( Material,'Levelset Velocity 2',n,NodeIndexes,GotIt)
845
SELECT CASE (corners)
864
TriangleIndexes = NodeIndexes(LocalInd)
865
srf = Surface(SurfPerm(TriangleIndexes))
866
IF ( ALL(srf < 0) .OR. ALL( srf > 0) ) CYCLE
868
nx = Solver % Mesh % Nodes % x(TriangleIndexes)
869
ny = Solver % Mesh % Nodes % y(TriangleIndexes)
870
nz = Solver % Mesh % Nodes % z(TriangleIndexes)
872
CALL TriangleIsoLineWeights( nx,ny,nz,srf,w0,w1,found)
873
IF( .NOT. Found) CYCLE
883
ds1 = SQRT( r1x*r1x + r1y*r1y)
886
ZeroLevels = ZeroLevels + 1
890
! Find the value that differs most from the zero levelset
894
IF(ABS(srf(k)) > ABS(Maxsrf)) THEN
903
aid = r1x * r2y - r2x * r1y
904
ds2 = SQRT( r2x*r2x + r2y*r2y)
906
Direction( ZeroLevels ) = aid / (ds1 * ds2)
907
IF( Maxsrf < 0.0) THEN
908
Direction( ZeroLevels ) = -Direction( ZeroLevels )
911
r1x = SUM(w0 * ElemVelo(1,LocalInd)) * dt
912
r1y = SUM(w0 * ElemVelo(2,LocalInd)) * dt
913
r2x = SUM(w1 * ElemVelo(1,LocalInd)) * dt
914
r2y = SUM(w1 * ElemVelo(2,LocalInd)) * dt
916
ds1 = SQRT( r1x*r1x + r1y*r1y)
917
ds2 = SQRT( r2x*r2x + r2y*r2y)
918
dsmax = MAX(dsmax, MAX(ds1, ds2) )
920
ZeroNodes(ZeroLevels,1,1) = x0 + r1x
921
ZeroNodes(ZeroLevels,1,2) = y0 + r1y
922
ZeroNodes(ZeroLevels,2,1) = x1 + r2x
923
ZeroNodes(ZeroLevels,2,2) = y1 + r2y
925
ZeroNodes(ZeroLevels,1,1) = x0
926
ZeroNodes(ZeroLevels,1,2) = y0
927
ZeroNodes(ZeroLevels,2,1) = x1
928
ZeroNodes(ZeroLevels,2,2) = y1
936
WRITE(10,'(I4)',ADVANCE='NO') Solver % DoneTime
938
Var => Model % Variables
939
DO WHILE( ASSOCIATED( Var ) )
941
IF ( .NOT. Var % Output .OR. SIZE(Var % Values) == 1 .OR. (Var % DOFs /= 1) ) THEN
948
l = TriangleIndexes(k)
949
IF ( ASSOCIATED(Var % Perm) ) l = Var % Perm(l)
952
Value = Value + w0(k) * (Var % Values(l))
954
Value = Value + w1(k) * (Var % Values(l))
959
WRITE(10,'(ES20.11E3)',ADVANCE='NO') Value
975
!------------------------------------------------------------------------------
976
END SUBROUTINE ExtractZeroLevel
977
!------------------------------------------------------------------------------
980
!------------------------------------------------------------------------------
981
SUBROUTINE TriangleIsoLineWeights( NX,NY,NZ,S,w0,w1,Found )
982
!------------------------------------------------------------------------------
983
! This subroutine extracts the zero line of one triangular element
984
!------------------------------------------------------------------------------
986
REAL(KIND=dp) :: NX(:),NY(:),NZ(:),S(:),w0(3),w1(3)
989
!------------------------------------------------------------------------------
996
IF ( ABS(S(1)) < AEPS .AND. ABS(S(2)) < AEPS ) THEN
999
ELSE IF ( ABS(S(1)) < AEPS .AND. ABS(S(3)) < AEPS ) THEN
1002
ELSE IF ( ABS(S(2)) < AEPS .AND. ABS(S(3)) < AEPS ) THEN
1005
ELSE IF ( ALL(S <= 0) .OR. ALL( S >= 0) ) THEN
1008
IF ( S(1) >= 0 .AND. S(2) >= 0 .OR. &
1009
S(1) <= 0 .AND. S(2) <= 0 ) THEN
1010
t = -S(1) / ( S(3) - S(1) )
1013
t = -S(2) / ( S(3) - S(2) )
1016
ELSE IF ( S(1) >= 0 .AND. S(3) >= 0 .OR. &
1017
S(1) <= 0 .AND. S(3) <= 0 ) THEN
1018
t = -S(1) / ( S(2) - S(1) )
1021
t = -S(3) / ( S(2) - S(3) )
1025
ELSE IF ( S(2) >= 0 .AND. S(3) >= 0 .OR. &
1026
S(2) <= 0 .AND. S(3) <= 0 ) THEN
1027
t = -S(2) / ( S(1) - S(2) )
1030
t = -S(3) / ( S(1) - S(3) )
1034
PRINT *,'TriangleIsoLineWeights: this should not occur'
1035
PRINT *,s(1),s(2),s(3)
1039
!------------------------------------------------------------------------------
1040
END SUBROUTINE TriangleIsoLineWeights
1041
!------------------------------------------------------------------------------
1044
!------------------------------------------------------------------------------
1045
FUNCTION ComputeDistance(xp,yp,zp) RESULT(dist)
1046
!------------------------------------------------------------------------------
1047
! Computes the distance from the given zero levelset given by ZeroNodes.
1048
!------------------------------------------------------------------------------
1049
REAL(KIND=dp) :: xp,yp,zp,dist
1050
!------------------------------------------------------------------------------
1051
REAL(KIND=dp) :: x0,y0,x1,y1,a,b,c,d,s
1053
!------------------------------------------------------------------------------
1056
x0 = ZeroNodes(i,1,1)
1057
y0 = ZeroNodes(i,1,2)
1059
x1 = ZeroNodes(i,2,1)
1060
y1 = ZeroNodes(i,2,2)
1070
IF ( s > 10*AEPS ) THEN
1071
s = MIN( MAX( -(a*b + c*d) / s, 0.0d0), 1.0d0 )
1072
x = (1-s) * x0 + s * x1
1073
y = (1-s) * y0 + s * y1
1076
dist = MIN( dist, SQRT( (xp - x)**2 + (yp - y)**2 ) )
1078
!------------------------------------------------------------------------------
1079
END FUNCTION ComputeDistance
1080
!------------------------------------------------------------------------------
1083
!------------------------------------------------------------------------------
1084
FUNCTION ComputeDistanceWithDirection(xp,yp,zp,prevdist) RESULT(mindist)
1085
!------------------------------------------------------------------------------
1086
! Computes the distance from the given zero levelset given by ZeroNodes.
1087
!------------------------------------------------------------------------------
1088
REAL(KIND=dp) :: xp,yp,zp,prevdist,mindist
1089
!------------------------------------------------------------------------------
1090
REAL(KIND=dp) :: x0,y0,x1,y1,a,b,c,d,s,dist,r1x,r1y,r2x,r2y,angle,angle0
1092
!------------------------------------------------------------------------------
1094
IF(prevdist - dsmax > narrowband) THEN
1095
mindist = prevdist - dsmax
1097
ELSE IF(prevdist + dsmax < -narrowband) THEN
1098
mindist = prevdist + dsmax
1102
mindist = HUGE(mindist)
1105
x0 = ZeroNodes(i,1,1)
1106
y0 = ZeroNodes(i,1,2)
1108
x1 = ZeroNodes(i,2,1)
1109
y1 = ZeroNodes(i,2,2)
1119
IF ( s > 10*AEPS ) THEN
1120
s = MIN( MAX( -(a*b + c*d) / s, 0.0d0), 1.0d0 )
1121
x = (1-s) * x0 + s * x1
1122
y = (1-s) * y0 + s * y1
1125
dist = SQRT( (xp - x)**2 + (yp - y)**2 )
1128
IF(dist <= (ABS(mindist) + AEPS) ) THEN
1135
angle = r1x * r2y - r2x * r1y
1137
! Favor parents with clear angles
1138
IF( dist < (ABS(mindist) - AEPS) .OR. (ABS(angle) > ABS(angle0)) ) THEN
1139
IF(Direction(i) * angle < 0.0) THEN
1150
!------------------------------------------------------------------------------
1151
END FUNCTION ComputeDistanceWithDirection
1152
!------------------------------------------------------------------------------
1156
!------------------------------------------------------------------------------
1157
FUNCTION Solve3rd( Element,Nodes,n,dist,which ) RESULT(val)
1158
!------------------------------------------------------------------------------
1160
REAL(KIND=dp) :: dist(3),val
1162
TYPE(Nodes_t) :: Nodes
1163
TYPE(Element_t), POINTER :: Element
1164
!------------------------------------------------------------------------------
1166
REAL(KIND=dp) :: Basis(n), dBasisdx(n,3), ddBasisddx(1,1,1), detJ, &
1167
a,b,c,dx,dy,s,s1,s2,t,u,x0,x1,y0,y1,cosp,ta,tb
1171
!------------------------------------------------------------------------------
1173
stat = ElementInfo( Element, Nodes, 1.0d0/3.0d0, 1.0d0/3.0d0, 0.0d0, &
1174
detJ, Basis, dBasisdx, ddBasisddx, .FALSE., .FALSE. )
1179
IF ( i /= Which ) THEN
1180
dx = dx + dBasisdx(i,1) * dist(i)
1181
dy = dy + dBasisdx(i,2) * dist(i)
1185
a = dBasisdx(Which,1)**2 + dBasisdx(Which,2)**2
1186
b = 2*( dBasisdx(Which,1) * dx + dBasisdx(Which,2) * dy )
1187
c = dx**2 + dy**2 - 1
1191
IF ( s < -1.0d-10 ) THEN
1199
s1 = 2*c/(-b-SQRT(s))
1200
s2 = (-b-SQRT(s))/(2*a)
1202
s1 = (-b+SQRT(s))/(2*a)
1203
s2 = 2*c/(-b+SQRT(s))
1212
x0 = Nodes % x(2) - Nodes % x(1)
1213
y0 = Nodes % y(2) - Nodes % y(1)
1215
x1 = Nodes % x(3) - Nodes % x(1)
1216
y1 = Nodes % y(3) - Nodes % y(1)
1218
ta = Dist(2); tb = Dist(3)
1220
x0 = Nodes % x(1) - Nodes % x(2)
1221
y0 = Nodes % y(1) - Nodes % y(2)
1223
x1 = Nodes % x(3) - Nodes % x(2)
1224
y1 = Nodes % y(3) - Nodes % y(2)
1226
ta = Dist(1); tb = Dist(3)
1228
x0 = Nodes % x(1) - Nodes % x(3)
1229
y0 = Nodes % y(1) - Nodes % y(3)
1231
x1 = Nodes % x(2) - Nodes % x(3)
1232
y1 = Nodes % y(2) - Nodes % y(3)
1233
ta = Dist(1); tb = Dist(2)
1236
a = SQRT( x0**2 + y0**2 )
1237
b = SQRT( x1**2 + y1**2 )
1239
dx = dx + dBasisdx(Which,1) * val
1240
dy = dy + dBasisdx(Which,2) * val
1241
s = SQRT(dx**2 + dy**2)
1243
s1 = (x0*y1 - y0*x1) / (a*b)
1244
s2 = -(x0*dy - y0*dx) / (s*a)
1251
IF ( s2 < 0 .OR. s2 > s1 ) THEN
1252
val = MIN( a + ta, b + tb )
1254
!------------------------------------------------------------------------------
1255
END FUNCTION Solve3rd
1256
!------------------------------------------------------------------------------
1258
!------------------------------------------------------------------------------
1259
END SUBROUTINE LevelSetDistance
1260
!------------------------------------------------------------------------------
1265
!------------------------------------------------------------------------------
1266
SUBROUTINE LevelSetIntegrate( Model,Solver,Timestep,TransientSimulation )
1267
!------------------------------------------------------------------------------
1268
!******************************************************************************
1270
! Compute the volume and area in 3D or area and line intgral in 2D over the
1271
! levelset function. This is better done within a dedicated solver since
1272
! it is crucial for the accuracy that the Heaviside and Delta function are
1273
! computed at Gaussian integration points.
1275
!******************************************************************************
1281
!------------------------------------------------------------------------------
1283
TYPE(Model_t), TARGET :: Model
1284
TYPE(Solver_t) :: Solver
1285
REAL(KIND=dp) :: Timestep
1286
LOGICAL :: TransientSimulation
1288
!------------------------------------------------------------------------------
1290
!------------------------------------------------------------------------------
1291
TYPE(Nodes_t) :: ElementNodes
1292
TYPE(Element_t),POINTER :: CurrentElement
1293
TYPE(ValueList_t), POINTER :: Material
1294
TYPE(Variable_t), POINTER :: SurfSol
1296
INTEGER :: i,j,k,n,t,istat,bf_id
1297
INTEGER, POINTER :: NodeIndexes(:), SurfPerm(:)
1298
LOGICAL :: Visited = .FALSE., GotIt
1299
REAL(KIND=dp), POINTER :: Surface(:), NodalSurf(:)
1300
INTEGER :: body_id, dim
1301
REAL(KIND=dp) :: TotVolume, TotArea, Alpha, Relax, InitVolume, dSurface, dt, &
1303
CHARACTER(LEN=MAX_NAME_LEN) :: LevelSetVariableName
1305
SAVE ElementNodes, Visited, NodalSurf, InitVolume
1307
!------------------------------------------------------------------------------
1308
! Get variables needed for solution
1309
!------------------------------------------------------------------------------
1311
! The variable that should be renormalized
1312
LevelSetVariableName = ListGetString(Solver % Values,'Level Set Variable',GotIt)
1314
SurfSol => VariableGet( Solver % Mesh % Variables, TRIM(LevelSetVariableName) )
1316
SurfSol => VariableGet( Solver % Mesh % Variables, 'Surface' )
1318
IF(ASSOCIATED(SurfSol)) THEN
1319
Surface => SurfSol % Values
1320
SurfPerm => SurfSol % Perm
1322
CALL Warn('LevelSetIntegrate','Surface variable does not exist')
1325
IF ( ALL( SurfPerm == 0) ) THEN
1326
CALL Warn('LevelSetIntegrate','Nothing to compute')
1330
dim = CoordinateSystemDimension()
1332
!------------------------------------------------------------------------------
1333
! Allocate some permanent storage, this is done first time only
1334
!------------------------------------------------------------------------------
1335
IF ( .NOT. Visited ) THEN
1336
N = Solver % Mesh % MaxElementNodes
1338
ALLOCATE( NodalSurf( N ), &
1339
ElementNodes % x( N ), &
1340
ElementNodes % y( N ), &
1341
ElementNodes % z( N ), &
1344
IF ( istat /= 0 ) THEN
1345
CALL Fatal( 'LevelSetIntegrate', 'Memory allocation error.' )
1348
!------------------------------------------------------------------------------
1349
! Do some additional initialization, and go for it
1350
!------------------------------------------------------------------------------
1356
Alpha = ListGetConstReal(Model % Simulation,'Levelset Bandwidth',GotIt)
1357
IF(.NOT. GotIt) Alpha = ListGetConstReal(Solver % Values,'Levelset Bandwidth')
1359
CALL Info( 'LevelSetIntegrate','-------------------------------------', Level=4 )
1360
CALL Info( 'LevelSetIntegrate', 'Integrating over levelset function', Level=4 )
1361
CALL Info( 'LevelSetIntegrate','-------------------------------------', Level=4 )
1363
DO t=1,Solver % Mesh % NumberOfBulkElements
1365
CurrentElement => Solver % Mesh % Elements(t)
1366
n = CurrentElement % TYPE % NumberOfNodes
1367
NodeIndexes => CurrentElement % NodeIndexes
1368
IF( ANY(SurfPerm(NodeIndexes) == 0)) CYCLE
1370
Model % CurrentElement => CurrentElement
1371
body_id = CurrentElement % Bodyid
1372
k = ListGetInteger( Model % Bodies( body_id ) % Values, 'Material' )
1373
Material => Model % Materials(k) % Values
1375
!-----------------------------------------------------------------------------
1376
! Get element nodal coordinates
1377
!------------------------------------------------------------------------------
1378
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
1379
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
1380
ElementNodes % z(1:n) = Solver % Mesh % Nodes % z(NodeIndexes)
1382
NodalSurf = Surface( SurfPerm(NodeIndexes) )
1384
CALL HeavisideIntegrate( NodalSurf, CurrentElement, n, ElementNodes, &
1385
Alpha, TotVolume, TotArea, Moment)
1388
Moment = Moment / TotVolume
1391
WRITE(Message,'(a,ES12.3)') 'Center 3',Moment(3)
1392
CALL Info( 'LevelSetIntegrate',Message, Level=4 )
1394
WRITE(Message,'(a,ES12.3)') 'Inside Volume',TotVolume
1395
CALL Info( 'LevelSetIntegrate',Message, Level=4 )
1397
WRITE(Message,'(a,ES12.3)') 'Interface Area',TotArea
1398
CALL Info( 'LevelSetIntegrate',Message, Level=4 )
1400
CALL ListAddConstReal(Model % Simulation,'res: LevelSet Center 3',Moment(3))
1401
CALL ListAddConstReal(Model % Simulation,'res: LevelSet Volume',TotVolume)
1402
CALL ListAddConstReal(Model % Simulation,'res: LevelSet Area',TotArea)
1404
WRITE(Message,'(a,ES12.3)') 'Inside Area',TotVolume
1405
CALL Info( 'LevelSetIntegrate',Message, Level=4 )
1407
WRITE(Message,'(a,ES12.3)') 'Interface length',TotArea
1408
CALL Info( 'LevelSetIntegrate',Message, Level=4 )
1410
CALL ListAddConstReal(Model % Simulation,'res: LevelSet Area',TotVolume)
1411
CALL ListAddConstReal(Model % Simulation,'res: LevelSet Length',TotArea)
1414
WRITE(Message,'(a,ES12.3)') 'Center 2',Moment(2)
1415
CALL Info( 'LevelSetIntegrate',Message, Level=4 )
1417
WRITE(Message,'(a,ES12.3)') 'Center 1',Moment(1)
1418
CALL Info( 'LevelSetIntegrate',Message, Level=4 )
1420
CALL ListAddConstReal(Model % Simulation,'res: LevelSet Center 2',Moment(2))
1421
CALL ListAddConstReal(Model % Simulation,'res: LevelSet Center 1',Moment(1))
1423
IF ( ListGetLogical(Solver % Values,'Conserve Volume',GotIt) ) THEN
1424
IF(.NOT. Visited) THEN
1425
InitVolume = ListGetConstReal(Solver % Values,'Initial Volume',GotIt)
1426
IF(.NOT. GotIt) InitVolume = TotVolume
1429
Relax = ListGetConstReal(Solver % Values,'Conserve Volume Relaxation',GotIt)
1430
IF(.NOT. GotIt) Relax = 1.0d0
1432
dSurface = Relax * (InitVolume - TotVolume) / TotArea
1433
IF(ABS(dSurface) > AEPS) THEN
1434
Surface = Surface + dSurface
1437
WRITE(Message,'(a,ES12.3)') 'Levelset correction',dSurface
1438
CALL Info( 'LevelSetIntegrate',Message, Level=4 )
1439
CALL ListAddConstReal(Model % Simulation,'res: Levelset Correction',dSurface)
1445
!------------------------------------------------------------------------------
1449
!------------------------------------------------------------------------------
1450
SUBROUTINE HeavisideIntegrate( Surf,Element,n,Nodes,Alpha,Volume,Area,Moment)
1451
!------------------------------------------------------------------------------
1453
REAL(KIND=dp), DIMENSION(:) :: Surf
1455
TYPE(Nodes_t) :: Nodes
1456
TYPE(Element_t), POINTER :: Element
1457
REAL(KIND=dp) :: Alpha, Volume, Area, Moment(3)
1459
!------------------------------------------------------------------------------
1461
!------------------------------------------------------------------------------
1463
REAL(KIND=dp) :: Basis(n)
1464
REAL(KIND=dp) :: dBasisdx(n,3),detJ
1465
REAL(KIND=dp) :: Val,Grad(3),Velo(3),NormalVelo,GradAbs,Heavi,Delta
1466
INTEGER :: t,N_Integ, CoordinateSystem
1467
REAL(KIND=dp) :: s,u,v,w,x,y,z
1468
TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff
1469
REAL(KIND=dp), DIMENSION(:), POINTER :: U_Integ,V_Integ,W_Integ,S_Integ
1472
!------------------------------------------------------------------------------
1474
dim = CoordinateSystemDimension()
1475
CoordinateSystem = CurrentCoordinateSystem()
1477
!------------------------------------------------------------------------------
1479
!------------------------------------------------------------------------------
1480
IntegStuff = GaussPoints( element )
1482
U_Integ => IntegStuff % u
1483
V_Integ => IntegStuff % v
1484
W_Integ => IntegStuff % w
1485
S_Integ => IntegStuff % s
1486
N_Integ = IntegStuff % n
1488
!------------------------------------------------------------------------------
1489
! Now we start integrating
1490
!------------------------------------------------------------------------------
1497
!------------------------------------------------------------------------------
1498
! Basis function values & derivatives at the integration point
1499
!------------------------------------------------------------------------------
1500
stat = ElementInfo( Element,Nodes,u,v,w,detJ, Basis,dBasisdx)
1502
s = detJ * S_Integ(t)
1504
x = SUM( Nodes % x(1:n) * Basis(1:n) )
1505
y = SUM( Nodes % y(1:n) * Basis(1:n) )
1506
IF(dim == 3) z = SUM( Nodes % z(1:n) * Basis(1:n) )
1508
!------------------------------------------------------------------------------
1509
! Coordinatesystem dependent info
1510
!------------------------------------------------------------------------------
1511
IF ( CoordinateSystem == AxisSymmetric .OR. CoordinateSystem == CylindricSymmetric ) THEN
1512
s = s * x * 2.0d0 * PI
1515
!------------------------------------------------------------------------------
1516
Val = SUM( Basis(1:n) * Surf(1:n) )
1518
IF( Val < -Alpha) THEN
1520
ELSE IF(Val > Alpha) THEN
1523
Heavi = (1.0d0 + SIN( (Val/Alpha) * (PI/2) ) ) / 2.0d0
1524
Delta = (1.0d0 + COS( (Val/Alpha) * PI ) ) / (2.0d0 * Alpha)
1527
Grad(i) = SUM( dBasisdx(1:n,i) * Surf(1:n) )
1529
GradAbs = SQRT( SUM( Grad(1:dim) * Grad(1:dim) ) )
1531
Area = Area + s * Delta * GradAbs
1534
Volume = Volume + s * Heavi
1535
Moment(1) = Moment(1) + s * Heavi * x
1536
Moment(2) = Moment(2) + s * Heavi * y
1537
IF(dim == 3) Moment(3) = Moment(3) + s * Heavi * z
1541
!------------------------------------------------------------------------------
1542
END SUBROUTINE HeavisideIntegrate
1543
!------------------------------------------------------------------------------
1545
END SUBROUTINE LevelSetIntegrate
1546
!------------------------------------------------------------------------------
1550
!------------------------------------------------------------------------------
1551
SUBROUTINE LevelSetCurvature( Model,Solver,Timestep,TransientSimulation )
1552
!------------------------------------------------------------------------------
1553
!******************************************************************************
1555
! Computes the curvature from the level set function. Additional diffusion may
1556
! be added in order to limit the singular curvature peaks.
1558
!******************************************************************************
1563
!------------------------------------------------------------------------------
1565
TYPE(Model_t), TARGET :: Model
1566
TYPE(Solver_t) :: Solver
1567
REAL(KIND=dp) :: Timestep
1568
LOGICAL :: TransientSimulation
1570
!------------------------------------------------------------------------------
1572
!------------------------------------------------------------------------------
1573
TYPE(Matrix_t),POINTER :: StiffMatrix
1574
TYPE(Nodes_t) :: ElementNodes, ParentNodes
1575
TYPE(Element_t),POINTER :: Element, Parent
1576
TYPE(Variable_t), POINTER :: SurfSol
1578
INTEGER :: i,j,k,n,pn,t,istat,bf_id,CoordinateSystem
1579
REAL(KIND=dp) :: Norm, Coeff, Diff, Alpha, Val, Delta
1580
INTEGER, POINTER :: NodeIndexes(:)
1581
INTEGER, POINTER :: CurvPerm(:), SurfPerm(:)
1582
REAL(KIND=dp), POINTER :: Curvature(:),ForceVector(:), Curv(:),Surface(:)
1583
REAL(KIND=dp), ALLOCATABLE :: LocalStiffMatrix(:,:),LocalForce(:),Surf(:)
1584
REAL(KIND=dp) :: at,totat,st,totst,CPUTime
1585
CHARACTER(LEN=MAX_NAME_LEN) :: LevelSetVariableName
1586
LOGICAL :: GotIt, Stat, AllocationsDone = .FALSE.
1588
SAVE LocalStiffMatrix,LocalForce, ElementNodes,ParentNodes,Surf,AllocationsDone
1590
!------------------------------------------------------------------------------
1591
! Get variables needed for solution
1592
!------------------------------------------------------------------------------
1593
IF ( .NOT. ASSOCIATED( Solver % Matrix ) ) RETURN
1595
CoordinateSystem = CurrentCoordinateSystem()
1597
Curvature => Solver % Variable % Values
1598
CurvPerm => Solver % Variable % Perm
1599
IF ( SIZE( Curvature ) == 0 ) RETURN
1601
LevelSetVariableName = ListGetString(Solver % Values,'LevelSet Variable',GotIt)
1603
SurfSol => VariableGet( Solver % Mesh % Variables, TRIM(LevelSetVariableName) )
1605
SurfSol => VariableGet( Solver % Mesh % Variables, 'Surface' )
1607
Surface => Surfsol % Values
1608
SurfPerm => SurfSol % Perm
1610
StiffMatrix => Solver % Matrix
1611
ForceVector => StiffMatrix % RHS
1612
Norm = Solver % Variable % Norm
1614
Diff = ListGetConstReal(Solver % Values,'Curvature Diffusion',GotIt)
1616
!------------------------------------------------------------------------------
1617
! Allocate some permanent storage, this is done first time only
1618
!------------------------------------------------------------------------------
1619
IF ( .NOT. AllocationsDone ) THEN
1620
N = Solver % Mesh % MaxElementNodes
1622
ALLOCATE( ElementNodes % x( N ), &
1623
ElementNodes % y( N ), &
1624
ElementNodes % z( N ), &
1625
ParentNodes % x( N ), &
1626
ParentNodes % y( N ), &
1627
ParentNodes % z( N ), &
1629
LocalStiffMatrix( N, N ), &
1633
IF ( istat /= 0 ) THEN
1634
CALL Fatal( 'CurvatureSolve', 'Memory allocation error.' )
1637
AllocationsDone = .TRUE.
1639
!------------------------------------------------------------------------------
1640
! Do some additional initialization, and go for it
1641
!------------------------------------------------------------------------------
1648
CALL Info( 'LevelSetCurvature','-------------------------------------', Level=4 )
1649
CALL Info( 'LevelSetCurvature','Solving Level set curvature', Level=4 )
1650
CALL Info( 'LevelSetCurvature','-------------------------------------', Level=4 )
1652
CALL InitializeToZero( StiffMatrix, ForceVector )
1654
!------------------------------------------------------------------------------
1655
! Do the assembly for bulk elements
1656
!------------------------------------------------------------------------------
1658
DO t=1,Solver % NumberOfActiveElements
1660
Element => Solver % Mesh % Elements(Solver % ActiveElements(t))
1661
n = Element % TYPE % NumberOfNodes
1662
NodeIndexes => Element % NodeIndexes
1664
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
1665
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
1666
ElementNodes % z(1:n) = Solver % Mesh % Nodes % z(NodeIndexes)
1668
Surf = Surface( SurfPerm(NodeIndexes) )
1670
CALL LocalMatrix( LocalStiffMatrix, LocalForce, &
1671
Surf, Element, n, ElementNodes )
1673
CALL UpdateGlobalEquations( StiffMatrix, LocalStiffMatrix, &
1674
ForceVector, LocalForce, n, 1, CurvPerm(NodeIndexes) )
1678
!------------------------------------------------------------------------------
1679
! Do the assembly for boundary elements
1680
!------------------------------------------------------------------------------
1682
DO t=Solver % Mesh % NumberOfBulkElements + 1, &
1683
Solver % Mesh % NumberOfBulkElements + &
1684
Solver % Mesh % NumberOfBoundaryElements
1686
Element => Solver % Mesh % Elements(t)
1687
!------------------------------------------------------------------------------
1688
DO i=1,Model % NumberOfBCs
1689
IF ( Element % BoundaryInfo % Constraint == Model % BCs(i) % Tag ) THEN
1691
n = Element % TYPE % NumberOfNodes
1692
NodeIndexes => Element % NodeIndexes
1693
IF ( ANY( CurvPerm(NodeIndexes) <= 0 ) ) CYCLE
1695
IF ( Element % TYPE % ElementCode == 101 ) CYCLE
1697
IF ( .NOT. ListGetLogical(Model % BCs(i) % Values, &
1698
'Levelset Curvature BC',gotIt) ) CYCLE
1700
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
1701
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
1702
ElementNodes % z(1:n) = Solver % Mesh % Nodes % z(NodeIndexes)
1704
Parent => Element % BoundaryInfo % Left
1706
stat = ASSOCIATED( Parent )
1707
IF ( stat ) stat = stat .AND. ALL(CurvPerm(Parent % NodeIndexes) > 0)
1709
IF ( .NOT. stat ) THEN
1710
Parent => Element % BoundaryInfo % Right
1712
stat = ASSOCIATED( Parent )
1713
IF ( stat ) stat = ALL(CurvPerm(Parent % NodeIndexes(1:pn)) > 0)
1715
IF ( .NOT. stat ) THEN
1716
CALL Warn( 'LevelSetCurvature', &
1717
'No curvature solution available for specified boundary' )
1722
pn = Parent % TYPE % NumberOfNodes
1723
ParentNodes % x(1:pn) = Solver % Mesh % Nodes % x(Parent % NodeIndexes)
1724
ParentNodes % y(1:pn) = Solver % Mesh % Nodes % y(Parent % NodeIndexes)
1725
ParentNodes % z(1:pn) = Solver % Mesh % Nodes % z(Parent % NodeIndexes)
1727
Surf(1:pn) = Surface(SurfPerm(Parent % NodeIndexes))
1729
!------------------------------------------------------------------------------
1730
! Get element matrix and rhs due to boundary conditions ...
1731
!------------------------------------------------------------------------------
1733
CALL LocalBoundary( LocalStiffMatrix, LocalForce, &
1734
Surf, Element, Parent, n, pn, ElementNodes, ParentNodes )
1735
!------------------------------------------------------------------------------
1736
! Update global matrices from local matrices
1737
!------------------------------------------------------------------------------
1738
CALL UpdateGlobalEquations( StiffMatrix, LocalStiffMatrix, &
1739
ForceVector, LocalForce, n, 1, CurvPerm(NodeIndexes) )
1740
!------------------------------------------------------------------------------
1744
!------------------------------------------------------------------------------
1746
CALL FinishAssembly( Solver,ForceVector )
1749
WRITE(Message,'(a,F8.2)') 'Assembly done in time (s):',at
1750
CALL Info( 'LevelSetCurvature',Message, Level=4 )
1752
!------------------------------------------------------------------------------
1753
! Solve the system and we are done.
1754
!------------------------------------------------------------------------------
1756
CALL SolveSystem( StiffMatrix, ParMatrix, ForceVector, &
1757
Curvature, Norm, 1, Solver )
1760
WRITE(Message,'(a,F8.2)') 'Solution done in time (s):',st
1761
CALL Info( 'LevelSetCurvature',Message, Level=4 )
1763
!------------------------------------------------------------------------------
1765
Coeff = ListGetConstReal(Solver % Values,'Curvature Coefficient',GotIt)
1767
Curvature = Coeff * Curvature
1770
Alpha = ListGetConstReal(Model % Simulation,'Levelset Bandwidth',GotIt)
1771
IF(.NOT. GotIt) Alpha = ListGetConstReal(Solver % Values,'Levelset Bandwidth',GotIt)
1773
DO i=1,SIZE(CurvPerm)
1776
IF(j == 0 .OR. k == 0) CYCLE
1779
IF( Val < -Alpha) THEN
1781
ELSE IF(Val > Alpha) THEN
1784
Delta = (1.0d0 + COS( (Val/Alpha) * PI ) ) / (2.0d0 * Alpha)
1787
Curvature(j) = Delta * Curvature(j)
1794
SUBROUTINE LocalMatrix( StiffMatrix,ForceVector, Surf, &
1796
!------------------------------------------------------------------------------
1798
REAL(KIND=dp), DIMENSION(:) :: ForceVector,Surf
1799
REAL(KIND=dp), DIMENSION(:,:) :: StiffMatrix
1801
TYPE(Nodes_t) :: Nodes
1802
TYPE(Element_t), POINTER :: Element
1804
!------------------------------------------------------------------------------
1806
!------------------------------------------------------------------------------
1808
REAL(KIND=dp) :: Basis(n)
1809
REAL(KIND=dp) :: dBasisdx(n,3),detJ
1810
REAL(KIND=dp) :: Grad(3),GradAbs,A,B,xpos
1811
INTEGER :: i,j,k,c,p,q,t,dim,N_Integ
1812
REAL(KIND=dp) :: s,u,v,w
1813
TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff
1814
REAL(KIND=dp), DIMENSION(:), POINTER :: U_Integ,V_Integ,W_Integ,S_Integ
1818
!------------------------------------------------------------------------------
1820
dim = CoordinateSystemDimension()
1825
!------------------------------------------------------------------------------
1827
!------------------------------------------------------------------------------
1828
IntegStuff = GaussPoints( element )
1829
U_Integ => IntegStuff % u
1830
V_Integ => IntegStuff % v
1831
W_Integ => IntegStuff % w
1832
S_Integ => IntegStuff % s
1833
N_Integ = IntegStuff % n
1835
!------------------------------------------------------------------------------
1836
! Now we start integrating
1837
!------------------------------------------------------------------------------
1844
!------------------------------------------------------------------------------
1845
! Basis function values & derivatives at the integration point
1846
!------------------------------------------------------------------------------
1847
stat = ElementInfo( Element,Nodes,u,v,w,detJ,Basis,dBasisdx)
1849
s = detJ * S_Integ(t)
1851
!------------------------------------------------------------------------------
1852
! Coordinatesystem dependent info
1853
!------------------------------------------------------------------------------
1854
IF ( Coordinates == AxisSymmetric .OR. Coordinates == CylindricSymmetric ) THEN
1855
xpos = SUM( Nodes % x(1:n) * Basis(1:n) )
1859
!------------------------------------------------------------------------------
1862
Grad(i) = SUM( dBasisdx(1:n,i) * Surf(1:n) )
1864
GradAbs = SQRT( SUM( Grad * Grad ) )
1865
IF ( GradAbs > 10*AEPS ) THEN
1866
Grad = Grad / GradAbs
1869
!------------------------------------------------------------------------------
1870
! Loop over basis functions of both unknowns and weights
1871
!------------------------------------------------------------------------------
1875
A = Basis(q) * Basis(p)
1876
A = A + Diff * SUM( dBasisdx(q,1:dim) * dBasisdx(p,1:dim) )
1878
StiffMatrix(p,q) = StiffMatrix(p,q) + s * A
1881
B = - SUM( dBasisdx(p, 1:dim) * Grad(1:dim))
1882
ForceVector(p) = ForceVector(p) + s * B
1887
!------------------------------------------------------------------------------
1888
END SUBROUTINE LocalMatrix
1891
!------------------------------------------------------------------------------
1892
SUBROUTINE LocalBoundary( BoundaryMatrix, BoundaryVector, &
1893
Surf, Element, Parent, n, pn, ElementNodes, ParentNodes )
1894
!------------------------------------------------------------------------------
1896
REAL(KIND=dp) :: BoundaryMatrix(:,:), BoundaryVector(:), Surf(:)
1897
TYPE(Nodes_t) :: ElementNodes, ParentNodes
1898
TYPE(Element_t), POINTER :: Element, Parent
1901
REAL(KIND=dp) :: Basis(n), dBasisdx(n,3), Normal(3), Grad(3), GradAbs, detJ, A
1902
REAL(KIND=dp) :: ParentBasis(pn), ParentdBasisdx(pn,3)
1903
REAL(KIND=dp) :: u,v,w,s,x(n),y(n),z(n),xpos, Force
1904
REAL(KIND=dp), POINTER :: U_Integ(:),V_Integ(:),W_Integ(:),S_Integ(:)
1906
INTEGER :: i,j,k,t,p,q,N_Integ,dim
1908
TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff
1911
!------------------------------------------------------------------------------
1913
BoundaryVector = 0.0d0
1914
BoundaryMatrix = 0.0d0
1915
dim = CoordinateSystemDimension()
1918
!------------------------------------------------------------------------------
1920
!------------------------------------------------------------------------------
1921
IntegStuff = GaussPoints( Element )
1922
U_Integ => IntegStuff % u
1923
V_Integ => IntegStuff % v
1924
W_Integ => IntegStuff % w
1925
S_Integ => IntegStuff % s
1926
N_Integ = IntegStuff % n
1928
!------------------------------------------------------------------------------
1929
! Now we start integrating
1930
!------------------------------------------------------------------------------
1935
!------------------------------------------------------------------------------
1936
! Basis function values & derivates at the integration point
1937
!------------------------------------------------------------------------------
1938
stat = ElementInfo( Element,ElementNodes,u,v,w,detJ,Basis,dBasisdx )
1939
s = S_Integ(t) * detJ
1941
!------------------------------------------------------------------------------
1942
! Coordinatesystem dependent info
1943
!------------------------------------------------------------------------------
1944
IF ( CurrentCoordinateSystem() /= Cartesian ) THEN
1945
xpos = SUM( ElementNodes % x(1:n)*Basis(1:n) )
1949
Normal = Normalvector( Element, ElementNodes, u, v, .TRUE. )
1951
!------------------------------------------------------------------------------
1952
! Need parent element basis etc., for computing normal derivatives on boundary.
1953
!------------------------------------------------------------------------------
1957
IF ( Element % NodeIndexes(i) == Parent % NodeIndexes(j) ) THEN
1958
x(i) = Parent % TYPE % NodeU(j)
1959
y(i) = Parent % TYPE % NodeV(j)
1960
z(i) = Parent % TYPE % NodeW(j)
1966
u = SUM( Basis(1:n) * x(1:n) )
1967
v = SUM( Basis(1:n) * y(1:n) )
1968
w = SUM( Basis(1:n) * z(1:n) )
1970
stat = ElementInfo( Parent, ParentNodes, u, v, w, detJ, ParentBasis, ParentdBasisdx )
1973
Grad(j) = SUM( ParentdBasisdx(1:pn,j) * Surf(1:pn) )
1975
GradAbs = SQRT( SUM(Grad(1:dim) * Grad(1:dim)) )
1977
IF ( GradAbs > 10*AEPS ) THEN
1978
Grad = Grad / GradAbs
1981
!------------------------------------------------------------------------------
1985
A = Diff * SUM( Normal(1:dim) * dBasisdx(q,1:dim)) * Basis(p)
1986
BoundaryMatrix(p,q) = BoundaryMatrix(p,q) + s * A
1990
Force = SUM( Normal(1:dim) * Grad(1:dim) )
1992
BoundaryVector(q) = BoundaryVector(q) + s * Basis(q) * Force
1997
END SUBROUTINE LocalBoundary
1998
!------------------------------------------------------------------------------
2000
!------------------------------------------------------------------------------
2001
END SUBROUTINE LevelSetCurvature
2002
!------------------------------------------------------------------------------
2007
FUNCTION LevelSetTimestep( Model ) RESULT( dt )
2011
USE ElementDescription
2015
TYPE(Model_t) :: Model
2018
TYPE(Solver_t), POINTER :: Solver
2019
TYPE(Variable_t), POINTER :: TimeVariable, SurfSol
2020
REAL(KIND=dp), POINTER :: Surface(:), Surf(:)
2021
INTEGER, POINTER :: SurfPerm(:), NodeIndexes(:)
2022
TYPE(Nodes_t) :: ElementNodes
2023
TYPE(Element_t),POINTER :: CurrentElement
2024
TYPE(ValueList_t), POINTER :: Material
2025
REAL(KIND=dp), POINTER :: TimestepSizes(:,:)
2027
INTEGER :: i,j,k,n,t,elem,N_Integ,body_id,mat_id, dim, TimeIntervals
2028
REAL(KIND=dp), ALLOCATABLE :: Basis(:), dBasisdx(:,:), NodalVelo(:,:)
2029
REAL(KIND=dp) :: Val,Grad(3),Velo(3),NormalVelo,AbsVelo,GradAbs,detJ,&
2030
MaxNormVelo,MaxAbsVelo
2031
REAL(KIND=dp) :: s,u,v,w,dt0,prevdt,cumtime,dsmax
2032
TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff
2033
REAL(KIND=dp), DIMENSION(:), POINTER :: U_Integ,V_Integ,W_Integ,S_Integ
2034
LOGICAL :: stat, GotIt, AllocationsDone = .FALSE.
2035
CHARACTER(LEN=MAX_NAME_LEN) :: LevelSetVariableName
2037
SAVE AllocationsDone, Basis, dBasisdx, NodalVelo, Surf, ElementNodes, prevdt
2040
TimestepSizes => ListGetConstRealArray( CurrentModel % Simulation,&
2041
'Timestep Sizes', GotIt )
2042
TimeIntervals = SIZE(TimestepSizes)
2044
IF(TimeIntervals > 1) THEN
2045
CALL Warn('LevelSetTimestep','Implemented only for one Time Interval')
2048
dt0 = TimestepSizes(1,1)
2050
TimeVariable => VariableGet(Model % Variables, 'Time')
2051
cumtime = TimeVariable % Values(1)
2053
dim = CoordinateSystemDimension()
2055
! The variable that should be reinitialized
2056
LevelSetVariableName = 'Surface'
2057
SurfSol => VariableGet( Model % Variables, TRIM(LevelSetVariableName) )
2058
IF(ASSOCIATED(SurfSol)) THEN
2059
Surface => SurfSol % Values
2060
SurfPerm => SurfSol % Perm
2062
CALL Warn('LevelSetTimeStep','SurfSol does not exist: '//TRIM(LevelSetVariableName))
2066
Solver => SurfSol % Solver
2067
DsMax = ListGetConstReal(Model % Simulation,'LevelSet Courant Number',GotIt)
2068
IF(.NOT. GotIt) DsMax = 1.0d0
2070
IF(.NOT. AllocationsDone) THEN
2071
N = Solver % Mesh % MaxElementNodes
2072
ALLOCATE( Basis(n), dBasisdx(n,3), NodalVelo(3,n), Surf(n), &
2073
ElementNodes % x(n), ElementNodes % y(n), ElementNodes % z(n) )
2075
AllocationsDone = .TRUE.
2081
DO elem=1,Solver % Mesh % NumberOfBulkElements
2083
CurrentElement => Solver % Mesh % Elements(elem)
2084
n = CurrentElement % TYPE % NumberOfNodes
2085
NodeIndexes => CurrentElement % NodeIndexes
2087
IF(ANY(SurfPerm(NodeIndexes) == 0)) CYCLE
2089
Surf(1:n) = Surface( SurfPerm(NodeIndexes) )
2090
IF(ALL(Surf(1:n) < 0.0d0) .OR. ALL(Surf(1:n) > 0.0d0) ) CYCLE
2092
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
2093
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
2094
ElementNodes % z(1:n) = Solver % Mesh % Nodes % z(NodeIndexes)
2096
Model % CurrentElement => CurrentElement
2097
body_id = CurrentElement % Bodyid
2098
mat_id = ListGetInteger( Model % Bodies( body_id ) % Values, 'Material' )
2099
Material => Model % Materials(mat_id) % Values
2101
!------------------------------------------------------------------------------
2102
! Computed or given velocity field
2103
!------------------------------------------------------------------------------
2105
NodalVelo(1,1:n) = ListGetReal( Material,'Levelset Velocity 1',n,NodeIndexes,GotIt)
2106
NodalVelo(2,1:n) = ListGetReal( Material,'Levelset Velocity 2',n,NodeIndexes,GotIt)
2107
IF(dim == 3) NodalVelo(3,1:n) = ListGetReal( Material,'Levelset Velocity 3',n,NodeIndexes,GotIt)
2109
!------------------------------------------------------------------------------
2111
!------------------------------------------------------------------------------
2112
IntegStuff = GaussPoints( CurrentElement )
2114
U_Integ => IntegStuff % u
2115
V_Integ => IntegStuff % v
2116
W_Integ => IntegStuff % w
2117
S_Integ => IntegStuff % s
2118
N_Integ = IntegStuff % n
2120
!------------------------------------------------------------------------------
2121
! Maximum at any integration point
2122
!------------------------------------------------------------------------------
2130
!------------------------------------------------------------------------------
2131
! Basis function values & derivatives at the integration point
2132
!------------------------------------------------------------------------------
2134
stat = ElementInfo( CurrentElement,ElementNodes,u,v,w,detJ, Basis,dBasisdx)
2137
Grad(i) = SUM( dBasisdx(1:n,i) * Surf(1:n) )
2138
Velo(i) = SUM( Basis(1:n) * NodalVelo(i,1:n) )
2141
GradAbs = SQRT( SUM( Grad(1:dim) * Grad(1:dim) ) )
2142
NormalVelo = SUM( Grad(1:dim) * Velo(1:dim) ) / GradAbs
2143
NormalVelo = NormalVelo / SQRT(detJ)
2144
MaxNormVelo = MAX(MaxNormVelo, ABS(NormalVelo))
2146
AbsVelo = SQRT(SUM (Velo(1:dim) * Velo(1:dim)) )
2147
AbsVelo = AbsVelo / SQRT(detJ)
2148
MaxAbsVelo = MAX(MaxAbsVelo, ABS(AbsVelo))
2153
IF( ListGetLogical(Model % Simulation,'LevelSet Timestep Directional',GotIt) ) THEN
2154
IF( MaxNormVelo * dt0 > dsMax) dt = dsMax / MaxNormVelo
2156
IF( MaxAbsVelo * dt0 > dsMax) dt = dsMax / MaxAbsVelo
2160
IF(dt > prevdt) dt = 0.5d0 * (dt + prevdt)
2164
WRITE(Message,'(a,ES12.3)') 'Levelset timestep',dt
2165
CALL Info( 'LevelSetTimestep',Message, Level=4 )
2166
CALL ListAddConstReal(Model % Simulation,'res: Levelset timestep',dt)
2168
END FUNCTION LevelSetTimestep