Module for writing sectional and integrated rotor results to HDF5
- fullresults.h5: cumulative file for entire simulation (open, append each write, close at end)
- results00000.h5, results00001.h5, etc.: one file per timestep (open, write, close)
/rotor_
!! Module for writing sectional and integrated rotor results to HDF5 !! - fullresults.h5: cumulative file for entire simulation (open, append each write, close at end) !! - results00000.h5, results00001.h5, etc.: one file per timestep (open, write, close) !! /rotor_<id>/ !! /geom/ geom.nml parameters for this rotor !! /integrated/ rotor-level integrated forces !! iter (nt,) !! psi (nt,) reference azimuth (blade 1) !! CL (nt,) rotor-level !! CD (nt,) !! CLu (nt,) !! CDi (nt,) !! CD0 (nt,) !! forceInertial (nt, 3) rotor force vector [N] !! lift (nt, 3) rotor lift vector [N] !! drag (nt, 3) rotor drag vector [N] !! liftUnsteady (nt, 3) !! dragInduced (nt, 3) !! dragProfile (nt, 3) !! dragUnsteady (nt, 3) !! /blade_<id>/ !! /sectional/ !! r_R (ns,) radial stations, written once at init !! iter (nt,) timestep index, extendable !! psi (nt,) azimuth per timestep, extendable !! secCL (nt, ns) extendable !! secCD (nt, ns) !! secCLu (nt, ns) !! secAlpha (nt, ns) [deg] !! secTheta (nt, ns) [deg] !! secPhi (nt, ns) [deg] !! secVel (nt, ns) !! secViz (nt, ns) !! secVix (nt, ns) !! secLift (nt, ns) magnitude per section !! secDrag (nt, ns) !! secForceInertial (nt, ns) !! secLiftInPlane (nt, ns) !! secLiftOutPlane (nt, ns) !! secChord (ns,) geometry, written once !! secArea (ns,) geometry, written once !! /integrated/ !! iter (nt,) !! psi (nt,) !! CL (nt,) blade-level !! CD (nt,) blade-level !! CLu (nt,) blade-level !! CDi (nt,) blade-level !! CD0 (nt,) blade-level !! secLift (nt,) blade-integrated magnitude !! secDrag (nt,) blade-integrated magnitude !! secForceInertial (nt,) blade-integrated magnitude !! totalArea (nt,) blade total planform area !! forceInertial (nt, 3) blade force vector [N] !! lift (nt, 3) blade lift vector [N] !! drag (nt, 3) blade drag vector [N] !! liftUnsteady (nt, 3) blade unsteady lift [N] !! dragInduced (nt, 3) blade induced drag [N] !! dragProfile (nt, 3) blade profile drag [N] !! dragUnsteady (nt, 3) blade unsteady drag [N] !! flap (nt,) [deg] !! theta (nt,) [deg] !! dflap (nt,) [deg] module libHDF5 use hdf5 use libMath, only: dp, radToDeg use classdef, only: rotor_class, switches_class use libErrorHandling implicit none contains ! ----------------------------------------------------------------------- subroutine init_hdf5(rotorArray, nt, dt, density, velSound, switches, filename, file_id) !! Create HDF5 file with extendable structure. Call before results2hdf5, then close_hdf5. type(rotor_class), intent(in), dimension(:) :: rotorArray integer, intent(in) :: nt real(dp), intent(in) :: dt, density, velSound type(switches_class), intent(in) :: switches character(len=*), intent(in) :: filename integer(HID_T), intent(out) :: file_id integer :: hdferr, ir, ib, nr integer(HID_T) :: grp_rotor, grp_rotor_int, grp_blade, grp_sec, grp_int character(len=64) :: grpname integer(HSIZE_T), parameter :: CHUNK_T = 64 nr = size(rotorArray) call h5open_f(hdferr) call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, hdferr) if (hdferr /= 0) then call raise_error(ERR_MISC, 'Failed to create HDF5 file: '//trim(filename)// & & ' (ensure Results/ directory exists)') endif call write_params(file_id, nr, nt, dt, density, velSound, switches, rotorArray) do ir = 1, nr grpname = 'rotor_'//trim(rotorArray(ir)%id) call h5gcreate_f(file_id, trim(grpname), grp_rotor, hdferr) call write_geom_params(grp_rotor, rotorArray(ir)) grpname = 'rotor_'//trim(rotorArray(ir)%id)//'/integrated' call h5gcreate_f(file_id, trim(grpname), grp_rotor_int, hdferr) call create_extendable_1d(grp_rotor_int, 'iter', CHUNK_T) call create_extendable_1d(grp_rotor_int, 'psi', CHUNK_T) call create_extendable_1d(grp_rotor_int, 'CL', CHUNK_T) call create_extendable_1d(grp_rotor_int, 'CD', CHUNK_T) call create_extendable_1d(grp_rotor_int, 'CLu', CHUNK_T) call create_extendable_1d(grp_rotor_int, 'CDi', CHUNK_T) call create_extendable_1d(grp_rotor_int, 'CD0', CHUNK_T) call create_extendable_2d(grp_rotor_int, 'forceInertial', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_rotor_int, 'lift', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_rotor_int, 'drag', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_rotor_int, 'liftUnsteady', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_rotor_int, 'dragInduced', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_rotor_int, 'dragProfile', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_rotor_int, 'dragUnsteady', CHUNK_T, 3_HSIZE_T) call h5gclose_f(grp_rotor_int, hdferr) do ib = 1, rotorArray(ir)%nbConvect grpname = 'rotor_'//trim(rotorArray(ir)%id)// & & '/blade_'//trim(rotorArray(ir)%blade(ib)%id) call h5gcreate_f(file_id, trim(grpname), grp_blade, hdferr) grpname = 'rotor_'//trim(rotorArray(ir)%id)// & & '/blade_'//trim(rotorArray(ir)%blade(ib)%id)//'/sectional' call h5gcreate_f(file_id, trim(grpname), grp_sec, hdferr) call write_fixed_1d(grp_sec, 'r_R', & rotorArray(ir)%blade(ib)%secChord / rotorArray(ir)%blade(ib)%secChord(1), & int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_1d(grp_sec, 'iter', CHUNK_T) call create_extendable_1d(grp_sec, 'psi', CHUNK_T) call create_extendable_2d(grp_sec, 'secCL', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secCD', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secCLu', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secAlpha', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secTheta', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secPhi', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secVel', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secViz', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secVix', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secLift', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secDrag', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secForceInertial', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secLiftInPlane', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call create_extendable_2d(grp_sec, 'secLiftOutPlane', CHUNK_T, int(rotorArray(ir)%ns, HSIZE_T)) call write_fixed_1d(grp_sec, 'secChord', rotorArray(ir)%blade(ib)%secChord, & int(rotorArray(ir)%ns, HSIZE_T)) call write_fixed_1d(grp_sec, 'secArea', rotorArray(ir)%blade(ib)%secArea, & int(rotorArray(ir)%ns, HSIZE_T)) call h5gclose_f(grp_sec, hdferr) grpname = 'rotor_'//trim(rotorArray(ir)%id)// & & '/blade_'//trim(rotorArray(ir)%blade(ib)%id)//'/integrated' call h5gcreate_f(file_id, trim(grpname), grp_int, hdferr) call create_extendable_1d(grp_int, 'iter', CHUNK_T) call create_extendable_1d(grp_int, 'psi', CHUNK_T) call create_extendable_1d(grp_int, 'CL', CHUNK_T) call create_extendable_1d(grp_int, 'CD', CHUNK_T) call create_extendable_1d(grp_int, 'CLu', CHUNK_T) call create_extendable_1d(grp_int, 'CDi', CHUNK_T) call create_extendable_1d(grp_int, 'CD0', CHUNK_T) call create_extendable_1d(grp_int, 'secLift', CHUNK_T) call create_extendable_1d(grp_int, 'secDrag', CHUNK_T) call create_extendable_1d(grp_int, 'secForceInertial', CHUNK_T) call create_extendable_1d(grp_int, 'totalArea', CHUNK_T) call create_extendable_2d(grp_int, 'forceInertial', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_int, 'lift', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_int, 'drag', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_int, 'liftUnsteady', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_int, 'dragInduced', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_int, 'dragProfile', CHUNK_T, 3_HSIZE_T) call create_extendable_2d(grp_int, 'dragUnsteady', CHUNK_T, 3_HSIZE_T) call create_extendable_1d(grp_int, 'flap', CHUNK_T) call create_extendable_1d(grp_int, 'theta', CHUNK_T) call create_extendable_1d(grp_int, 'dflap', CHUNK_T) call h5gclose_f(grp_int, hdferr) call h5gclose_f(grp_blade, hdferr) enddo call h5gclose_f(grp_rotor, hdferr) enddo end subroutine init_hdf5 ! ----------------------------------------------------------------------- subroutine results2hdf5(rotor, file_id, iter) !! Append one timestep of data to open HDF5 file. type(rotor_class), intent(in) :: rotor integer(HID_T), intent(in) :: file_id integer, intent(in) :: iter integer :: ib, hdferr, i integer(HID_T) :: grp_sec, grp_int, grp_rotor_int character(len=64) :: grpname real(dp) :: signLiftBlade, bladeDenom, signLiftRotor signLiftRotor = sign(1._dp, dot_product(rotor%lift, rotor%zAxisBody)) grpname = 'rotor_'//trim(rotor%id)//'/integrated' call h5gopen_f(file_id, trim(grpname), grp_rotor_int, hdferr) call append_scalar_1d(grp_rotor_int, 'iter', real(iter, dp)) call append_scalar_1d(grp_rotor_int, 'psi', rotor%blade(1)%psi) call append_scalar_1d(grp_rotor_int, 'CL', & signLiftRotor * norm2(rotor%lift) / rotor%nonDimforceDenominator) call append_scalar_1d(grp_rotor_int, 'CD', norm2(rotor%drag) / rotor%nonDimforceDenominator) call append_scalar_1d(grp_rotor_int, 'CLu', & norm2(rotor%liftUnsteady) / rotor%nonDimforceDenominator) call append_scalar_1d(grp_rotor_int, 'CDi', & norm2(rotor%dragInduced) / rotor%nonDimforceDenominator) call append_scalar_1d(grp_rotor_int, 'CD0', & norm2(rotor%dragProfile) / rotor%nonDimforceDenominator) call append_row_2d(grp_rotor_int, 'forceInertial', rotor%forceInertial) call append_row_2d(grp_rotor_int, 'lift', rotor%lift) call append_row_2d(grp_rotor_int, 'drag', rotor%drag) call append_row_2d(grp_rotor_int, 'liftUnsteady', rotor%liftUnsteady) call append_row_2d(grp_rotor_int, 'dragInduced', rotor%dragInduced) call append_row_2d(grp_rotor_int, 'dragProfile', rotor%dragProfile) call append_row_2d(grp_rotor_int, 'dragUnsteady', rotor%dragUnsteady) call h5gclose_f(grp_rotor_int, hdferr) do ib = 1, rotor%nbConvect signLiftBlade = sign(1._dp, dot_product(rotor%blade(ib)%lift, rotor%zAxisBody)) bladeDenom = rotor%nonDimforceDenominator / real(rotor%nbConvect, dp) grpname = 'rotor_'//trim(rotor%id)//'/blade_'//trim(rotor%blade(ib)%id)//'/sectional' call h5gopen_f(file_id, trim(grpname), grp_sec, hdferr) call append_scalar_1d(grp_sec, 'iter', real(iter, dp)) call append_scalar_1d(grp_sec, 'psi', rotor%blade(ib)%psi) call append_row_2d(grp_sec, 'secCL', rotor%blade(ib)%secCL) call append_row_2d(grp_sec, 'secCD', rotor%blade(ib)%secCD) call append_row_2d(grp_sec, 'secCLu', rotor%blade(ib)%secCLu) call append_row_2d(grp_sec, 'secAlpha', rotor%blade(ib)%secAlpha * radToDeg) call append_row_2d(grp_sec, 'secTheta', rotor%blade(ib)%secTheta * radToDeg) call append_row_2d(grp_sec, 'secPhi', rotor%blade(ib)%secPhi * radToDeg) call append_row_2d(grp_sec, 'secVel', & [(norm2(rotor%blade(ib)%secChordwiseResVel(:, i)), i=1, rotor%ns)]) call append_row_2d(grp_sec, 'secViz', rotor%blade(ib)%secViz) call append_row_2d(grp_sec, 'secVix', rotor%blade(ib)%secVix) call append_row_2d(grp_sec, 'secLift', & [(norm2(rotor%blade(ib)%secLift(:, i)), i=1, rotor%ns)]) call append_row_2d(grp_sec, 'secDrag', & [(norm2(rotor%blade(ib)%secDrag(:, i)), i=1, rotor%ns)]) call append_row_2d(grp_sec, 'secForceInertial', & [(norm2(rotor%blade(ib)%secForceInertial(:, i)), i=1, rotor%ns)]) call append_row_2d(grp_sec, 'secLiftInPlane', & [(norm2(rotor%blade(ib)%secLiftInPlane(:, i)), i=1, rotor%ns)]) call append_row_2d(grp_sec, 'secLiftOutPlane', & [(norm2(rotor%blade(ib)%secLiftOutPlane(:, i)), i=1, rotor%ns)]) call h5gclose_f(grp_sec, hdferr) grpname = 'rotor_'//trim(rotor%id)//'/blade_'//trim(rotor%blade(ib)%id)//'/integrated' call h5gopen_f(file_id, trim(grpname), grp_int, hdferr) call append_scalar_1d(grp_int, 'iter', real(iter, dp)) call append_scalar_1d(grp_int, 'psi', rotor%blade(ib)%psi) call append_scalar_1d(grp_int, 'CL', & signLiftBlade * norm2(rotor%blade(ib)%lift) / bladeDenom) call append_scalar_1d(grp_int, 'CD', norm2(rotor%blade(ib)%drag) / bladeDenom) call append_scalar_1d(grp_int, 'CLu', & norm2(rotor%blade(ib)%liftUnsteady) / bladeDenom) call append_scalar_1d(grp_int, 'CDi', & norm2(rotor%blade(ib)%dragInduced) / bladeDenom) call append_scalar_1d(grp_int, 'CD0', & norm2(rotor%blade(ib)%dragProfile) / bladeDenom) call append_scalar_1d(grp_int, 'secLift', norm2(rotor%blade(ib)%lift)) call append_scalar_1d(grp_int, 'secDrag', norm2(rotor%blade(ib)%drag)) call append_scalar_1d(grp_int, 'secForceInertial', norm2(rotor%blade(ib)%forceInertial)) call append_scalar_1d(grp_int, 'totalArea', sum(rotor%blade(ib)%secArea)) call append_row_2d(grp_int, 'forceInertial', rotor%blade(ib)%forceInertial) call append_row_2d(grp_int, 'lift', rotor%blade(ib)%lift) call append_row_2d(grp_int, 'drag', rotor%blade(ib)%drag) call append_row_2d(grp_int, 'liftUnsteady', rotor%blade(ib)%liftUnsteady) call append_row_2d(grp_int, 'dragInduced', rotor%blade(ib)%dragInduced) call append_row_2d(grp_int, 'dragProfile', rotor%blade(ib)%dragProfile) call append_row_2d(grp_int, 'dragUnsteady', rotor%blade(ib)%dragUnsteady) call append_scalar_1d(grp_int, 'flap', rotor%blade(ib)%flap * radToDeg) call append_scalar_1d(grp_int, 'theta', rotor%blade(ib)%theta * radToDeg) call append_scalar_1d(grp_int, 'dflap', rotor%blade(ib)%dflap * radToDeg) call h5gclose_f(grp_int, hdferr) enddo end subroutine results2hdf5 ! ----------------------------------------------------------------------- subroutine close_hdf5(file_id) !! Flush and close HDF5 file. Call after results2hdf5. integer(HID_T), intent(in) :: file_id integer :: hdferr call h5fflush_f(file_id, H5F_SCOPE_LOCAL_F, hdferr) call h5fclose_f(file_id, hdferr) end subroutine close_hdf5 ! ----------------------------------------------------------------------- subroutine deinit_hdf5(file_id) !! Deinitialize HDF5 library (h5close_f). file_id unused (kept for API). integer(HID_T), intent(in) :: file_id integer :: hdferr call h5close_f(hdferr) end subroutine deinit_hdf5 ! ======================================================================= ! Private helper routines ! ======================================================================= subroutine write_geom_params(grp_rotor_id, rotor) !! Write geom.nml parameters to geom sub-group under the rotor integer(HID_T), intent(in) :: grp_rotor_id type(rotor_class), intent(in) :: rotor integer :: hdferr integer(HID_T) :: grp_params call h5gcreate_f(grp_rotor_id, 'geom', grp_params, hdferr) ! SURFACE call write_scalar_int(grp_params, 'surfaceType', rotor%surfaceType) call write_scalar_int(grp_params, 'imagePlane', rotor%imagePlane) call write_scalar_int(grp_params, 'imageRotorNum', rotor%imageRotorNum) ! PANELS call write_scalar_int(grp_params, 'nb', rotor%nb) call write_scalar_int(grp_params, 'propConvention', rotor%propConvention) call write_scalar_int(grp_params, 'spanSpacing', rotor%spanSpacing) call write_scalar_int(grp_params, 'chordSpacing', rotor%chordSpacing) call write_scalar_int(grp_params, 'nCamberFiles', rotor%nCamberFiles) call write_scalar_int(grp_params, 'nc', rotor%nc) call write_scalar_int(grp_params, 'ns', rotor%ns) call write_scalar_int(grp_params, 'nNwake', rotor%nNwake) ! ORIENT call write_vector_3d(grp_params, 'hubCoords', rotor%hubCoords) call write_vector_3d(grp_params, 'cgCoords', rotor%cgCoords) call write_vector_3d(grp_params, 'fromCoords', rotor%fromCoords) call write_vector_3d(grp_params, 'phiThetaPsi', rotor%pts) ! GEOMPARAMS call write_scalar_double(grp_params, 'radius', rotor%radius) call write_scalar_double(grp_params, 'root_cut', rotor%root_cut) call write_scalar_double(grp_params, 'chord', rotor%chord) call write_scalar_double(grp_params, 'preconeAngle', rotor%preconeAngle*radToDeg) call write_scalar_double(grp_params, 'Omega', rotor%Omega) call write_vector_3d(grp_params, 'shaftAxis', rotor%shaftAxis) call write_scalar_double(grp_params, 'theta0', rotor%controlPitch(1)*radToDeg) call write_scalar_double(grp_params, 'thetaC', rotor%controlPitch(2)*radToDeg) call write_scalar_double(grp_params, 'thetaS', rotor%controlPitch(3)*radToDeg) call write_scalar_double(grp_params, 'thetaTwist', rotor%thetaTwist*radToDeg) call write_scalar_int(grp_params, 'ductSwitch', rotor%ductSwitch) call write_scalar_int(grp_params, 'axisymmetrySwitch', rotor%axisymmetrySwitch) call write_scalar_double(grp_params, 'pivotLE', rotor%pivotLE) call write_scalar_double(grp_params, 'flapHinge', rotor%flapHinge) call write_scalar_int(grp_params, 'spanwiseLiftSwitch', rotor%spanwiseLiftSwitch) call write_scalar_int(grp_params, 'symmetricTau', rotor%symmetricTau) call write_scalar_int(grp_params, 'customTrajectorySwitch', rotor%customTrajectorySwitch) call write_vector_3d(grp_params, 'velBody', rotor%velBody) call write_vector_3d(grp_params, 'omegaBody', rotor%omegaBody) call write_scalar_int(grp_params, 'forceCalcSwitch', rotor%forceCalcSwitch) call write_scalar_int(grp_params, 'nAirfoils', rotor%nAirfoils) ! WAKEPARAMS call write_scalar_double(grp_params, 'apparentViscCoeff', rotor%apparentViscCoeff) call write_scalar_double(grp_params, 'decayCoeff', rotor%decayCoeff) call write_scalar_double(grp_params, 'wakeDispLimitFactor', rotor%wakeDispLimitFactor) call write_scalar_int(grp_params, 'wakeTruncateNt', rotor%wakeTruncateNt) call write_scalar_int(grp_params, 'prescWakeAfterTruncNt', rotor%prescWakeAfterTruncNt) call write_scalar_int(grp_params, 'prescWakeGenNt', rotor%prescWakeGenNt) call write_scalar_double(grp_params, 'spanwiseCore', rotor%spanwiseCore) call write_scalar_double(grp_params, 'rollupStartRadius', rotor%rollupStartRadius) call write_scalar_double(grp_params, 'rollupEndRadius', rotor%rollupEndRadius) call write_scalar_double(grp_params, 'initWakeVel', rotor%initWakeVel) call write_scalar_double(grp_params, 'psiStart', rotor%psiStart*radToDeg) call write_scalar_double(grp_params, 'skewLimit', rotor%skewLimit) ! DYNAMICS call write_scalar_int(grp_params, 'bladeDynamicsSwitch', rotor%bladeDynamicsSwitch) call write_scalar_double(grp_params, 'flapInitial', rotor%flapInitial) call write_scalar_double(grp_params, 'dflapInitial', rotor%dflapInitial) call write_scalar_double(grp_params, 'Iflap', rotor%Iflap) call write_scalar_double(grp_params, 'cflap', rotor%cflap) call write_scalar_double(grp_params, 'kflap', rotor%kflap) call write_scalar_double(grp_params, 'MflapConstant', rotor%MflapConstant) call write_scalar_double(grp_params, 'flap0', rotor%flap0*radToDeg) call write_scalar_double(grp_params, 'flapC', rotor%flapC*radToDeg) call write_scalar_double(grp_params, 'flapS', rotor%flapS*radToDeg) call write_scalar_int(grp_params, 'pitchDynamicsSwitch', rotor%pitchDynamicsSwitch) call write_scalar_double(grp_params, 'dpitch', rotor%dpitch) call write_scalar_int(grp_params, 'bodyDynamicsSwitch', rotor%bodyDynamicsSwitch) call write_scalar_int(grp_params, 'bodyDynamicsIOVars', rotor%bodyDynamicsIOVars) ! WINDFRAME call write_vector_3d(grp_params, 'dragUnitVec', rotor%dragUnitVec) call write_vector_3d(grp_params, 'sideUnitVec', rotor%sideUnitVec) call write_vector_3d(grp_params, 'liftUnitVec', rotor%liftUnitVec) ! Derived / computed call write_scalar_double(grp_params, 'nonDimForceDenom', rotor%nonDimforceDenominator) if (rotor%nAirfoils > 0) then call write_scalar_double(grp_params, 'alpha0', rotor%alpha0(1)) else call write_scalar_double(grp_params, 'alpha0', 0._dp) endif call h5gclose_f(grp_params, hdferr) end subroutine write_geom_params subroutine write_params(file_id, nr, nt, dt, density, velSound, switches, rotorArray) integer(HID_T), intent(in) :: file_id integer, intent(in) :: nr, nt real(dp), intent(in) :: dt, density, velSound type(switches_class), intent(in) :: switches type(rotor_class), intent(in), dimension(:) :: rotorArray integer :: hdferr integer(HID_T) :: grp_params call h5gcreate_f(file_id, 'params', grp_params, hdferr) ! Config (matching params2file) call write_scalar_int(grp_params, 'nt', nt) call write_scalar_double(grp_params, 'dt', dt) call write_scalar_int(grp_params, 'nr', nr) call write_scalar_int(grp_params, 'restartWriteNt', switches%restartWriteNt) call write_scalar_int(grp_params, 'restartFromNt', switches%restartFromNt) call write_scalar_int(grp_params, 'hdf5WriteNt', switches%hdf5WriteNt) call write_scalar_int(grp_params, 'ntSub', switches%ntSub) call write_scalar_int(grp_params, 'ntSubInit', switches%ntSubInit) call write_scalar_double(grp_params, 'density', density) call write_scalar_double(grp_params, 'velSound', velSound) call write_scalar_int(grp_params, 'wakePlot', switches%wakePlot) call write_scalar_int(grp_params, 'wakeTipPlot', switches%wakeTipPlot) call write_scalar_int(grp_params, 'rotorForcePlot', switches%rotorForcePlot) call write_scalar_int(grp_params, 'gridPlot', switches%gridPlot) call write_scalar_int(grp_params, 'wakeDissipation', switches%wakeDissipation) call write_scalar_int(grp_params, 'wakeStrain', switches%wakeStrain) call write_scalar_int(grp_params, 'wakeBurst', switches%wakeBurst) call write_scalar_int(grp_params, 'slowStart', switches%slowStart) call write_scalar_int(grp_params, 'slowStartNt', switches%slowStartNt) call write_scalar_int(grp_params, 'fdScheme', switches%fdScheme) call write_scalar_int(grp_params, 'initWakeVelNt', switches%initWakeVelNt) call write_scalar_int(grp_params, 'probe', switches%probe) ! Per-rotor geom params are in /rotor_<id>/geom/ call h5gclose_f(grp_params, hdferr) end subroutine write_params subroutine write_scalar_int(grp_id, dsetname, val) integer(HID_T), intent(in) :: grp_id character(len=*), intent(in) :: dsetname integer, intent(in) :: val integer(HID_T) :: dspace_id, dset_id integer(HSIZE_T), dimension(1) :: dims integer :: hdferr dims(1) = 1 call h5screate_simple_f(1, dims, dspace_id, hdferr) call h5dcreate_f(grp_id, dsetname, H5T_NATIVE_INTEGER, dspace_id, dset_id, hdferr) call h5dwrite_f(dset_id, H5T_NATIVE_INTEGER, [val], dims, hdferr) call h5dclose_f(dset_id, hdferr) call h5sclose_f(dspace_id, hdferr) end subroutine write_scalar_int subroutine write_scalar_double(grp_id, dsetname, val) integer(HID_T), intent(in) :: grp_id character(len=*), intent(in) :: dsetname real(dp), intent(in) :: val integer(HID_T) :: dspace_id, dset_id integer(HSIZE_T), dimension(1) :: dims integer :: hdferr dims(1) = 1 call h5screate_simple_f(1, dims, dspace_id, hdferr) call h5dcreate_f(grp_id, dsetname, H5T_NATIVE_DOUBLE, dspace_id, dset_id, hdferr) call h5dwrite_f(dset_id, H5T_NATIVE_DOUBLE, [val], dims, hdferr) call h5dclose_f(dset_id, hdferr) call h5sclose_f(dspace_id, hdferr) end subroutine write_scalar_double subroutine write_vector_3d(grp_id, dsetname, vec) integer(HID_T), intent(in) :: grp_id character(len=*), intent(in) :: dsetname real(dp), intent(in), dimension(3) :: vec integer(HID_T) :: dspace_id, dset_id integer(HSIZE_T), dimension(1) :: dims integer :: hdferr dims(1) = 3 call h5screate_simple_f(1, dims, dspace_id, hdferr) call h5dcreate_f(grp_id, dsetname, H5T_NATIVE_DOUBLE, dspace_id, dset_id, hdferr) call h5dwrite_f(dset_id, H5T_NATIVE_DOUBLE, vec, dims, hdferr) call h5dclose_f(dset_id, hdferr) call h5sclose_f(dspace_id, hdferr) end subroutine write_vector_3d subroutine write_fixed_1d(grp_id, dsetname, data, n) !! Write a fixed-size 1D dataset (not extendable) -- used for r_R integer(HID_T), intent(in) :: grp_id character(len=*), intent(in) :: dsetname real(dp), intent(in), dimension(:) :: data integer(HSIZE_T), intent(in) :: n integer(HID_T) :: dspace_id, dset_id integer(HSIZE_T), dimension(1) :: dims integer :: hdferr dims(1) = n call h5screate_simple_f(1, dims, dspace_id, hdferr) call h5dcreate_f(grp_id, dsetname, H5T_NATIVE_DOUBLE, & dspace_id, dset_id, hdferr) call h5dwrite_f(dset_id, H5T_NATIVE_DOUBLE, data, dims, hdferr) call h5dclose_f(dset_id, hdferr) call h5sclose_f(dspace_id, hdferr) end subroutine write_fixed_1d subroutine write_fixed_2d(grp_id, dsetname, data, nrows, ncols) !! Write a fixed-size 2D dataset (1 x ncols) for snapshot files integer(HID_T), intent(in) :: grp_id character(len=*), intent(in) :: dsetname real(dp), intent(in), dimension(:) :: data integer(HSIZE_T), intent(in) :: nrows, ncols integer(HID_T) :: dspace_id, dset_id integer(HSIZE_T), dimension(2) :: dims integer :: hdferr dims = [ncols, nrows] ! Fortran column-major order call h5screate_simple_f(2, dims, dspace_id, hdferr) call h5dcreate_f(grp_id, dsetname, H5T_NATIVE_DOUBLE, & dspace_id, dset_id, hdferr) call h5dwrite_f(dset_id, H5T_NATIVE_DOUBLE, data, dims, hdferr) call h5dclose_f(dset_id, hdferr) call h5sclose_f(dspace_id, hdferr) end subroutine write_fixed_2d ! ----------------------------------------------------------------------- subroutine create_extendable_1d(grp_id, dsetname, chunk_size) !! Create an extendable 1D dataset of shape (0,) with unlimited max dim integer(HID_T), intent(in) :: grp_id character(len=*), intent(in) :: dsetname integer(HSIZE_T), intent(in) :: chunk_size integer(HID_T) :: dspace_id, dset_id, dcpl_id integer(HSIZE_T), dimension(1) :: dims, maxdims, chunk_dims integer :: hdferr dims(1) = 0 maxdims(1) = H5S_UNLIMITED_F chunk_dims(1) = chunk_size call h5screate_simple_f(1, dims, dspace_id, hdferr, maxdims) call h5pcreate_f(H5P_DATASET_CREATE_F, dcpl_id, hdferr) call h5pset_chunk_f(dcpl_id, 1, chunk_dims, hdferr) call h5dcreate_f(grp_id, dsetname, H5T_NATIVE_DOUBLE, & dspace_id, dset_id, hdferr, dcpl_id) call h5dclose_f(dset_id, hdferr) call h5pclose_f(dcpl_id, hdferr) call h5sclose_f(dspace_id, hdferr) end subroutine create_extendable_1d ! ----------------------------------------------------------------------- subroutine create_extendable_2d(grp_id, dsetname, chunk_t, ns) !! Create an extendable 2D dataset of shape (0, ns) -- time x span integer(HID_T), intent(in) :: grp_id character(len=*), intent(in) :: dsetname integer(HSIZE_T), intent(in) :: chunk_t, ns integer(HID_T) :: dspace_id, dset_id, dcpl_id integer(HSIZE_T), dimension(2) :: dims, maxdims, chunk_dims integer :: hdferr dims = [0_HSIZE_T, ns] maxdims = [H5S_UNLIMITED_F, ns] chunk_dims = [chunk_t, ns] call h5screate_simple_f(2, dims, dspace_id, hdferr, maxdims) call h5pcreate_f(H5P_DATASET_CREATE_F, dcpl_id, hdferr) call h5pset_chunk_f(dcpl_id, 2, chunk_dims, hdferr) call h5dcreate_f(grp_id, dsetname, H5T_NATIVE_DOUBLE, & dspace_id, dset_id, hdferr, dcpl_id) call h5dclose_f(dset_id, hdferr) call h5pclose_f(dcpl_id, hdferr) call h5sclose_f(dspace_id, hdferr) end subroutine create_extendable_2d ! ----------------------------------------------------------------------- subroutine append_scalar_1d(grp_id, dsetname, val) !! Append a single scalar to an extendable 1D dataset integer(HID_T), intent(in) :: grp_id character(len=*), intent(in) :: dsetname real(dp), intent(in) :: val integer(HID_T) :: dset_id, dspace_id, memspace_id integer(HSIZE_T), dimension(1) :: cur_dims, new_dims, offset, count integer :: hdferr call h5dopen_f(grp_id, dsetname, dset_id, hdferr) call h5dget_space_f(dset_id, dspace_id, hdferr) call h5sget_simple_extent_dims_f(dspace_id, cur_dims, new_dims, hdferr) new_dims(1) = cur_dims(1) + 1 call h5dset_extent_f(dset_id, new_dims, hdferr) call h5dget_space_f(dset_id, dspace_id, hdferr) offset(1) = cur_dims(1) count(1) = 1 call h5sselect_hyperslab_f(dspace_id, H5S_SELECT_SET_F, & offset, count, hdferr) call h5screate_simple_f(1, count, memspace_id, hdferr) call h5dwrite_f(dset_id, H5T_NATIVE_DOUBLE, [val], count, hdferr, & memspace_id, dspace_id) call h5sclose_f(memspace_id, hdferr) call h5sclose_f(dspace_id, hdferr) call h5dclose_f(dset_id, hdferr) end subroutine append_scalar_1d ! ----------------------------------------------------------------------- subroutine append_row_2d(grp_id, dsetname, row) !! Append a 1D array as a new row in an extendable 2D dataset (nt x ns) integer(HID_T), intent(in) :: grp_id character(len=*), intent(in) :: dsetname real(dp), intent(in), dimension(:) :: row integer(HID_T) :: dset_id, dspace_id, memspace_id integer(HSIZE_T), dimension(2) :: cur_dims, max_dims, new_dims, offset, count integer :: hdferr integer(HSIZE_T) :: ns ns = int(size(row), HSIZE_T) call h5dopen_f(grp_id, dsetname, dset_id, hdferr) call h5dget_space_f(dset_id, dspace_id, hdferr) call h5sget_simple_extent_dims_f(dspace_id, cur_dims, max_dims, hdferr) new_dims = [cur_dims(1) + 1, ns] call h5dset_extent_f(dset_id, new_dims, hdferr) call h5dget_space_f(dset_id, dspace_id, hdferr) offset = [cur_dims(1), 0_HSIZE_T] count = [1_HSIZE_T, ns] call h5sselect_hyperslab_f(dspace_id, H5S_SELECT_SET_F, & offset, count, hdferr) call h5screate_simple_f(2, count, memspace_id, hdferr) call h5dwrite_f(dset_id, H5T_NATIVE_DOUBLE, row, count, hdferr, & memspace_id, dspace_id) call h5sclose_f(memspace_id, hdferr) call h5sclose_f(dspace_id, hdferr) call h5dclose_f(dset_id, hdferr) end subroutine append_row_2d end module libHDF5