Skip to content

Commit 7e88cab

Browse files
authored
Fixing Sickle Cell Model, Reintroducing Intercellular Repulsion (#21)
1 parent 6382a5b commit 7e88cab

File tree

10 files changed

+124
-74
lines changed

10 files changed

+124
-74
lines changed

common/ModRbc.F90

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,11 @@ subroutine RBC_MakeUncurvedSickleSpheroid(cell, r, xc)
195195
real(WP),optional :: xc(3)
196196
integer :: ilat, ilon, ii
197197
real(WP) :: th, phi
198-
real(WP) :: pol, eq, curv
198+
real(WP) :: pol, eq
199199

200-
pol = 1.2 * r
201-
eq = 0.25 * r
202-
curv = 0.2 * r
200+
! following the cited model, scale the spheroid radii by the major radius of an RBC
201+
pol = 1.2 * r * 1.4
202+
eq = 0.25 * r * 1.4
203203

204204
do ilon = 1, cell%nlon
205205
do ilat = 1, cell%nlat
@@ -209,8 +209,6 @@ subroutine RBC_MakeUncurvedSickleSpheroid(cell, r, xc)
209209
cell%x(ilat,ilon,2) = eq*sin(th)*sin(phi)
210210
cell%x(ilat,ilon,3) = eq*cos(th)
211211

212-
!curve capsule
213-
!cell%x(ilon, ilat, 2) = cell%x(ilon, ilat, 2) - (curv * (cell%x(ilon, ilat, 3)**2))
214212
end do ! ilat
215213
end do ! ilon
216214
if (present(xc)) then

common/ModTimeInt.F90

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -331,22 +331,21 @@ subroutine TimeInt_Euler
331331

332332
! call LeukWallRepulsion
333333

334-
! SHB commenting out the vol constraint calls
335-
!call VolConstrainRbcs
336-
!call InterCellRepulsion
337-
!call FilterRbcs
338-
339-
!call VolConstrainRbcs
340-
!call InterCellRepulsion
341-
!call FilterRbcs
342-
343-
!call VolConstrainRbcs
344-
!call InterCellRepulsion
345-
!call FilterRbcs
346-
347-
!call VolConstrainRbcs
348-
!call InterCellRepulsion
349-
!call FilterRbcs
334+
call VolConstrainRbcs
335+
call InterCellRepulsion
336+
call FilterRbcs
337+
338+
call VolConstrainRbcs
339+
call InterCellRepulsion
340+
call FilterRbcs
341+
342+
call VolConstrainRbcs
343+
call InterCellRepulsion
344+
call FilterRbcs
345+
346+
call VolConstrainRbcs
347+
call InterCellRepulsion
348+
call FilterRbcs
350349
!!$
351350
!!$ call VolConstrainRbcs
352351
!!$ call InterCellRepulsion
@@ -985,24 +984,16 @@ subroutine VolConstrainRbcs
985984
type(t_rbc),pointer :: rbc
986985
real(WP) :: xc
987986
real :: fac
988-
real(WP) :: leukVol,platVol,rbcVol
989-
990-
real(WP) :: cellVol(3)
991-
992-
leukVol = 4./3.*PI*(1.4)**3
993-
rbcVol = 4./3.*PI*(1.0)**3
994-
platVol = 4./3.*PI*(4.*3./(2.*2.82)/2.)**3 ! about 3 microns
995-
cellVol = (/ rbcVol, leukVol, platVol /)
996987

997988
do irbc = 1, nrbc
998989

999990
rbc => rbcs(irbc)
1000991

1001992
call RBC_ComputeGeometry(rbc)
1002-
fac = (cellVol(rbc%celltype)-rbc%vol)/rbc%area
993+
fac = (rbcRefs(rbc%celltype)%vol-rbc%vol)/rbc%area
1003994
fac = SIGN(MIN(ABS(fac),epsDist/20.),fac)
1004995
if (rootWorld .and. ABS(fac).gt.epsDist/40.) then
1005-
print *,"VOL: ",cellVol(rbc%celltype),rbc%vol,fac
996+
print *,"VOL: ",rbcRefs(rbc%celltype)%vol,rbc%vol,fac
1006997
end if
1007998
do ilat = 1, rbc%nlat
1008999
do ilon = 1, rbc%nlon

examples/case/Input/tube.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
'D/restart.LATEST.dat'
2525

26-
0.0000000001 ! epsDist
26+
0.02 ! epsDist
2727
10. ! forceCoef
2828
10. ! viscRatThresh
2929
.false. ! rigidsep

examples/case_diff_celltypes/Input/SickleCell.dat

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

examples/case_diff_celltypes/Input/tube.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
'D/restart.LATEST.dat'
2525

26-
0.0000000001 ! epsDist
26+
0.012 ! epsDist
2727
10. ! forceCoef
2828
10. ! viscRatThresh
2929
.false. ! rigidsep

examples/randomized_case/Input/SickleCell.dat

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

examples/randomized_case/Input/tube.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
0.0 !
1313

1414
10000 ! Nt
15-
0.00014 ! Ts
15+
0.00035 ! Ts
1616

1717
100 ! cell_out
1818
-10000 ! wall_out
@@ -23,7 +23,7 @@
2323

2424
'D/restart.LATEST.dat'
2525

26-
0.0000000001 ! epsDist
26+
0.012 ! epsDist
2727
10. ! forceCoef
2828
10. ! viscRatThresh
2929
.false. ! rigidsep

examples/randomized_case/initcond_random.F90

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
program randomized_cell_gen
2-
2+
33
use ModDataTypes
44
use ModDataStruct
55
use ModRbc
@@ -30,8 +30,8 @@ program randomized_cell_gen
3030

3131
!calculate number of cells for the defined hematocrit, assuming all blood cells are healthy RBCs for volume
3232
!hematocrit = 4 * nrbc / (tube_radius^2 * tube_length)
33-
nrbcMax = ((3 * (tubelen * tuber**2 * hematocrit)) / 4) - 1
34-
33+
nrbcMax = ((3*(tubelen*tuber**2*hematocrit))/4)
34+
3535
!set periodic boundary box based on tube shape
3636
Lb(1) = tuber * 2 + 0.5
3737
Lb(2) = tuber * 2 + 0.5
@@ -93,10 +93,10 @@ program randomized_cell_gen
9393
fn = 'D/restart.LATEST.dat'
9494
call WriteRestart(fn, Nt0, time)
9595

96-
deallocate(rbcs)
97-
deallocate(walls)
96+
deallocate (rbcs)
97+
deallocate (walls)
9898
call FinalizeMPI
99-
stop
99+
stop
100100

101101
contains
102102

@@ -246,45 +246,104 @@ subroutine rotate_cell(cell)
246246

247247
end subroutine rotate_cell
248248

249-
!helper for place_cell, checks if cell1 and cell2 intersect/collide
250-
logical function check_cell_collision(cell1, cell2)
251-
type(t_Rbc) :: cell1, cell2
249+
!helper for place_cell, checks if cell1 intersects/collides with wall
250+
logical function check_wall_collision(cell)
251+
type(t_Rbc) :: cell
252252

253253
integer :: i, j, i2, j2
254254
real(WP) :: c1p(3), c2p(3), sp(3)
255255

256+
check_wall_collision = .false.
257+
258+
!each point in cell1
259+
do i = 1, cell%nlat
260+
do j = 1, cell%nlon
261+
262+
!define 2 diagonal points c1p & c2p for collision detection
263+
c1p = cell%x(i, j, :)
264+
c2p = cell%x(modulo(i, cell%nlat) + 1, modulo(j, cell%nlon) + 1, :)
265+
266+
!each wall
267+
do i2 = 1, nwall
268+
!each point in the wall
269+
do j2 = 1, walls(i2)%nvert
270+
271+
sp = walls(i2)%x(j2, :)
272+
273+
!check if the cell2 point lies inside the cube delineated by c1p & c2p
274+
if ( &
275+
((c1p(1) .le. sp(1) .and. sp(1) .le. c2p(1)) .or. (c2p(1) .le. sp(1) .and. sp(1) .le. c1p(1))) .and. & !x direction overlap
276+
((c1p(2) .le. sp(2) .and. sp(2) .le. c2p(2)) .or. (c2p(2) .le. sp(2) .and. sp(2) .le. c1p(2))) .and. & !y direction overlap
277+
((c1p(3) .le. sp(3) .and. sp(3) .le. c2p(3)) .or. (c2p(3) .le. sp(3) .and. sp(3) .le. c1p(3))) & !z direction overlap
278+
) then
279+
! since we found a collision, return true
280+
check_wall_collision = .true.
281+
return
282+
end if
283+
284+
end do !j2
285+
end do !i2
286+
287+
end do !j
288+
end do !i
289+
end function check_wall_collision
290+
291+
! helper for place_cell, checks if cell1 and cell2 intersect/collide
292+
! creates miniature bounding boxes along cell meshes to do AABB-AABB collision detection
293+
! should not have any false-negatives (return false even if the cells are intersecting)
294+
! may have false-positives (might return true if cells aren't intersecting, but are very close)
295+
logical function check_cell_collision(cell1, cell2)
296+
type(t_Rbc) :: cell1, cell2
297+
298+
integer :: i, j, i2, j2, ii
299+
300+
real(WP) :: p1(3), p2(3)
301+
real(WP) :: b1(3, 2), b2(3, 2)
302+
256303
check_cell_collision = .false.
257304

258305
!each point in cell1
259-
do i = 1, cell1%nlat-1
260-
do j = 1, cell1%nlon-1
306+
do i = 1, cell1%nlat
307+
do j = 1, cell1%nlon
261308

262-
!define 2 diagonal points c1p & c2p for collision detection
263-
c1p = cell1%x(i, j, : )
264-
c2p = cell1%x(i + 1, j + 1, : )
309+
! create first AABB from patch of cell1
310+
p1 = cell1%x(i, j, :)
311+
p2 = cell1%x(modulo(i, cell1%nlat) + 1, modulo(j, cell1%nlon) + 1, :)
265312

266-
!each point in cell2
267-
do i2 = 1, cell2%nlat
268-
do j2 = 1, cell2%nlon
313+
do ii = 1, 3
314+
b1(ii, 1) = min(p1(ii), p2(ii))
315+
b1(ii, 2) = max(p1(ii), p2(ii))
316+
end do
269317

270-
sp = cell2%x(i2, j2, : )
318+
!each point in cell2
319+
do i2 = 1, cell2%nlat
320+
do j2 = 1, cell2%nlon
271321

272-
!check if the cell2 point lies inside the cube delineated by c1p & c2p
322+
!create second AABB from patch of cell2
323+
p1 = cell2%x(i2, j2, :)
324+
p2 = cell2%x(modulo(i2, cell2%nlat) + 1, modulo(j2, cell2%nlon) + 1, :)
325+
do ii = 1, 3
326+
b2(ii, 1) = min(p1(ii), p2(ii))
327+
b2(ii, 2) = max(p1(ii), p2(ii))
328+
end do
329+
330+
!check for AABB collision, we find AABB intersection iff X, Y, and Z intervals all overlap
273331
if ( &
274-
((c1p(1).le.sp(1) .and. sp(1).le.c2p(1)) .or. (c2p(1).le.sp(1) .and. sp(1).le.c1p(1))) .and. & !x direction overlap
275-
((c1p(2).le.sp(2) .and. sp(2).le.c2p(2)) .or. (c2p(2).le.sp(2) .and. sp(2).le.c1p(2))) .and. & !y direction overlap
276-
((c1p(3).le.sp(3) .and. sp(3).le.c2p(3)) .or. (c2p(3).le.sp(3) .and. sp(3).le.c1p(3))) & !z direction overlap
277-
) then
278-
! since we found a collision, return true
279-
check_cell_collision = .true.
280-
return
332+
b1(1, 1) .le. b2(1, 2) &
333+
.and. b1(1, 2) .ge. b2(1, 1) &
334+
.and. b1(2, 1) .le. b2(2, 2) &
335+
.and. b1(2, 2) .ge. b2(2, 1) &
336+
.and. b1(3, 1) .le. b2(3, 2) &
337+
.and. b1(3, 2) .ge. b2(3, 1) &
338+
) then
339+
check_cell_collision = .true.
340+
return
281341
end if
282342

283-
end do !j2
284-
end do !i2
343+
end do !j2
344+
end do !i2
285345
end do !j
286346
end do !i
287-
end function check_cell_collision
288-
347+
end function check_cell_collision
289348

290349
end program randomized_cell_gen

sample_files/sample_cells/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ Examples for this usage can be found in `\examples\case_diff_celltypes\` code.
77
## `SickleCell.dat`
88
This sample file is a simplified mesh of a Sickle Cell.
99
The cell is described as a deformed prolate spheroid.
10-
The mesh's number of latitudinal modes, `nlat0`, is 12.
10+
The mesh's number of latitudinal modes, `nlat0`, is 12, and has a dealiasing factor of 3.
1111

1212
### Generating `SickleCell.dat`
1313
The Sickle Cell is generated by inducing a prolate spheroid under a flow in the RBC3D simulation for a prolonged period of time.
1414
The prolate spheroid cell is generated by the `ModRBC::RBC_MakeUncurvedSickleSpheroid` method.
15-
Then, the cell undergoes flow within a no-slip cylindrical wall for 5000 timesteps with stepsize of 0.00014.
15+
Specifics of the model are taken from ["Dynamics of deformable straight and curved prolate capsules in simple shear flow"](https://doi.org/10.1103%2FPhysRevFluids.4.043103).
16+
17+
Then, the cell undergoes flow within a no-slip cylindrical wall for 2000 timesteps with stepsize of 0.00028.
1618
The resulting mesh is exported as `SickleCell.dat`
1719

1820
## Why Import Cell Meshes?

sample_files/sample_cells/SickleCell.dat

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)