Skip to content

Commit c3ea065

Browse files
committed
Document the force history columns and offsets in case.md instead of a sidecar file
1 parent bbb5d02 commit c3ea065

2 files changed

Lines changed: 29 additions & 14 deletions

File tree

docs/documentation/case.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,31 @@ If `file_per_process` is true, then pre_process, simulation, and post_process mu
809809

810810
- `probe_wrt` activates the output of state variables at coordinates specified by `probe(i)%[x;y,z]`.
811811

812-
- `ib_state_wrt` is used to trigger post-processing of the IB state to be written out as a point mesh in the SILO files. When no IBs are moving, it also triggers force and torque calculation so that those values may be written to the output state files. It also records one line per time step in `D/ib<id>_forces.dat` for each immersed boundary (time step, time, force, torque, velocity, angular velocity, angles, centroid). Records are buffered and written in batches rather than opened per step, and `ib_force_stride` writes only every N-th step for runs long enough that the record itself becomes large.
812+
- `ib_state_wrt` is used to trigger post-processing of the IB state to be written out as a point mesh in the SILO files. When no IBs are moving, it also triggers force and torque calculation so that those values may be written to the output state files. It also records the force, torque and kinematics of every immersed boundary in a single shared text file, `D/ib_forces.dat`, described below. `ib_force_stride` writes only every N-th step, for runs long enough that the history itself becomes large.
813+
814+
#### Immersed-boundary force history {#sec-ib-force-history}
815+
816+
`D/ib_forces.dat` holds one fixed-width record per body per written step. Its twenty columns are
817+
818+
| Columns | Quantity |
819+
| ---: | :--- |
820+
| 1 | body id (the global `patch_ib` index) |
821+
| 2 | time |
822+
| 3–5 | force, x/y/z |
823+
| 6–8 | torque, x/y/z |
824+
| 9–11 | velocity, x/y/z |
825+
| 12–14 | angular velocity, x/y/z |
826+
| 15–17 | angles about x/y/z |
827+
| 18–20 | centroid, x/y/z |
828+
829+
The file carries no header line, because every record sits at a computed byte offset and a header would shift them all. Each record is exactly 353 bytes including its newline (`I10` followed by nineteen `1X,ES17.9E3` fields), so the whole file loads with `numpy.loadtxt` and a single body or step can be read without scanning it:
830+
831+
```
832+
row = t_step / ib_force_stride
833+
offset = (row * num_ibs + ib_id - 1) * 353
834+
```
835+
836+
Rows are written in global body-id order, so the file is byte-identical however the domain is decomposed, and no merge step is needed after a parallel run.
813837

814838
- `output_partial_domain` activates the output of part of the domain specified by `[x,y,z]_output%%beg` and `[x,y,z]_output%%end`.
815839
This is useful for large domains where only a portion of the domain is of interest.

src/simulation/m_data_output.fpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,8 +1122,8 @@ contains
11221122
!! 3e5 filesystem metadata operations per step at 1000 ranks holding 100 bodies each.
11231123
!!
11241124
!! Layout: row r = t_step/ib_force_stride holds all num_gbl_ibs bodies in global id order, so
1125-
!! body g occupies bytes ((r*num_gbl_ibs) + g - 1)*IB_REC_LEN. Column order is documented in
1126-
!! D/ib_forces.hdr rather than in a header line, which would shift every offset after it.
1125+
!! body g occupies bytes ((r*num_gbl_ibs) + g - 1)*IB_REC_LEN. The file carries no header line,
1126+
!! which would shift every offset after it; the columns are listed in docs/documentation/case.md.
11271127
impure subroutine s_write_ib_force_history(t_step)
11281128
11291129
integer, intent(in) :: t_step
@@ -1176,12 +1176,12 @@ contains
11761176
11771177
end subroutine s_write_ib_force_history
11781178
1179-
!> Open the shared history file and drop a sibling naming its columns. Both are done once.
1179+
!> Open the shared history file. Done once for the run.
11801180
impure subroutine s_open_ib_force_history
11811181
11821182
character(LEN=path_len + 2*name_len) :: file_loc
11831183
character(LEN=IB_REC_LEN) :: probe
1184-
integer :: hdr, i
1184+
integer :: i
11851185
11861186
#ifdef MFC_MPI
11871187
integer :: ierr
@@ -1197,15 +1197,6 @@ contains
11971197
@:PROHIBIT(len_trim(probe) /= IB_REC_BODY, &
11981198
& "IB force record width disagrees with IB_REC_BODY; IB_REC_FMT and IB_REC_BODY must be changed together")
11991199
1200-
if (proc_rank == 0) then
1201-
file_loc = trim(case_dir) // '/D/ib_forces.hdr'
1202-
open (newunit=hdr, file=trim(file_loc), form='formatted', status='replace')
1203-
write (hdr, '(A)') 'ib_id time Fx Fy Fz Tx Ty Tz vx vy vz wx wy wz ax ay az xc yc zc'
1204-
write (hdr, '(A,I0,A)') 'record ', IB_REC_LEN, ' bytes; row = t_step/ib_force_stride'
1205-
write (hdr, '(A)') 'offset(step,body) = (row*num_gbl_ibs + ib_id - 1)*record'
1206-
close (hdr)
1207-
end if
1208-
12091200
file_loc = trim(case_dir) // '/D/ib_forces.dat'
12101201
#ifdef MFC_MPI
12111202
! MPI_MODE_CREATE does not truncate, so a shorter run following a longer one in the same

0 commit comments

Comments
 (0)