Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bringing back VOLP for ghost cell (TUM) #124

Merged
merged 1 commit into from
Dec 2, 2024

Conversation

swenczowski
Copy link
Contributor

--- please, consider this PR a draft for discussion, improvements to follow, not tested ---

Dear all,

as encountered by @javierebb, mglet-base does not provide the field "VOLP", which provides the volume of intersected cells within the ghost cell immersed boundary framework.

This PR outlines an idea to recover this field, which is primarily used for postprocessing on our side. The following considerations have been made, such that I am slightly optimistic that all relevant locations in the code have been touched. As discussed beforehand, both areas and volume are given absolute in [L^2] or [L^3] and not in terms of fractions.

image

I would much appreciate your ideas and feedback on this very rough first draft.

Best regards,

Simon

Copy link
Contributor

@hakostra hakostra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The significant comments are on some suggestions on how to improve the volp-computations.

A last small request:
Can you simultaneously rename the fields AU, AV, AW - that are now real areas with unit length squared - to AREAU, AREAV, AREAW? This will apply to the fields that are created in gc_mod.F90 and accessed in gc_flowstencils_mod.F90 - not gc_blockbp_mod.F90 - this should be left untouched!

This establish the practice that field AU = non-dimensional field with fraction of open face area - only existing locally in blocking and AREAU = real, physical area with unit length squared used during time-integration.

It is enough to rename the fields them selves, you do not need to rename the pointer arrays unless you see particular needs, i.e. change:

CALL set_field("AU")
CALL get_fieldptr(au, "AU")

to

CALL set_field("AREAU", istag=1, units=[0, 2, 0, 0, 0, 0, 0])
CALL get_fieldptr(au, "AREAU")

I think you get this point as well.

Comment on lines 203 to 299

! Local variables
INTEGER(intk) :: imygrid, idx, igrid, ind, ip3
TYPE(field_t), POINTER :: ddx_f, ddy_f, ddz_f
INTEGER(intk) :: imygrid, idx, igrid, ind
INTEGER(intk) :: aucells
INTEGER(intk) :: kk, jj, ii, k, j, i
REAL(realk) :: area
REAL(realk), POINTER, CONTIGUOUS :: au(:, :, :)

! First set AU to value of BU
au_f%arr = bu%arr
av_f%arr = bv%arr
aw_f%arr = bw%arr

! Now set AU, AV, AW
REAL(realk), POINTER, CONTIGUOUS :: bu(:, :, :)
REAL(realk), POINTER, CONTIGUOUS :: ddx(:), ddy(:), ddz(:)

CALL get_field(ddx_f, "DDX")
CALL get_field(ddy_f, "DDY")
CALL get_field(ddz_f, "DDZ")

! Now set AU, AV, AW ( absolute areas in unit [L^2] )
all_grids: DO imygrid = 1, nmygrids

igrid = mygrids(imygrid)
CALL get_mgdims(kk, jj, ii, igrid)
CALL get_ip3(ip3, igrid)

! Getting the pressure cell side lengths
CALL ddx_f%get_ptr(ddx, igrid)
CALL ddy_f%get_ptr(ddy, igrid)
CALL ddz_f%get_ptr(ddz, igrid)

! Area AU from BU
CALL au_f%get_ptr(au, igrid)
CALL bu_f%get_ptr(bu, igrid)
DO i = 1, ii
DO j = 1, jj
DO k = 1, kk
area = ddz(k) * ddy(j)
au(k, j, i) = bu(k, j, i) * area
END DO
END DO
END DO
! Refine for intersected cells
aucells = SIZE(this%auind(imygrid)%arr)
DO idx = 1, aucells
ind = this%auind(imygrid)%arr(idx)
CALL ind2sub(ind, k, j, i, kk, jj, ii)
au(k, j, i) = this%auvalue(imygrid)%arr(idx)
area = ddz(k) * ddy(j)
au(k, j, i) = this%auvalue(imygrid)%arr(idx) * area
END DO

! Area AV from BV
CALL av_f%get_ptr(au, igrid)
CALL bv_f%get_ptr(bu, igrid)
DO i = 1, ii
DO j = 1, jj
DO k = 1, kk
area = ddx(i) * ddz(k)
au(k, j, i) = bu(k, j, i) * area
END DO
END DO
END DO
! Refine for intersected cells
aucells = SIZE(this%avind(imygrid)%arr)
DO idx = 1, aucells
ind = this%avind(imygrid)%arr(idx)
CALL ind2sub(ind, k, j, i, kk, jj, ii)
au(k, j, i) = this%avvalue(imygrid)%arr(idx)
area = ddx(i) * ddz(k)
au(k, j, i) = this%avvalue(imygrid)%arr(idx) * area
END DO

! Area AW from BW
CALL aw_f%get_ptr(au, igrid)
CALL bw_f%get_ptr(bu, igrid)
DO i = 1, ii
DO j = 1, jj
DO k = 1, kk
area = ddx(i) * ddy(j)
au(k, j, i) = bu(k, j, i) * area
END DO
END DO
END DO
! Refine for intersected cells
aucells = SIZE(this%awind(imygrid)%arr)
DO idx = 1, aucells
ind = this%awind(imygrid)%arr(idx)
CALL ind2sub(ind, k, j, i, kk, jj, ii)
au(k, j, i) = this%awvalue(imygrid)%arr(idx)
area = ddx(i) * ddy(j)
au(k, j, i) = this%awvalue(imygrid)%arr(idx) * area
END DO

END DO all_grids
END SUBROUTINE get_auavaw
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would be simpler and cleaner to keep the original code, constructing au, av aw as fractions in the range 0..1, and then just in the end have another loop:

        DO i = 1, ii
                DO j = 1, jj
                    DO k = 1, kk
                        au(k, j, i) = ddy(j)*ddz(k)*au(k, j, i)
                        av(k, j, i) = ddx(i)*ddz(k)*av(k, j, i)
                        aw(k, j, i) = ddx(i)*ddy(j)*aw(k, j, i)
                    END DO
                END DO
            END DO

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, can be done. Admittedly, I do not dislike the current form, as it shows the systematics more clearly. However, I have no strong preferences...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The you make a call - I will accept both.

Comment on lines 344 to 346
CALL get_fieldptr(x, "X", igrid)
CALL get_fieldptr(y, "Y", igrid)
CALL get_fieldptr(z, "Z", igrid)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip: XSTAG, YSTAG, ZSTAG also exist as fields - you no longer need to construct these on the fly.

Comment on lines 365 to 367
REAL(realk), INTENT(in) :: ddx(ii), ddy(jj), ddz(kk)
REAL(realk), INTENT(in) :: dx(ii), dy(jj), dz(kk)
REAL(realk), INTENT(in) :: x(ii), y(jj), z(kk)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass in XSTAG, YSTAG, ZSTAG, DDX, DDY, DDZ

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, ok. Will be changed.

Comment on lines 402 to 404
areax = au(k, j, i-1) - au(k, j, i)
areay = av(k, j-1, i) - av(k, j, i)
areaz = aw(k-1, j, i) - aw(k, j, i)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In most other stencil operations we have the higher index first and subtract the lower index

Suggested change
areax = au(k, j, i-1) - au(k, j, i)
areay = av(k, j-1, i) - av(k, j, i)
areaz = aw(k-1, j, i) - aw(k, j, i)
areax = au(k, j, i) - au(k, j, i-1)
areay = av(k, j, i) - av(k, j-1, i)
areaz = aw(k, j, i) - aw(k-1, j, i)

This will flip the sign of the areas, see also comment below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Will be changed.

Comment on lines 408 to 409
vpx = (-au(k, j, i-1) * (xstagm - xstag)) &
+ areax * (swx - xstag)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference between two xstag values are ddx: xstagm - xstag = -ddx.
(-au)*(-ddx) = au*ddx

Since we flipped the sign of areax, we also flip the sign of (swx - xstag).

So you end up with something like: vpx = (au(k, j, i-1)*ddx(i)) + areax*(xstag-swx)

This will be more numerically accurate (since we take one less difference between numbers of similar magnitude - subject to high round-off errors), easier to read and less code.

The same of course apply for the y- and z-directions as well - I guess you get the point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, that also came to my mind yesterday evening -- of course, the difference between two staggered positions is the pressure cell side length...

When coding it, I was too focussed on a pure replication of the previous implementation... Will be changed.

@swenczowski
Copy link
Contributor Author

Dear all,

this PR has been updated based on the preceding discussion. Thank you for the hints!

@hakostra, please, let me know if all points have been addressed.

@javierebb, please, already give the implementation a try.

Best regards,

Simon

@hakostra
Copy link
Contributor

hakostra commented Dec 2, 2024

Hi Simon, now try ci/lint-fortran.py --fixall

@hakostra
Copy link
Contributor

hakostra commented Dec 2, 2024

@swenczowski This looks good. Are your intentions now to apply the areau/v/w and volp to the scalar solver as discussed?

@swenczowski
Copy link
Contributor Author

@swenczowski This looks good. Are your intentions now to apply the areau/v/w and volp to the scalar solver as discussed?

Yes, that will come now. Also, we are planning to add a volume source for the scalar field, which would also need the VOLP field.

@swenczowski
Copy link
Contributor Author

If you agree, I suggest merging the content of this PR before we continue with the actual "usage" of VOLP for the scalar.
Would that be OK for you?

@hakostra hakostra merged commit 398a527 into kmturbulenz:master Dec 2, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants