Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions doc/openfast.rst
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,8 @@ without an auxiliary process:
with ``dtM`` larger than ``DT``, the loads of the solve before it (the load predictor), so a
restart continues the run bit for bit at any ``dtM``. The accumulated range graphs (``LINES``
flag ``r``) are part of it, so a restarted run writes the range files of an uninterrupted one. A
checkpoint is accepted only on a committed CableDyn
step, so choose ``ChkptTime`` as a whole multiple of ``dtM``; a checkpoint written between two
commits stops the restart with a message that says so. On restart the module writes a
checkpoint can fall on any glue step: ``ChkptTime`` need not be a multiple of ``dtM``, and a run
restarted between two commits goes on as the uninterrupted run. On restart the module writes a
temporary deck copy, ``<RootName>.CD.rst.dat``, beside the ``MooringFile``, rebuilds the model
from it and removes it; files the deck names (``bathymetryFile``, a WaterKin file, Syrope
tables) resolve against the ``MooringFile`` folder as in the original run. Keep restart files with the exact executable and complete input set.
Expand Down
10 changes: 6 additions & 4 deletions doc/outputs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -393,10 +393,12 @@ corrects counts once, with its corrected state. The accumulators are double prec
OpenFAST build and travel in the checkpoint, so a restart continues them. The file is written at
the end of a run that completes, whenever the host ends it: at ``TMax``, at a steady state found
by ``CalcSteady``, or at FAST.Farm's last whole ``DT_Low``, and holds the samples up to there.
The run removes a file left by an earlier run when it starts; a run that stops on an error, in any
module, says so and leaves none. A turbine's own CableDyn instance in FAST.Farm (``CompMooring = 5``
in its ``.fst``) writes ``<RootName>.T<n>.CD.Line<L>.range.out``. A FAST.Farm shared mooring and
the C API write no range file and reject the flag by name.
The run removes a file left by an earlier run as soon as its deck is parsed, and a run that stops on
an error after that, in any module, leaves none. A deck that does not parse, or a module that stops
before CableDyn starts, leaves every output of the earlier run as it was. A turbine's own CableDyn
instance in FAST.Farm (``CompMooring = 5`` in its ``.fst``) writes
``<RootName>.T<n>.CD.Line<L>.range.out``. A FAST.Farm shared mooring and the C API write no range
file and reject the flag by name.

Layout: title line, header row, **units row**, then one row per node, End A first. The title reads
``CableDyn range graph (line <L>; <n> samples from t = <t0> s to t = <t1> s; public node order
Expand Down
22 changes: 20 additions & 2 deletions src/CableDyn_DeckDriver.f90
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ MODULE CableDyn_DeckDriver
CD_Sea_Parse_Train, CD_Sea_Add_Train, CD_Sea_Synthesise, CD_Sea_Kinematics
USE CableDyn_RangeOutput, ONLY: CD_RangeSet, CD_RangeLine, CD_Range_Setup, CD_Range_End, CD_Range_Needs_Sample, &
CD_Range_Commit_Sample, CD_Range_Clearance, CD_Range_TDP_Evaluate, &
CD_Range_TDP_Reference, CD_Range_Write_Files, CD_Is_TDP_Channel, &
CD_Range_TDP_Reference, CD_Range_Write_Files, CD_Range_Discard_File, &
CD_Is_TDP_Channel, &
CD_Parse_TDP_Channel, CD_RANGE_OK, CD_RANGE_BADINPUT, CD_RQ_TENSION, &
CD_RQ_CURVATURE, CD_RQ_BEND, CD_RQ_DECLINATION, CD_RQ_CLEARANCE, CD_TDP_N, &
CD_RQ_TORQUE, CD_RQ_TWIST
Expand Down Expand Up @@ -7414,7 +7415,8 @@ SUBROUTINE CD_Init_Deck_Aggregate(deck_path, dt, agg, ErrStat, ErrMsg, env_gravi
ptfm_init, external_fluid, coupled_positions, &
n_turbines, turbine_ref_pos, farm_ptfm_init, forbid_deck_ambient, run_tmax, &
range_files, host_orientation, static_current, prescribed_motion, &
static_run, deck_current, deck_turbines, static_deck_current)
static_run, deck_current, deck_turbines, static_deck_current, &
range_discard_root)
!! Parse a MIXED deck ONCE and partition its lines into {EI=0 mooring} and
!! {finite-EI cable}, returning the raw parts the OpenFAST aggregate facade wraps:
!! the EI=0 mooring SYSTEM built from the mooring subset (over ALL deck points, the
Expand Down Expand Up @@ -7485,6 +7487,11 @@ SUBROUTINE CD_Init_Deck_Aggregate(deck_path, dt, agg, ErrStat, ErrMsg, env_gravi
! standalone mixed route, the single-turbine OpenFAST module); a host that does not (a FAST.Farm
! shared mooring, the C API) leaves it out, and the flag fails closed there.
LOGICAL, INTENT(IN), OPTIONAL :: range_files
! range_discard_root: the output root of a run that starts here: the range files of an earlier
! run go as soon as the parsed deck names them, so nothing that fails after this point (the
! statics, the host's own checks) leaves one to be taken for this run's. A rebuild of a run
! already under way leaves it out.
CHARACTER(*), INTENT(IN), OPTIONAL :: range_discard_root
! host_orientation: the caller passes each moving point's orientation with every update
! (the OpenFAST and FAST.Farm shells, and the standalone mixed route, which holds the frame
! or turns it with its vesselMotion table), which turns the fairlead frame of a finite-EI
Expand Down Expand Up @@ -7575,6 +7582,17 @@ SUBROUTINE CD_Init_Deck_Aggregate(deck_path, dt, agg, ErrStat, ErrMsg, env_gravi
env_rho_water=env_rho_water, env_wtrdpth=env_wtrdpth, allow_turbine=.NOT. own_turbines, &
failures=fails, controls=ctrls, run_tmax=run_tmax, host_coupled_objects=.TRUE., &
static_run=static_run)
IF (ErrStat == CD_DECKDRV_OK .AND. PRESENT(range_discard_root)) THEN
DO i = 1, SIZE(lines)
IF (.NOT. line_output_has_flag(lines(i)%outputs, 'r')) CYCLE
CALL CD_Range_Discard_File(range_discard_root, lines(i)%id, ErrStat, ErrMsg)
IF (ErrStat /= CD_RANGE_OK) THEN
ErrStat = CD_DECKDRV_BADINPUT
RETURN
END IF
END DO
ErrStat = CD_DECKDRV_OK
END IF
IF (ErrStat == CD_DECKDRV_OK) THEN
host_turns = .FALSE.
IF (PRESENT(host_orientation)) host_turns = host_orientation
Expand Down
17 changes: 15 additions & 2 deletions src/CableDyn_OpenFAST_Aggregate.f90
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ MODULE CableDyn_OpenFAST_Aggregate
PUBLIC :: CD_AGG_WriteStaticProfile
! Range graphs of the LINES flag r: the standalone mixed route and the single-turbine OpenFAST
! module sample and write them; the accumulated state rides a host's checkpoint
PUBLIC :: CD_AGG_Reopen_Start
PUBLIC :: CD_AGG_Range_Sample, CD_AGG_Range_Write, CD_AGG_Range_Discard, CD_AGG_Range_Graphs, &
CD_AGG_Range_MirrorSize, CD_AGG_Range_Get_State, CD_AGG_Range_Set_State
PUBLIC :: CD_AGG_GetInitMetadata, CD_AGG_GetInitLine
Expand Down Expand Up @@ -296,7 +297,7 @@ SUBROUTINE CD_AGG_Init_From_Deck(self, deck_path, dt, ErrStat, ErrMsg, env_gravi
ptfm_init, external_fluid, coupled_positions, &
n_turbines, turbine_ref_pos, farm_ptfm_init, forbid_deck_ambient, run_tmax, &
range_files, host_orientation, static_current, prescribed_motion, static_run, &
deck_current, deck_turbines, static_deck_current)
deck_current, deck_turbines, static_deck_current, range_discard_root)
!! Build the aggregate from ONE mixed deck: partition its lines into {EI=0 mooring}
!! and {finite-EI cable}, wrap the mooring subset into a CD_FMF, and own one CD_HFMF
!! per cable. Same signature philosophy as CD_FMF_Init_From_Deck (host environment
Expand Down Expand Up @@ -332,6 +333,8 @@ SUBROUTINE CD_AGG_Init_From_Deck(self, deck_path, dt, ErrStat, ErrMsg, env_gravi
LOGICAL, INTENT(IN), OPTIONAL :: forbid_deck_ambient
! range_files: the caller samples and writes the range graphs of the LINES flag r (CD_AGG_Range_*)
LOGICAL, INTENT(IN), OPTIONAL :: range_files
! range_discard_root: the output root of a run that starts here (see CD_Init_Deck_Aggregate)
CHARACTER(*), INTENT(IN), OPTIONAL :: range_discard_root
! host_orientation: the caller passes the moving-point orientations with every update,
! which a finite-EI line restrained in torsion requires (see CD_Init_Deck_Aggregate)
LOGICAL, INTENT(IN), OPTIONAL :: host_orientation
Expand Down Expand Up @@ -394,7 +397,8 @@ SUBROUTINE CD_AGG_Init_From_Deck(self, deck_path, dt, ErrStat, ErrMsg, env_gravi
range_files=range_files, host_orientation=host_orientation, &
static_current=static_current, prescribed_motion=prescribed_motion, &
static_run=static_run, deck_current=deck_current, &
deck_turbines=deck_turbines, static_deck_current=static_deck_current)
deck_turbines=deck_turbines, static_deck_current=static_deck_current, &
range_discard_root=range_discard_root)
IF (PRESENT(external_fluid)) THEN
candidate%built_extfluid = external_fluid
END IF
Expand Down Expand Up @@ -3330,6 +3334,15 @@ SUBROUTINE CD_AGG_Get_Rod_States(self, states, ErrStat, ErrMsg)
IF (self%has_rod) CALL CD_Rod_Get_States(self%rod, states, ErrStat, ErrMsg)
END SUBROUTINE CD_AGG_Get_Rod_States

SUBROUTINE CD_AGG_Reopen_Start(self)
!! Back to the start of the first step after a restored state mirror, which marks the object
!! accelerations committed: a state from before the first commit keeps its start open, as the
!! run it continues does, so the fluid fields of the first step re-solve them
!! (objects_committed). Until then they stay those of the mirror.
TYPE(CD_AGG_ModuleType), INTENT(INOUT) :: self
self%objects_committed = .FALSE.
END SUBROUTINE CD_AGG_Reopen_Start

SUBROUTINE CD_AGG_Set_Rod_States(self, states, ErrStat, ErrMsg)
!! Restore the rod state and immediately scatter its end-point kinematics
!! into the EI=0 system used by restart-time output and the next advance.
Expand Down
47 changes: 30 additions & 17 deletions src/CableDyn_RangeOutput.f90
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ MODULE CableDyn_RangeOutput
PUBLIC :: CD_RangeLine, CD_RangeSet
PUBLIC :: CD_Range_Setup, CD_Range_End, CD_Range_Needs_Sample, CD_Range_Commit_Sample
PUBLIC :: CD_Range_Clearance, CD_Range_TDP_Evaluate, CD_Range_TDP_Reference
PUBLIC :: CD_Range_Write_Files, CD_Range_Discard_Files
PUBLIC :: CD_Range_Write_Files, CD_Range_Discard_Files, CD_Range_Discard_File
PUBLIC :: CD_Range_Has_Graph, CD_Range_Mirror_Size, CD_Range_Get_State, CD_Range_Set_State
PUBLIC :: CD_Is_TDP_Channel, CD_Parse_TDP_Channel

Expand Down Expand Up @@ -673,31 +673,44 @@ SUBROUTINE CD_Range_Discard_Files(set, out_root, ErrStat, ErrMsg)
CHARACTER(*), INTENT(IN) :: out_root
INTEGER, INTENT(OUT) :: ErrStat
CHARACTER(*), INTENT(OUT) :: ErrMsg
INTEGER :: il, unit, ios
CHARACTER(LEN(out_root) + 32) :: path
CHARACTER(16) :: id_text
INTEGER :: il

ErrStat = CD_RANGE_OK
ErrMsg = ''
IF (.NOT. set%active) RETURN
DO il = 1, SIZE(set%lines)
IF (.NOT. set%lines(il)%want_range) CYCLE
WRITE (id_text, '(I0)') set%lines(il)%line_id
path = TRIM(out_root)//'.Line'//TRIM(id_text)//'.range.out'
IF (.NOT. CD_Path_Openable(TRIM(path), .FALSE.)) CYCLE ! no such file
CALL CD_Open_Write(unit, TRIM(path), ios, status='OLD')
IF (ios == 0) CLOSE (unit, STATUS='DELETE', IOSTAT=ios)
IF (ios == 0) THEN
IF (CD_Path_Openable(TRIM(path), .FALSE.)) ios = 1
END IF
IF (ios /= 0) THEN
ErrStat = CD_RANGE_BADINPUT
ErrMsg = 'CableDyn_RangeOutput: cannot replace the range-graph output file of an earlier run: '//TRIM(path)
RETURN
END IF
CALL CD_Range_Discard_File(out_root, set%lines(il)%line_id, ErrStat, ErrMsg)
IF (ErrStat /= CD_RANGE_OK) RETURN
END DO
END SUBROUTINE CD_Range_Discard_Files

SUBROUTINE CD_Range_Discard_File(out_root, line_id, ErrStat, ErrMsg)
!! Remove the <out_root>.Line<line_id>.range.out file of an earlier run, if there is one.
CHARACTER(*), INTENT(IN) :: out_root
INTEGER, INTENT(IN) :: line_id
INTEGER, INTENT(OUT) :: ErrStat
CHARACTER(*), INTENT(OUT) :: ErrMsg
INTEGER :: unit, ios
CHARACTER(LEN(out_root) + 32) :: path
CHARACTER(16) :: id_text

ErrStat = CD_RANGE_OK
ErrMsg = ''
WRITE (id_text, '(I0)') line_id
path = TRIM(out_root)//'.Line'//TRIM(id_text)//'.range.out'
IF (.NOT. CD_Path_Openable(TRIM(path), .FALSE.)) RETURN ! no such file
CALL CD_Open_Write(unit, TRIM(path), ios, status='OLD')
IF (ios == 0) CLOSE (unit, STATUS='DELETE', IOSTAT=ios)
IF (ios == 0) THEN
IF (CD_Path_Openable(TRIM(path), .FALSE.)) ios = 1
END IF
IF (ios /= 0) THEN
ErrStat = CD_RANGE_BADINPUT
ErrMsg = 'CableDyn_RangeOutput: cannot replace the range-graph output file of an earlier run: '//TRIM(path)
END IF
END SUBROUTINE CD_Range_Discard_File

PURE LOGICAL FUNCTION CD_Is_TDP_Channel(lo) RESULT(yes)
!! True for a name of the TDP family (lower case), valid or not: "tdp" then a digit.
CHARACTER(*), INTENT(IN) :: lo
Expand Down
Loading
Loading