Skip to content

Commit b8fab46

Browse files
authored
Merge pull request #184 from BerkeleyLab/vibes
doc(ai4dev): fix type in README
2 parents 0f87cd1 + 50fdb21 commit b8fab46

3 files changed

Lines changed: 159 additions & 2 deletions

File tree

doc/ai4dev/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ Vibe Coding
1616
2. Edit `diffusion-app.F90` to remove the lines beginning and ending with
1717
`module procedure laplacian` and `end procedure laplacian`, respectively.
1818
3. Enter the file `doc/ai4dev/vibe-coding/README.md` as your prompt and
19-
attach the edited `diffusion-app.F90` file.
19+
attach the edited `diffusion-app.F90` file. You might need to rename
20+
the file to something like `diffusion-app.txt` for the file type to be
21+
acccepted.
2022
4. Insert the resulting function into the `subdomain_s` submodule and
2123
try compiling and executing again to check the result.
2224

@@ -29,6 +31,8 @@ Idiomtic Vibe Coding
2931
2. Edit `test-suite.F90` to remove the lines beginning and ending with
3032
`module procedure laplacian` and `end procedure laplacian`, respectively.
3133
3. Enter the file `doc/ai4dev/idiomaic-vibe-coding/README.md` as your prompt
32-
and attach the edited `tgest-sutie.F90` file.
34+
and attach the edited `test-suite.F90` file. You might need to rename
35+
the file to something like `test-suite.txt` for the file type to be
36+
acccepted.
3337
4. Insert the resulting function into the `subdomain_s` submodule and
3438
try compiling and executing again to check the result.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
pure module function laplacian(rhs) result(laplacian_rhs)
2+
implicit none
3+
class(subdomain_t), intent(in) :: rhs
4+
type(subdomain_t) :: laplacian_rhs
5+
6+
! Local variables for array bounds and grid spacing
7+
integer :: my_nx, ny, nz, me, num_subdomains
8+
real :: dx_val, dy_val, dz_val, dx2_inv, dy2_inv, dz2_inv
9+
10+
! Get array dimensions and parallel image information
11+
my_nx = size(rhs%s_, 1)
12+
ny = size(rhs%s_, 2)
13+
nz = size(rhs%s_, 3)
14+
me = this_image()
15+
num_subdomains = num_images()
16+
17+
! Get grid spacing values
18+
dx_val = rhs%dx()
19+
dy_val = rhs%dy()
20+
dz_val = rhs%dz()
21+
22+
! Compute inverse squared grid spacings for efficiency
23+
dx2_inv = 1.0 / (dx_val * dx_val)
24+
dy2_inv = 1.0 / (dy_val * dy_val)
25+
dz2_inv = 1.0 / (dz_val * dz_val)
26+
27+
! Allocate result array with same shape as input
28+
allocate(laplacian_rhs%s_(my_nx, ny, nz))
29+
30+
! Initialize result to zero
31+
laplacian_rhs%s_ = 0.0
32+
33+
! Compute 2nd-order central difference Laplacian in interior points
34+
! Laplacian = d²/dx² + d²/dy² + d²/dz²
35+
do concurrent (i = 2:my_nx-1, j = 2:ny-1, k = 2:nz-1) default(none) &
36+
shared(laplacian_rhs, rhs, dx2_inv, dy2_inv, dz2_inv, my_nx, ny, nz, me, num_subdomains)
37+
38+
! Second derivative in x-direction: (f(i+1) - 2*f(i) + f(i-1))/dx²
39+
! Second derivative in y-direction: (f(j+1) - 2*f(j) + f(j-1))/dy²
40+
! Second derivative in z-direction: (f(k+1) - 2*f(k) + f(k-1))/dz²
41+
laplacian_rhs%s_(i,j,k) = &
42+
dx2_inv * (rhs%s_(i+1,j,k) - 2.0*rhs%s_(i,j,k) + rhs%s_(i-1,j,k)) + &
43+
dy2_inv * (rhs%s_(i,j+1,k) - 2.0*rhs%s_(i,j,k) + rhs%s_(i,j-1,k)) + &
44+
dz2_inv * (rhs%s_(i,j,k+1) - 2.0*rhs%s_(i,j,k) + rhs%s_(i,j,k-1))
45+
end do
46+
47+
! Handle boundary conditions at subdomain interfaces for x-direction
48+
! Left boundary (i=1) - only compute if not the first subdomain
49+
if (me > 1) then
50+
do concurrent (j = 2:ny-1, k = 2:nz-1) default(none) &
51+
shared(laplacian_rhs, rhs, dx2_inv, dy2_inv, dz2_inv, ny, nz, halo_x)
52+
53+
laplacian_rhs%s_(1,j,k) = &
54+
dx2_inv * (rhs%s_(2,j,k) - 2.0*rhs%s_(1,j,k) + halo_x(west,j,k)) + &
55+
dy2_inv * (rhs%s_(1,j+1,k) - 2.0*rhs%s_(1,j,k) + rhs%s_(1,j-1,k)) + &
56+
dz2_inv * (rhs%s_(1,j,k+1) - 2.0*rhs%s_(1,j,k) + rhs%s_(1,j,k-1))
57+
end do
58+
end if
59+
60+
! Right boundary (i=my_nx) - only compute if not the last subdomain
61+
if (me < num_subdomains) then
62+
do concurrent (j = 2:ny-1, k = 2:nz-1) default(none) &
63+
shared(laplacian_rhs, rhs, dx2_inv, dy2_inv, dz2_inv, my_nx, ny, nz, halo_x, num_subdomains)
64+
65+
laplacian_rhs%s_(my_nx,j,k) = &
66+
dx2_inv * (halo_x(east,j,k) - 2.0*rhs%s_(my_nx,j,k) + rhs%s_(my_nx-1,j,k)) + &
67+
dy2_inv * (rhs%s_(my_nx,j+1,k) - 2.0*rhs%s_(my_nx,j,k) + rhs%s_(my_nx,j-1,k)) + &
68+
dz2_inv * (rhs%s_(my_nx,j,k+1) - 2.0*rhs%s_(my_nx,j,k) + rhs%s_(my_nx,j,k-1))
69+
end do
70+
end if
71+
72+
! Set boundary values to zero as specified
73+
! Y boundaries
74+
laplacian_rhs%s_(:, 1, :) = 0.0
75+
laplacian_rhs%s_(:, ny, :) = 0.0
76+
77+
! Z boundaries
78+
laplacian_rhs%s_(:, :, 1) = 0.0
79+
laplacian_rhs%s_(:, :, nz) = 0.0
80+
81+
! X boundaries for first and last subdomains
82+
if (me == 1) then
83+
laplacian_rhs%s_(1, :, :) = 0.0
84+
end if
85+
86+
if (me == num_subdomains) then
87+
laplacian_rhs%s_(my_nx, :, :) = 0.0
88+
end if
89+
90+
end function laplacian
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
pure module function laplacian(rhs) result(laplacian_rhs)
2+
implicit none
3+
class(subdomain_t), intent(in) :: rhs
4+
type(subdomain_t) :: laplacian_rhs
5+
integer :: i, j, k
6+
7+
! Step 1: Empty module procedure with comments explaining the computation
8+
! This function computes the 2nd-order central difference approximation
9+
! to the Laplacian operator applied to the s_ component of the input subdomain
10+
11+
! Step 2: Allocate the result's s_ component to shape [my_nx, ny, nz]
12+
allocate(laplacian_rhs%s_(my_nx, ny, nz))
13+
14+
! Step 3: Compute 2nd-order central difference Laplacian using do concurrent
15+
! Handle interior points (excluding boundaries and halo regions)
16+
do concurrent(i=2:my_nx-1, j=2:ny-1, k=2:nz-1) default(none) shared(laplacian_rhs, rhs)
17+
! Step 4: Store Laplacian approximation in s_ component of result
18+
! Laplacian = d²/dx² + d²/dy² + d²/dz²
19+
laplacian_rhs%s_(i,j,k) = &
20+
(rhs%s_(i-1,j,k) - 2*rhs%s_(i,j,k) + rhs%s_(i+1,j,k))/dx_**2 + &
21+
(rhs%s_(i,j-1,k) - 2*rhs%s_(i,j,k) + rhs%s_(i,j+1,k))/dy_**2 + &
22+
(rhs%s_(i,j,k-1) - 2*rhs%s_(i,j,k) + rhs%s_(i,j,k+1))/dz_**2
23+
end do
24+
25+
! Handle western boundary points (i=1) with halo exchange
26+
if (me /= 1) then
27+
! Step 5: Use halo_x(west,:,:) when me==1 and accessing rhs%s_(1,:,:)
28+
do concurrent(j=2:ny-1, k=2:nz-1) default(none) shared(laplacian_rhs, rhs)
29+
laplacian_rhs%s_(1,j,k) = &
30+
(halo_x(west,j,k) - 2*rhs%s_(1,j,k) + rhs%s_(2,j,k))/dx_**2 + &
31+
(rhs%s_(1,j-1,k) - 2*rhs%s_(1,j,k) + rhs%s_(1,j+1,k))/dy_**2 + &
32+
(rhs%s_(1,j,k-1) - 2*rhs%s_(1,j,k) + rhs%s_(1,j,k+1))/dz_**2
33+
end do
34+
end if
35+
36+
! Handle eastern boundary points (i=my_nx) with halo exchange
37+
if (me /= num_subdomains) then
38+
! Step 5: Use halo_x(east,:,:) when me==num_subdomains and accessing rhs%s_(my_nx,:,:)
39+
do concurrent(j=2:ny-1, k=2:nz-1) default(none) shared(laplacian_rhs, rhs)
40+
laplacian_rhs%s_(my_nx,j,k) = &
41+
(rhs%s_(my_nx-1,j,k) - 2*rhs%s_(my_nx,j,k) + halo_x(east,j,k))/dx_**2 + &
42+
(rhs%s_(my_nx,j-1,k) - 2*rhs%s_(my_nx,j,k) + rhs%s_(my_nx,j+1,k))/dy_**2 + &
43+
(rhs%s_(my_nx,j,k-1) - 2*rhs%s_(my_nx,j,k) + rhs%s_(my_nx,j,k+1))/dz_**2
44+
end do
45+
end if
46+
47+
! Step 6: Set boundary conditions - zero Laplacian at domain boundaries
48+
laplacian_rhs%s_(:, 1, :) = 0. ! j=1 boundary
49+
laplacian_rhs%s_(:, ny, :) = 0. ! j=ny boundary
50+
laplacian_rhs%s_(:, :, 1) = 0. ! k=1 boundary
51+
laplacian_rhs%s_(:, :, nz) = 0. ! k=nz boundary
52+
53+
! Step 7: Set western domain boundary to zero if this is the first subdomain
54+
if (me == 1) then
55+
laplacian_rhs%s_(1, :, :) = 0.
56+
end if
57+
58+
! Step 8: Set eastern domain boundary to zero if this is the last subdomain
59+
if (me == num_subdomains) then
60+
laplacian_rhs%s_(my_nx, :, :) = 0.
61+
end if
62+
63+
end function

0 commit comments

Comments
 (0)