26 real(DP),
allocatable :: projectors(:,:) !>
33 real(DP),
allocatable :: h_red(:,:)
45 integer,
intent(in) :: n_max, ntot
49 allocate(apx%projectors(ntot, 0:n_max), apx%H_red(n_max, n_max))
50 apx%projectors = 0._dp
62 subroutine projh(r,h1,h2,bi,vml,vmk, apx, wl,ws,name4)
63 use kinds, only : dp, qp
64 use size_m
, only : nx1, ny1, nz1, nelv, nid
65 use geom, only : voltm1, volvm1
66 use tstep, only : istep, ifield, nelfld
68 use ctimer, only : nproj, tproj, proj_flop, proj_mop
72 real(DP),
intent(inout) :: r(*) !>
73 real(DP),
intent(in) :: h1(*) !>
74 real(DP),
intent(in) :: h2(*) !>
75 real(DP),
intent(in) :: vml(*) !>
76 real(DP),
intent(in) :: vmk(*) !>
77 real(DP),
intent(in) :: bi(*) !>
78 real(DP),
intent(out) :: wl(*) !>
79 real(DP),
intent(out) :: ws(*) !>
81 character(4),
intent(in) :: name4 !>
83 integer :: nel, ntot, i, j, n10
84 real(DP) :: vol, alpha1, alpha2, ratio
85 real(DP),
external :: glsc23
86 real(DP),
allocatable :: evecs(:,:), ev(:)
88 real(DP),
parameter :: one = 1._dp, zero = 0._dp
95 if (apx%n_sav == 0)
then
96 apx%projectors(:,0) = 0._dp
104 if (nel == nelv) vol = volvm1
107 alpha1 = glsc23(r,bi,vml,ntot)
108 if (alpha1 > 0) alpha1 = sqrt(alpha1/vol)
112 call
updrhsh(apx,h1,h2,vml,vmk,ws)
117 if (10 * apx%n_sav + 100 > ntot)
write(*,*)
"wl isn't big enough to be dsyev's work"
118 allocate(evecs(apx%n_sav, apx%n_sav), ev(apx%n_sav))
119 evecs = apx%H_red(1:apx%n_sav,1:apx%n_sav)
120 call dsyev(
'V',
'U', apx%n_sav, &
124 if (nid == 0 .and. ierr /= 0)
write(*,*)
"DSYEV failed", ierr
127 proj_flop = proj_flop + ntot
128 proj_mop = proj_mop + 3*ntot
129 wl(1:ntot) = r(1:ntot) * vml(1:ntot)
133 ws(i) =
glsc2(wl, apx%projectors(:,i), ntot)
136 proj_flop = proj_flop + (2*ntot-1)*apx%n_sav
137 proj_mop = proj_mop + apx%n_sav * (ntot+1)
138 call dgemv(
'T', ntot, apx%n_sav, &
139 one, apx%projectors(:,1:apx%n_sav), ntot, &
142 call
gop(ws, ws(1+apx%n_sav),
'+ ', apx%n_sav)
152 qsum = qsum + evecs(j,i) * ws(j)
158 qsum = qsum + evecs(j,i) * ws(j)
167 qsum = qsum + evecs(i,j) * ev(j)
173 proj_flop = proj_flop + ntot*(2*apx%n_sav-1)
174 proj_mop = proj_mop + (apx%n_sav+1) * ntot
175 call dgemv(
'N', ntot, apx%n_sav, &
176 one, apx%projectors(:,1:apx%n_sav), ntot, &
178 zero, apx%projectors(:,0), 1)
183 call
axhelm(wl,apx%projectors(:,0),h1,h2,1,1)
185 proj_flop = proj_flop + ntot
186 proj_mop = proj_mop + 2*ntot
187 wl(1:ntot) = wl(1:ntot) * vmk(1:ntot)
189 proj_flop = proj_flop + ntot
190 proj_mop = proj_mop + 2*ntot
191 r(1:ntot) = r(1:ntot) - wl(1:ntot)
196 alpha2 = glsc23(r,bi,vml,ntot)
197 if (alpha2 > 0) alpha2 = sqrt(alpha2/vol)
198 ratio = alpha1/alpha2
201 n10=min(10,apx%n_sav)
203 if (nid == 0)
write(6,10) istep,name4,alpha1,alpha2,ratio,apx%n_sav
204 10
format(4x,i7,4x,a4,
' alph1n',1p3e12.4,i6)
206 if (nid == 0)
write(6,11) istep,name4,apx%n_sav,(ev(i),i=1,n10)
207 11
format(4x,i7,4x,a4,
' halpha',i6,10(1p10e12.4,/,17x))
215 subroutine gensh(v1,h1,h2,vml,vmk,apx,ws)
217 use mesh, only : niterhm
220 REAL(DP),
intent(inout) :: V1 (*) !>
221 REAL(DP),
intent(in) :: H1 (*) !>
222 REAL(DP),
intent(in) :: H2 (*) !>
223 REAL(DP),
intent(in) :: vmk(*) !>
224 REAL(DP),
intent(in) :: vml(*) !>
225 real(DP),
intent(out) :: ws(:) !>
230 real(DP),
external :: dnrm2
231 ntot =
size(apx%projectors,1)
234 v1(1:ntot) = v1(1:ntot) + apx%projectors(:,0)
237 if (niterhm < 1)
return
240 apx%n_sav = min(apx%n_sav + 1, apx%n_max)
241 apx%next = mod(apx%next, apx%n_max) + 1
242 call
copy(apx%projectors(:,apx%next),v1,ntot)
243 call
hconj(apx,apx%next,h1,h2,vml,vmk,ws)
250 subroutine hconj(apx,k,h1,h2,vml,vmk,ws)
256 integer,
intent(in) :: k !>
257 real(DP),
intent(in) :: h1(*) !>
258 real(DP),
intent(in) :: h2(*) !>
259 real(DP),
intent(in) :: vml(*) !>
260 real(DP),
intent(in) :: vmk(*) !>
261 real(DP),
intent(out) :: ws(*) !>
264 real(DP),
parameter :: one = 1._dp, zero = 0._dp
267 ntot=
size(apx%projectors, 1)
268 hconj_flop = hconj_flop + apx%n_sav*(2*ntot-1)
269 hconj_mop = hconj_mop + apx%n_sav * (ntot +1)
270 hconj_flop = hconj_flop + ntot
271 hconj_mop = hconj_flop + 3*ntot
272 hconj_flop = hconj_flop + ntot
273 hconj_mop = hconj_flop + 3*ntot
277 call
axhelm(apx%projectors(:,0),apx%projectors(:,k),h1,h2,1,1)
279 apx%projectors(:,0) = apx%projectors(:,0) * vmk(1:ntot)
280 call
dssum(apx%projectors(:,0))
281 apx%projectors(:,0) = apx%projectors(:,0) * vml(1:ntot)
284 call dgemv(
'T', ntot, apx%n_sav, &
285 one, apx%projectors(1,1), ntot, &
286 apx%projectors(1,0), 1, &
287 zero, apx%H_red(1,k), 1)
288 call
gop(apx%H_red(:,k), ws,
'+ ', apx%n_sav)
292 apx%H_red(k,i) = apx%H_red(i,k)
303 use input, only : ifvarp, iflomach
304 use tstep, only : dt, ifield
308 real(DP),
intent(in) :: h1(*) !>
309 real(DP),
intent(in) :: h2(*) !>
310 real(DP),
intent(in) :: vml(*) !>
311 real(DP),
intent(in) :: vmk(*) !>
312 real(DP),
intent(out) :: ws(*) !>
315 logical,
save :: ifnewdt = .false.
320 if (dt /= apx%dt)
then
324 elseif (ifnewdt)
then
327 if (ifvarp(ifield)) ifupdate = .true.
328 if (iflomach) ifupdate = .true.
336 call
hconj(apx, apx%n_sav, h1,h2,vml,vmk,ws)
344 subroutine hmhzpf(name,u,r,h1,h2,mask,mult,imesh,tli,maxit,isd,bi)
346 use size_m
, only : lx1, ly1, lz1
347 use size_m
, only : nx1, ny1, nz1, nelv, nelt, ndim
349 use fdmh1, only : kfldfdm
350 use input, only : param
354 REAL(DP),
intent(out) :: U (lx1,ly1,lz1,1) !>
355 REAL(DP),
intent(in) :: R (lx1,ly1,lz1,1) !>
356 REAL(DP),
intent(in) :: H1 (lx1,ly1,lz1,1) !>
357 REAL(DP),
intent(in) :: H2 (lx1,ly1,lz1,1) !>
358 REAL(DP),
intent(in) :: MASK (lx1,ly1,lz1,1) !>
359 REAL(DP),
intent(in) :: MULT (lx1,ly1,lz1,1) !>
360 REAL(DP),
intent(in) :: bi (lx1,ly1,lz1,1) !>
362 integer :: imesh, maxit, isd
369 IF (imesh == 1) ntot = nx1*ny1*nz1*nelv
370 IF (imesh == 2) ntot = nx1*ny1*nz1*nelt
373 if (param(22) /= 0) tol = abs(param(22))
374 CALL
chktcg1(tol,r,h1,h2,mask,mult,imesh,isd)
384 if (name ==
'PRES') kfldfdm = ndim+1
387 (u,r,h1,h2,mask,mult,imesh,tol,maxit,isd,bi,name)
396 subroutine hsolve(name,u,r,h1,h2,vmk,vml,imsh,tol,maxit,isd &
399 use size_m
, only : lx1, ly1, lz1, lelv
400 use input, only : param
402 use tstep, only : ifield, nelfld, istep
405 CHARACTER(4),
intent(in) :: NAME !>
406 REAL(DP),
intent(out) :: U (lx1,ly1,lz1,lelv) !>
407 REAL(DP),
intent(inout) :: R (lx1,ly1,lz1,lelv) !>
408 REAL(DP),
intent(in) :: H1 (lx1,ly1,lz1,lelv) !>
409 REAL(DP),
intent(in) :: H2 (lx1,ly1,lz1,lelv) !>
410 REAL(DP),
intent(in) :: vmk (lx1,ly1,lz1,lelv) !>
411 REAL(DP),
intent(in) :: vml (lx1,ly1,lz1,lelv) !>
412 integer,
intent(in) :: imsh !>
413 real(DP),
intent(in) :: tol !>
414 integer,
intent(in) :: maxit !>
415 integer,
intent(in) :: isd !>
417 REAL(DP),
intent(in) :: bi (lx1,ly1,lz1,*) !>
419 real(DP),
allocatable :: w1(:)
420 real(DP),
allocatable :: w2(:)
423 character(4) :: cname
426 real(DP),
external :: glsc23
435 if (cname ==
'PRES')
then
436 if (param(95) /= 0 .AND. istep > param(95) .and. param(93) > 0)
then
440 elseif (cname ==
'VELX' .or. cname ==
'VELY' .or. cname ==
'VELZ')
then
441 if (param(94) /= 0 .AND. istep > param(94) .and. param(92) > 0)
then
449 call
hmholtz(name,u,r,h1,h2,vmk,vml,imsh,tol,maxit,isd)
456 r(:,:,:,1:nel) = r(:,:,:,1:nel) * vmk(:,:,:,1:nel)
458 allocate(w2(2+2*apx%n_max))
459 allocate(w1(lx1*ly1*lz1*lelv))
460 call
projh(r,h1,h2,bi,vml,vmk,apx,w1,w2,name)
463 call
hmhzpf(name,u,r,h1,h2,vmk,vml,imsh,tol,maxit,isd,bi)
464 call
gensh(u,h1,h2,vml,vmk,apx,w2)
subroutine, private updrhsh(apx, h1, h2, vml, vmk, ws)
Recompute H_red if dt has changed.
subroutine dssum(u)
Direct stiffness sum.
Type to hold the approximation space. Should not be modified outside this module, so more of a handle...
subroutine, private hmhzpf(name, u, r, h1, h2, mask, mult, imesh, tli, maxit, isd, bi)
subroutine axhelm(au, u, helm1, helm2, imesh, isd)
Compute the (Helmholtz) matrix-vector product, AU = helm1*[A]u + helm2*[B]u, for NEL elements...
subroutine, public hsolve(name, u, r, h1, h2, vmk, vml, imsh, tol, maxit, isd, apx, bi)
Either std. Helmholtz solve, or a projection + Helmholtz solve.
real(dp) function dnekclock()
real(dp) function glsc2(x, y, n)
Perform inner-product in double precision.
subroutine chktcg1(tol, res, h1, h2, mask, mult, imesh, isd)
Check that the tolerances are not too small for the CG-solver. Important when calling the CG-solver (...
subroutine, public init_approx_space(apx, n_max, ntot)
Initialize approximation space object.
subroutine capit(lettrs, n)
Capitalizes string of length n.
subroutine, private projh(r, h1, h2, bi, vml, vmk, apx, wl, ws, name4)
Project out the part of the residual in the approx space.
subroutine, private gensh(v1, h1, h2, vml, vmk, apx, ws)
Reconstruct the solution to the original problem by adding back the approximate solution, add solution to approximation space.
subroutine gop(x, w, op, n)
Global vector commutative operation.
subroutine cggo(x, f, h1, h2, mask, mult, imsh, tin, maxit, isd, binv, name)
Solve the Helmholtz equation, H*U = RHS, using preconditioned conjugate gradient iteration. Preconditioner: diag(H).
subroutine chcopy(a, b, n)
subroutine, private hconj(apx, k, h1, h2, vml, vmk, ws)
Update the k-th row/column of H_red.
subroutine hmholtz(name, u, rhs, h1, h2, mask, mult, imsh, tli, maxit, isd)