diff --git a/.github/scripts/check_tabs.sh b/.github/scripts/check_tabs.sh new file mode 100755 index 0000000000..12efaa92c5 --- /dev/null +++ b/.github/scripts/check_tabs.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +# +# check_tabs.sh -- verify that no Fortran source file contains tab characters. +# +# OpenFAST style requires 3-space indentation; tab characters are not allowed +# because they render inconsistently across editors and break the alignment of +# continuation lines. +# +# Scans every git-tracked *.f90 / *.F90 file, with no exclusions. When a tab is +# found in a file generated by the OpenFAST Registry, the report says so and +# points at the registry input, since the fix belongs in the .txt rather than in +# the generated Fortran. +# +# Exit status: +# 0 no tab characters found +# 1 one or more tab characters found +# 2 the check could not run (not a git checkout, or a file failed to scan) +# +set -uo pipefail + +TAB=$(printf '\t') +MARK='--->' + +repo_root=$(git rev-parse --show-toplevel) || { + echo "ERROR: not inside a git checkout; cannot determine repository root." + exit 2 +} +cd "$repo_root" || exit 2 + +echo "OpenFAST Fortran source style check" +echo "===================================" +echo +echo "OpenFAST style requires 3 space indentation in all Fortran source files." +echo "Tab characters are not allowed." +echo + +mapfile -t FILES < <(git ls-files -- '*.f90' '*.F90' | sort) + +if [ "${#FILES[@]}" -eq 0 ]; then + echo "ERROR: no Fortran source files found -- is this a git checkout?" + exit 2 +fi + +n_bad_files=0 +n_bad_lines=0 + +for file in "${FILES[@]}"; do + # grep exits 0 on a match, 1 on no match, and >1 on an actual error. + # Only "no match" may be skipped; a scan failure must not look like a pass. + matches=$(grep -n -- "$TAB" "$file") + status=$? + if [ "$status" -eq 1 ]; then + continue + elif [ "$status" -ne 0 ]; then + echo "ERROR: failed to scan ${file} (grep exit ${status})." + exit 2 + fi + + n_bad_files=$((n_bad_files + 1)) + echo "$file" + + while IFS= read -r match; do + lineno=${match%%:*} + content=${match#*:} + + # Compute the column with parameter expansion rather than awk: "awk -v" + # decodes backslash escapes in the assigned value, which shifts the index + # on any line containing a backslash (Doxygen markup, format strings). + prefix=${content%%$TAB*} + column=$(( ${#prefix} + 1 )) + n_bad_lines=$((n_bad_lines + 1)) + + printf ' line %s, column %s: %s\n' "$lineno" "$column" "${content//$TAB/$MARK}" + + # Inline annotation on the pull request diff. + if [ "${GITHUB_ACTIONS:-}" = "true" ]; then + echo "::error file=${file},line=${lineno},col=${column}::Tab character found. Use 3 space indentation; tabs are not allowed." + fi + done <<< "$matches" + + # A tab in a Registry-generated file cannot be fixed in place: it was copied + # from a description string in the registry input, so point the developer + # there instead. + if head -n 1 "$file" 2>/dev/null | grep -q 'STARTOFREGISTRYGENERATEDFILE'; then + echo " NOTE: this file is generated by the OpenFAST Registry. Fix the tab in" + echo " the corresponding registry input (.txt) in the same directory," + echo " then regenerate this file." + fi + + echo +done + +echo "Checked ${#FILES[@]} Fortran source file(s)." + +if [ "$n_bad_files" -gt 0 ]; then + echo + echo "ERROR: found ${n_bad_lines} line(s) containing tab characters in ${n_bad_files} file(s)." + echo " Replace each tab with spaces (3 space indentation) and commit the fix." + echo " Tabs above are shown as '${MARK}'." + exit 1 +fi + +echo "No tab characters found." +exit 0 diff --git a/.github/workflows/check-tabs.yml b/.github/workflows/check-tabs.yml new file mode 100644 index 0000000000..957d063070 --- /dev/null +++ b/.github/workflows/check-tabs.yml @@ -0,0 +1,36 @@ + +name: 'Fortran Source Style' + +#------------------------------------------------------------------------------- +# Notes +# - OpenFAST requires 3 space indentation in Fortran source; tab characters are +# not allowed. This workflow enforces that rule on all git-tracked *.f90 and +# *.F90 files. +# - No files are excluded from the scan. A tab in a Registry-generated file is +# reported with a note pointing at the registry .txt input, since that is +# where it has to be fixed. +#------------------------------------------------------------------------------- + +on: + push: + paths: + - '**.f90' + - '**.F90' + - '.github/workflows/check-tabs.yml' + - '.github/scripts/check_tabs.sh' + + pull_request: + types: [opened, synchronize, edited, reopened] + +jobs: + check-tabs: + name: Check for tab characters + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: false + + - name: Check Fortran source for tab characters + run: .github/scripts/check_tabs.sh diff --git a/cmake/OpenfastFortranOptions.cmake b/cmake/OpenfastFortranOptions.cmake index b93e027a5c..667753a4e1 100644 --- a/cmake/OpenfastFortranOptions.cmake +++ b/cmake/OpenfastFortranOptions.cmake @@ -133,10 +133,10 @@ macro(set_fast_gfortran) set( CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -fcheck=all,no-array-temps -pedantic -fbacktrace -finit-real=inf -finit-integer=9999." ) endif() - if(CYGWIN) - # increase the default 2MB stack size to 16 MB + if(CYGWIN OR MINGW) + # increase the default 1-2 MB stack size to 16 MB MATH(EXPR stack_size "16 * 1024 * 1024") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},--stack,${stack_size}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,${stack_size}") endif() # Profiling diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index 9da727a7bd..eba033d71d 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -6119,8 +6119,9 @@ SUBROUTINE TwrInflArray( p, u, RotInflow, m, Positions, Inflow, ErrStat, ErrMsg ! these models are valid for only small tower deflections; check for potential division-by-zero errors: call CheckTwrInfl( u, ErrStat2, ErrMsg2 ); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ); if (ErrStat >= AbortErrLev) return + ! FirstWarn_TowerStrike is firstprivate so each thread starts from the .false. set above (avoids reading uninitialized memory); ErrStat2/ErrMsg2 are private to avoid a data race !$OMP PARALLEL default(shared) - !$OMP do private(i,Pos,theta_tower_trans,W_tower,xbar,ybar,zbar,TwrCd,TwrTI,TwrClrnc,FirstWarn_TowerStrike,DisturbInflow,v) schedule(runtime) + !$OMP do private(i,Pos,theta_tower_trans,W_tower,xbar,ybar,zbar,TwrCd,TwrTI,TwrClrnc,DisturbInflow,v,ErrStat2,ErrMsg2) firstprivate(FirstWarn_TowerStrike) schedule(runtime) do i = 1, size(Positions,2) Pos=Positions(1:3,i) @@ -7737,6 +7738,9 @@ subroutine PerturbFlowField(Var, BaseFF, PerturbSign, PerturbFF) PerturbFF%Uniform%VelH = BaseFF%Uniform%VelH PerturbFF%Uniform%ShrV = BaseFF%Uniform%ShrV PerturbFF%PropagationDir = BaseFF%PropagationDir + PerturbFF%RotToWind = BaseFF%RotToWind + PerturbFF%RotFromWind = BaseFF%RotFromWind + PerturbFF%RotateWindBox = BaseFF%RotateWindBox select case (Var%DL%Num) case (AD_u_HWindSpeed) PerturbFF%Uniform%VelH = BaseFF%Uniform%VelH + Var%Perturb*PerturbSign @@ -7744,6 +7748,15 @@ subroutine PerturbFlowField(Var, BaseFF, PerturbSign, PerturbFF) PerturbFF%Uniform%ShrV = BaseFF%Uniform%ShrV + Var%Perturb*PerturbSign case (AD_u_PropagationDir) PerturbFF%PropagationDir = BaseFF%PropagationDir + Var%Perturb*PerturbSign + PerturbFF%RotToWind(1,:) = [ & + cos(-PerturbFF%VFlowAngle)*cos(-PerturbFF%PropagationDir), & + cos(-PerturbFF%VFlowAngle)*sin(-PerturbFF%PropagationDir), -sin(-PerturbFF%VFlowAngle)] + PerturbFF%RotToWind(2,:) = [-sin(-PerturbFF%PropagationDir), cos(-PerturbFF%PropagationDir), 0.0_ReKi] + PerturbFF%RotToWind(3,:) = [ & + sin(-PerturbFF%VFlowAngle)*cos(-PerturbFF%PropagationDir), & + sin(-PerturbFF%VFlowAngle)*sin(-PerturbFF%PropagationDir), cos(-PerturbFF%VFlowAngle)] + PerturbFF%RotFromWind = transpose(PerturbFF%RotToWind) + PerturbFF%RotateWindBox = .true. end select end subroutine diff --git a/modules/aerodyn/src/FVW.f90 b/modules/aerodyn/src/FVW.f90 index 1eddc41460..15da86e339 100644 --- a/modules/aerodyn/src/FVW.f90 +++ b/modules/aerodyn/src/FVW.f90 @@ -14,7 +14,7 @@ module FVW use FVW_IO use FVW_Wings use FVW_BiotSavart - use FVW_VortexTools, only: tic, toc + use FVW_VortexTools, only: tic, toc, T_Tree use FVW_Tests use AirFoilInfo @@ -30,9 +30,6 @@ module FVW public :: FVW_CalcOutput public :: FVW_UpdateStates - ! parameter for deciding if enough time has elapsed (Wake calculation, and vtk output) - real(DbKi), parameter :: OneMinusEpsilon = 1 - 10000*EPSILON(1.0_DbKi) - contains !---------------------------------------------------------------------------------------------------------------------------------- @@ -603,7 +600,7 @@ subroutine FVW_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, AFInfo, m bReevaluation=.True. endif ! Compute Induced wake effects only if time since last compute is > DTfvw - if ( (( t - m%OldWakeTime ) >= p%DTfvw*OneMinusEpsilon) ) then + if ( (( t - m%OldWakeTime ) >= p%DTfvw - 0.25_DbKi*p%DTaero) ) then m%OldWakeTime = t m%ComputeWakeInduced = .TRUE. ! It's time to update the induced velocities from wake else @@ -1570,6 +1567,9 @@ subroutine WriteVTKOutputs(t, force, VTKstep, u, p, x, z, m, ErrStat, ErrMsg) character(*), parameter :: RoutineName = 'WriteVTKOutputs' integer(IntKi) :: iW, iGrid integer(IntKi) :: nSeg, nSegP + logical, allocatable :: bDoGrid(:) ! Flag per output grid: .true. if it needs to be written now + type(T_Tree) :: Tree + type(T_Panl) :: Panl ErrStat = ErrID_None ErrMsg = '' if (OLAF_PROFILING) call tic('WriteVTKOutputs') @@ -1584,7 +1584,7 @@ subroutine WriteVTKOutputs(t, force, VTKstep, u, p, x, z, m, ErrStat, ErrMsg) do iW=1,p%nWings m%W(iW)%Vtot_CP = m%W(iW)%Vind_CP + m%W(iW)%Vwnd_CP - m%W(iW)%Vstr_CP enddo - if ( force .or. (( t - m%VTKlastTime ) >= p%DTvtk*OneMinusEpsilon )) then + if ( force .or. (( t - m%VTKlastTime ) >= p%DTvtk - 0.25_DbKi*p%DTaero )) then m%VTKlastTime = t if ((p%VTKCoord==2).or.(p%VTKCoord==3)) then ! Hub reference coordinates, for export only, ALL VTK Will be exported in this coordinate system! @@ -1612,18 +1612,31 @@ subroutine WriteVTKOutputs(t, force, VTKstep, u, p, x, z, m, ErrStat, ErrMsg) ! Distribute the Wind we requested to Inflow wind to storage Misc arrays ! TODO ANDY: replace with direct call to inflow wind at Grid points CALL DistributeRequestedWind_Grid(u%V_wind, p, m) + ! Compute once which grids are due for output now + allocate(bDoGrid(p%nGridOut)) do iGrid=1,p%nGridOut bWithinTime = t>=m%GridOutputs(iGrid)%tStart-p%DTaero/2. .and. t<= m%GridOutputs(iGrid)%tEnd+p%DTaero/2. - bTimeToOutput = ( t - m%GridOutputs(iGrid)%tLastOutput) >= m%GridOutputs(iGrid)%DTout * OneMinusEpsilon - if (force .or. (bWithinTime .and. bTimeToOutput) ) then - ! Compute induced velocity on grid, TODO use the same Tree for all CalcOutput - call InducedVelocitiesAll_OnGrid(m%GridOutputs(iGrid), p, x, m, ErrStat2, ErrMsg2); - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - m%GridOutputs(iGrid)%tLastOutput = t - call WrVTK_FVW_Grid(p, m, iGrid, trim(p%VTK_OutFileBase)//'FVW_Grid', VTKstep, 9) - m%VTKstep=VTKstep ! We save the step at which writing occurred - endif + bTimeToOutput = ( t - m%GridOutputs(iGrid)%tLastOutput) >= m%GridOutputs(iGrid)%DTout - 0.25_DbKi*p%DTaero + bDoGrid(iGrid) = force .or. (bWithinTime .and. bTimeToOutput) enddo + if (any(bDoGrid)) then + ! Build the wake segments/tree once and reuse it for all grids below + call InducedVelocitiesAll_Init(p, x, m, m%Sgmt, m%Part, Tree, Panl, ErrStat2, ErrMsg2, allocPart=.false.) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + do iGrid=1,p%nGridOut + if (bDoGrid(iGrid)) then + ! Compute induced velocity on grid, reusing the wake tree built once + call InducedVelocitiesAll_OnGrid_Calc(m%GridOutputs(iGrid), p, m%Sgmt, m%Part, Tree, Panl, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + m%GridOutputs(iGrid)%tLastOutput = t + call WrVTK_FVW_Grid(p, m, iGrid, trim(p%VTK_OutFileBase)//'FVW_Grid', VTKstep, 9) + m%VTKstep=VTKstep ! We save the step at which writing occurred + endif + enddo + call InducedVelocitiesAll_End(p, Tree, m%Part, Panl, ErrStat2, ErrMsg2, deallocPart=.false.) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + endif + deallocate(bDoGrid) endif if (OLAF_PROFILING) call toc() end subroutine WriteVTKOutputs diff --git a/modules/aerodyn/src/FVW_BiotSavart.f90 b/modules/aerodyn/src/FVW_BiotSavart.f90 index fcc301511d..d6db453b6f 100644 --- a/modules/aerodyn/src/FVW_BiotSavart.f90 +++ b/modules/aerodyn/src/FVW_BiotSavart.f90 @@ -10,6 +10,8 @@ module FVW_BiotSavart real(ReKi),parameter :: PRECISION_UI = epsilon(1.0_ReKi)/100 !< NOTE assuming problem of size 1 real(ReKi),parameter :: PRECISION_EPS = epsilon(1.0_ReKi) !< Machine Precision For the given ReKi for problems of scale 1! real(ReKi),parameter :: MIN_EXP_VALUE=-10.0_ReKi + real(ReKi),parameter :: PART_REG_NRAD = 2.0_ReKi !< Particle exp mollifier treated as 1 beyond this many core radii (matches 2*rc far-field multipole floor) + real(ReKi),parameter :: PART_REG_CUT3 = PART_REG_NRAD**3 !< Corresponding (r/rc)^3 cutoff real(ReKi),parameter :: MINDENOM=0.0_ReKi ! real(ReKi),parameter :: MINDENOM=1e-15_ReKi real(ReKi),parameter :: MINNORM=1e-4 @@ -374,26 +376,35 @@ subroutine ui_part_nograd_11(DeltaP, Alpha, RegFunction, RegParam, Ui) real(ReKi),dimension(3) :: C !< Cross product of Alpha and r real(ReKi) :: E !< Exponential poart for the mollifider real(ReKi) :: r3_inv !< + real(ReKi) :: r2, r3, rc3!< |r|^2, |r|^3, RegParam^3 (reused to avoid recomputing ** intrinsics) real(ReKi) :: rDeltaP !< norm , distance between point and particle real(ReKi) :: ScalarPart !< the part containing the inverse of the distance, but not 4pi, Mollifier - rDeltaP=sqrt(DeltaP(1)**2+ DeltaP(2)**2+ DeltaP(3)**2)! norm + r2 = DeltaP(1)**2+ DeltaP(2)**2+ DeltaP(3)**2 + rDeltaP = sqrt(r2)! norm if (rDeltaP PART_REG_CUT3*rc3) then ! r > 2*rc: mollifier -> 1 (skip exp), consistent with far-field multipole floor + ScalarPart = r3_inv*fourpi_inv + else + E = exp(-r3/rc3) + ScalarPart = (1._ReKi-E)*r3_inv*fourpi_inv + endif case (idRegCompact) ! Compact support - r3_inv = 1._ReKi/sqrt(RegParam**6+rDeltaP**6) + rc3 = RegParam*RegParam*RegParam + r3_inv = 1._ReKi/sqrt(rc3*rc3+r3*r3) ScalarPart = r3_inv*fourpi_inv case default print*,'[ERROR] Wrong regularization function for particles',RegFunction diff --git a/modules/aerodyn/src/FVW_IO.f90 b/modules/aerodyn/src/FVW_IO.f90 index a037c85dc3..aef35dcfcb 100644 --- a/modules/aerodyn/src/FVW_IO.f90 +++ b/modules/aerodyn/src/FVW_IO.f90 @@ -184,6 +184,7 @@ SUBROUTINE FVW_ReadInputFile( FileName, p, m, Inp, ErrStat, ErrMsg ) ! --- Validation of inputs if (PathIsRelative(Inp%CirculationFile)) Inp%CirculationFile = TRIM(PriPath)//TRIM(Inp%CirculationFile) + if (len_trim(Inp%SrcPnlFile)>0 .and. PathIsRelative(Inp%SrcPnlFile)) Inp%SrcPnlFile = TRIM(PriPath)//TRIM(Inp%SrcPnlFile) if (Check(.not.(ANY(idCircVALID ==Inp%CircSolvMethod)), 'Circulation method (CircSolvMethod) not implemented: '//trim(Num2LStr(Inp%CircSolvMethod)))) return if (Check(.not.(ANY(idIntMethodVALID==Inp%IntMethod )) , 'Time integration method (IntMethod) not yet implemented. Use Euler 1st order method for now.')) return diff --git a/modules/aerodyn/src/FVW_Subs.f90 b/modules/aerodyn/src/FVW_Subs.f90 index 3c9061e537..43ae7d3eb5 100644 --- a/modules/aerodyn/src/FVW_Subs.f90 +++ b/modules/aerodyn/src/FVW_Subs.f90 @@ -980,6 +980,7 @@ subroutine PackPanelsToSegments(p, x, iDepthStart, bMirror, nNW, nFW, SegConnct, SegConnct(1:2, iMirror) = SegConnct(1:2, i) + nSegP ! Increased point indices SegConnct(3:4, iMirror) = SegConnct(3:4, i) ! Span and age is copied SegGamma(iMirror) = -SegGamma(i) ! Vorticity needs mirroring + SegEpsilon(iMirror) = SegEpsilon(i) ! Regularization (core size) is copied enddo do i=1,nSegP iMirror = i + nSegP @@ -1047,7 +1048,8 @@ subroutine FVW_InitRegularization(x, p, m, ErrStat, ErrMsg) write(*,'(A,1F8.4)') 'RegParam (Input ) : ',p%WakeRegParam endif - if (p%RegDeterMethod==idRegDeterConstant) then + select case (p%RegDeterMethod) + case (idRegDeterConstant) ! Constant reg param throughout the wake if (p%WakeRegMethod==idRegAge) then ! NOTE: age method implies a division by rc p%WingRegParam=max(0.01_ReKi, p%WingRegParam) @@ -1061,7 +1063,7 @@ subroutine FVW_InitRegularization(x, p, m, ErrStat, ErrMsg) x%W(iW)%Eps_NW(1:3,:,2) = p%WakeRegParam ! Second age is always WakeRegParam endif - else if (p%RegDeterMethod==idRegDeterAuto) then + case (idRegDeterAuto) ! TODO this is beta print*,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' print*,'!!! NOTE: using optimized wake regularization parameters is still a beta feature!' @@ -1078,14 +1080,14 @@ subroutine FVW_InitRegularization(x, p, m, ErrStat, ErrMsg) write(*,'(A,1F8.4)') 'WakeRegParam : ', p%WakeRegParam write(*,'(A,1F8.4)') 'WingRegParam : ', p%WingRegParam write(*,'(A,1F9.4)') 'CoreSpreadEddyVisc: ', p%CoreSpreadEddyVisc - ! Set reg param on wing and first NW - ! NOTE: setting the same in all three directions for now, TODO! - x%W(iW)%Eps_NW(1:3,:,1) = p%WingRegParam ! First age is always WingRegParam (LL) - if (p%nNWMax>1) then - x%W(iW)%Eps_NW(1:3,:,2) = p%WakeRegParam ! Second age is always WakeRegParam - endif + ! Set reg param on wing and first NW + ! NOTE: setting the same in all three directions for now, TODO! + x%W(iW)%Eps_NW(1:3,:,1) = p%WingRegParam ! First age is always WingRegParam (LL) + if (p%nNWMax>1) then + x%W(iW)%Eps_NW(1:3,:,2) = p%WakeRegParam ! Second age is always WakeRegParam + endif - else if (p%RegDeterMethod==idRegDeterChord) then + case (idRegDeterChord) ! Using chord to scale the reg param do iSpan=1,p%W(iW)%nSpan x%W(iW)%Eps_NW(1:3, iSpan, 1) = p%WingRegParam * p%W(iW)%chord_CP(iSpan) @@ -1094,7 +1096,7 @@ subroutine FVW_InitRegularization(x, p, m, ErrStat, ErrMsg) endif enddo - else if (p%RegDeterMethod==idRegDeterSpan) then + case (idRegDeterSpan) ! Using dr to scale the reg param do iSpan=1,p%W(iW)%nSpan ds = p%W(iW)%s_LL(iSpan+1)-p%W(iW)%s_LL(iSpan) @@ -1103,10 +1105,11 @@ subroutine FVW_InitRegularization(x, p, m, ErrStat, ErrMsg) x%W(iW)%Eps_NW(1:3, iSpan, 2) = p%WakeRegParam * ds endif enddo - else ! Should never happen (caught earlier) + + case default ! Should never happen (caught earlier) ErrStat = ErrID_Fatal ErrMsg ='Regularization determination method not implemented' - endif + end select if (iW==1) then call WrScr(' - OLAF regularization parameters (for wing 1):') @@ -1122,28 +1125,29 @@ end subroutine FVW_InitRegularization -!> Compute induced velocities from all vortex elements onto nPoints -!! In : x, x%W(iW)%r_NW, x%W(iW)%r_FW, x%W(iW)%Gamma_NW, x%W(iW)%Gamma_FW +!> Compute induced velocities from all vortex elements onto nPoints, +!! reusing a wake Tree/Panl built once by InducedVelocitiesAll_Init +!! for all grids at a given output step. +!! In : Tree, Panl (already built from current wake state) !! Out: Vind -subroutine InducedVelocitiesAll_OnGrid(g, p, x, m, ErrStat, ErrMsg) +subroutine InducedVelocitiesAll_OnGrid_Calc(g, p, Sgmt, Part, Tree, Panl, ErrStat, ErrMsg) type(GridOutType), intent(inout) :: g !< Grid on whcih to compute the velocity type(FVW_ParameterType), intent(in ) :: p !< Parameters - type(FVW_ContinuousStateType), intent(in ) :: x !< States - type(FVW_MiscVarType), intent(inout) :: m !< Initial misc/optimization variables + type(T_Sgmt), intent(in ) :: Sgmt !< Segments, already built by InducedVelocitiesAll_Init + type(T_Part), intent(in ) :: Part !< Particle storage, already built by InducedVelocitiesAll_Init + type(T_Tree), intent(inout) :: Tree !< Wake tree, already built by InducedVelocitiesAll_Init + type(T_Panl), intent(in ) :: Panl !< Panel storage, already set by InducedVelocitiesAll_Init integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! Local variables integer(IntKi) :: nCPs, iHeadP integer(IntKi) :: i,j,k real(ReKi) :: xP,yP,zP - ! TODO new options - type(T_Tree) :: Tree - type(T_Panl) :: Panl real(ReKi), dimension(:,:), allocatable :: CPs ! TODO get rid of me with dedicated functions real(ReKi), dimension(:,:), allocatable :: Uind ! TODO get rid of me with dedicated functions ErrStat= ErrID_None ErrMsg ='' - if (OLAF_PROFILING) call tic('InducedVelocitiesAll_OnGrid') + if (OLAF_PROFILING) call tic('InducedVelocitiesAll_OnGrid_Calc') ! --- Packing control points nCPs = g%nx * g%ny * g%nz @@ -1166,11 +1170,8 @@ subroutine InducedVelocitiesAll_OnGrid(g, p, x, m, ErrStat, ErrMsg) iHeadP=1 call FlattenValues(g%uGrid, Uind, iHeadP); ! NOTE: Uind contains uGrid now (Uwnd) - ! --- Compute induced velocity - ! Convert Panels to segments, segments to particles, particles to tree - call InducedVelocitiesAll_Init(p, x, m, m%Sgmt, m%Part, Tree, Panl, ErrStat, ErrMsg, allocPart=.false.) - call InducedVelocitiesAll_Calc(CPs, nCPs, Uind, p, m%Sgmt, m%Part, Tree, Panl, ErrStat, ErrMsg) - call InducedVelocitiesAll_End(p, Tree, m%Part, Panl, ErrStat, ErrMsg, deallocPart=.false.) + ! --- Compute induced velocity using the wake Sgmt/Part/Tree/Panl built once + call InducedVelocitiesAll_Calc(CPs, nCPs, Uind, p, Sgmt, Part, Tree, Panl, ErrStat, ErrMsg) ! --- Unpacking induced velocity points iHeadP=1 @@ -1181,7 +1182,7 @@ subroutine InducedVelocitiesAll_OnGrid(g, p, x, m, ErrStat, ErrMsg) if (OLAF_PROFILING) call toc() -end subroutine InducedVelocitiesAll_OnGrid +end subroutine InducedVelocitiesAll_OnGrid_Calc !> Wrapper to setup part from set of segments subroutine SegmentsToPartWrap(Sgmt, nSeg, PartPerSegment, RegFunction, Part, allocPart) @@ -1223,9 +1224,9 @@ subroutine SegmentsToPartWrap(Sgmt, nSeg, PartPerSegment, RegFunction, Part, all Part%RegFunction = idRegExp ! TODO need to find a good equivalence and potentially adapt Epsilon in SegmentsToPart endif if (DEV_VERSION) then - call find_nan_2D(Part%P , 'SegmentsToPartWrap Part%P') - call find_nan_2D(Part%Alpha, 'SegmentsToPartWrap Part%Alpha') - if (any(Part%RegParam(:)<-9999.99_ReKi)) then + call find_nan_2D(Part%P(:,1:nPart) , 'SegmentsToPartWrap Part%P') + call find_nan_2D(Part%Alpha(:,1:nPart), 'SegmentsToPartWrap Part%Alpha') + if (any(Part%RegParam(1:nPart)<-9999.99_ReKi)) then ! Only the active particles are filled; the preallocated tail keeps its sentinel print*,'Error in Segment to part conversion' STOP endif @@ -1261,18 +1262,19 @@ subroutine InducedVelocitiesAll_Init(p, x, m, Sgmt, Part, Tree, Panl, ErrStat, E Sgmt%nAct = nSeg Sgmt%nActP = nSegP - ! --- Convert to particles if needed - if ((p%VelocityMethod(iVel)==idVelocityTreePart) .or. (p%VelocityMethod(iVel)==idVelocityPart)) then + select case (p%VelocityMethod(iVel)) + case (idVelocityPart) + ! --- Convert segments to particles call SegmentsToPartWrap(Sgmt, nSeg, p%PartPerSegment(iVel), p%RegFunction, Part, allocPart=allocPart) - endif - - ! --- Grow tree if needed - if (p%VelocityMethod(iVel)==idVelocityTreePart) then + case (idVelocityTreePart) + ! --- Convert segments to particles + call SegmentsToPartWrap(Sgmt, nSeg, p%PartPerSegment(iVel), p%RegFunction, Part, allocPart=allocPart) + ! --- Grow particle tree call grow_tree_part(Tree, Part%nAct, Part%P, Part%Alpha, Part%RegFunction, Part%RegParam, 0) - - elseif (p%VelocityMethod(iVel)==idVelocityTreeSeg) then + case (idVelocityTreeSeg) + ! --- Grow segment tree call grow_tree_segment(Tree, nSeg, Sgmt%Points, Sgmt%Connct(:,1:nSeg), Sgmt%Gamma(1:nSeg), p%RegFunction, Sgmt%Epsilon(1:nSeg), 0) - endif + end select ! --- Src Panl%p_Src => p%SrcPnl @@ -1298,20 +1300,26 @@ subroutine InducedVelocitiesAll_Calc(CPs, nCPs, Uind, p, Sgmt, Part, Tree, Panl, ErrStat= ErrID_None ErrMsg ='' - if (p%VelocityMethod(iVel)==idVelocityBasic) then + select case (p%VelocityMethod(iVel)) + case (idVelocityBasic) call ui_seg( 1, nCPs, CPs, 1, Sgmt%nAct, Sgmt%Points, Sgmt%Connct, Sgmt%Gamma, Sgmt%RegFunction, Sgmt%Epsilon, Uind) - elseif (p%VelocityMethod(iVel)==idVelocityTreePart) then + case (idVelocityTreePart) ! Tree has already been grown with InducedVelocitiesAll_Init !call print_tree(Tree) - call ui_tree_part(Tree, nCPs, CPs, p%TreeBranchFactor(iVel), Tree%DistanceDirect, Uind, ErrStat, ErrMsg) + call ui_tree_part(Tree, nCPs, CPs, p%TreeBranchFactor(iVel), 0.0_ReKi, Uind, ErrStat, ErrMsg) - elseif (p%VelocityMethod(iVel)==idVelocityPart) then + case (idVelocityPart) call ui_part_nograd(nCPs, CPs, Part%nAct, Part%P, Part%Alpha, Part%RegFunction, Part%RegParam, Uind) - elseif (p%VelocityMethod(iVel)==idVelocityTreeSeg) then - call ui_tree_segment(Tree, CPs, nCPs, p%TreeBranchFactor(iVel), Tree%DistanceDirect, Uind, ErrStat, ErrMsg) - endif + case (idVelocityTreeSeg) + call ui_tree_segment(Tree, CPs, nCPs, p%TreeBranchFactor(iVel), 0.0_ReKi, Uind, ErrStat, ErrMsg) + + case default + ErrStat = ErrID_Fatal + ErrMsg = 'Velocity method not implemented' + + end select ! --- Src Panels if (associated(Panl%p_Src)) then @@ -1338,19 +1346,25 @@ subroutine InducedVelocitiesAll_End(p, Tree, Part, Panl, ErrStat, ErrMsg, deallo ErrStat= ErrID_None ErrMsg ='' - if (p%VelocityMethod(iVel)==idVelocityBasic) then + select case (p%VelocityMethod(iVel)) + case (idVelocityBasic) ! Nothing - elseif (p%VelocityMethod(iVel)==idVelocityTreePart) then + case (idVelocityTreePart) if (deallocPart) deallocate(Part%P, Part%Alpha, Part%RegParam) call cut_tree(Tree) - elseif (p%VelocityMethod(iVel)==idVelocityPart) then + case (idVelocityPart) if (deallocPart) deallocate(Part%P, Part%Alpha, Part%RegParam) - elseif (p%VelocityMethod(iVel)==idVelocityTreeSeg) then + case (idVelocityTreeSeg) call cut_tree(Tree) ! We do not deallocate segment - endif + + case default + ErrStat = ErrID_Fatal + ErrMsg = 'Velocity method not implemented' + + end select ! Src Panels (we nullify only) nullify(Panl%p_Src) @@ -1547,26 +1561,31 @@ subroutine LiftingLineInducedVelocities(p, x, InductionAtCP, iDepthStart, m, Err ! --- Compute velocity on LL ! TreeSeg is faster but introduce some noise, so we keep this open for the user to choose - if (p%VelocityMethod(iVel) == idVelocityBasic) then + select case (p%VelocityMethod(iVel)) + case (idVelocityBasic) call ui_seg( 1, nCPs, CPs, 1, nSeg, m%Sgmt%Points, m%Sgmt%Connct, m%Sgmt%Gamma, m%Sgmt%RegFunction, m%Sgmt%Epsilon, Uind) - else if (p%VelocityMethod(iVel) == idVelocityPart) then + case (idVelocityPart) call SegmentsToPartWrap(m%Sgmt, nSeg, p%PartPerSegment(iVel), p%RegFunction, m%Part, allocPart=.false.) call ui_part_nograd(nCPs, CPs, m%Part%nAct, m%Part%P, m%Part%Alpha, m%Part%RegFunction, m%Part%RegParam, Uind) !deallocate(Part%P, Part%Alpha, Part%RegParam) - else if (p%VelocityMethod(iVel) == idVelocityTreeSeg) then + case (idVelocityTreeSeg) call grow_tree_segment(Tree, nSeg, m%Sgmt%Points, m%Sgmt%Connct(:,1:nSeg), m%Sgmt%Gamma(1:nSeg), m%Sgmt%RegFunction, m%Sgmt%Epsilon(1:nSeg), 0) call ui_tree_segment(Tree, CPs, nCPs, p%TreeBranchFactor(iVel), DistanceDirect, Uind, ErrStat, ErrMsg) call cut_tree(Tree) - else if (p%VelocityMethod(iVel) == idVelocityTreePart) then + case (idVelocityTreePart) call SegmentsToPartWrap(m%Sgmt, nSeg, p%PartPerSegment(iVel), p%RegFunction, m%Part, allocPart=.false.) call grow_tree_part(Tree, m%Part%nAct, m%Part%P, m%Part%Alpha, m%Part%RegFunction, m%Part%RegParam, 0) call ui_tree_part(Tree, nCPs, CPs, p%TreeBranchFactor(iVel), DistanceDirect, Uind, ErrStat, ErrMsg) !deallocate(Part%P, Part%Alpha, Part%RegParam) call cut_tree(Tree) - endif + + case default + ErrStat = ErrID_Fatal + ErrMsg = 'Velocity method not implemented' + end select ! --- Src Panel contribution if (p%SrcPnl%n>0) then call ui_quad_src_nn(CPs, m%SrcPnl%RHS, p%SrcPnl%xi, p%SrcPnl%eta, p%SrcPnl%Pcent, p%SrcPnl%R_g2p, Uind, nCPs, p%SrcPnl%n) diff --git a/modules/aerodyn/src/FVW_VortexTools.f90 b/modules/aerodyn/src/FVW_VortexTools.f90 index a4c5c6f920..a8589bebce 100644 --- a/modules/aerodyn/src/FVW_VortexTools.f90 +++ b/modules/aerodyn/src/FVW_VortexTools.f90 @@ -63,6 +63,7 @@ module FVW_VortexTools real(ReKi) :: radius !< Typical dimension of a cell (max of x,y,z extent) real(ReKi),dimension(3) :: center !< Used to store first the geometric center, then the vorticity center real(ReKi),dimension(3,10) :: Moments + real(ReKi) :: maxRegParam = 0.0_ReKi !< Max reg. param (eps) over all particles in this node integer,dimension(:),pointer :: iPart=>null() !< indexes of particles stored in this node integer,dimension(:),pointer :: leaves=>null() ! NOTE: leaves are introduced to save memory type(T_Node),dimension(:), pointer :: branches =>null() @@ -71,11 +72,10 @@ module FVW_VortexTools !> The type tree contains some basic data, a chained-list of nodes, and a pointer to the Particle data that were used type T_Tree - type(T_VPart) :: Part !< Storage for all particles - type(T_VSgmt) :: Seg !< Storage for all segments + type(T_VPart) :: Part !< Storage for all particles + type(T_VSgmt) :: Seg !< Storage for all segments integer :: iStep =-1 !< Time step at which the tree was built logical :: bGrown =.false. !< Is the tree build - real(ReKi) :: DistanceDirect type(T_Node) :: Root !< Contains the chained-list of nodes end type T_Tree @@ -587,6 +587,7 @@ subroutine grow_tree_part(Tree, nPart, PartP, PartAlpha, PartRegFunction, PartRe node%radius=0 node%center(1:3)=Part%P(1:3,1) node%Moments=0.0_ReKi + node%maxRegParam = Part%RegParam(1) nullify(node%iPart) nullify(node%branches) allocate(node%leaves(1:1)) @@ -625,7 +626,6 @@ subroutine grow_tree_part(Tree, nPart, PartP, PartAlpha, PartRegFunction, PartRe endif Tree%iStep = iStep Tree%bGrown = .true. - Tree%DistanceDirect = 2*sum(PartRegParam)/size(PartRegParam) ! 2*mean(eps), below that distance eps has a strong effect end subroutine grow_tree_part !> Recursive function to grow/setup a tree. @@ -675,6 +675,7 @@ subroutine grow_tree_part_substep(node, Part) GeomC = node%center ! NOTE: we rely on the fact that our parent has set this to the Geometric value VortC = 0.0_ReKi wTot = 0.0_ReKi + node%maxRegParam = 0.0_ReKi ! --- Barycenter of vorticity of the node do i = 1,node%nPart PartPos = Part%P(:,node%iPart(i)) @@ -682,6 +683,7 @@ subroutine grow_tree_part_substep(node, Part) wLoc = (PartAlpha(1)**2 + PartAlpha(2)**2 + PartAlpha(3)**2)**0.5_ReKi ! Vorticity norm VortC = VortC + wLoc*PartPos ! Sum coordinates weighted by vorticity wTot = wTot + wLoc ! Total vorticity + node%maxRegParam = max(node%maxRegParam, Part%RegParam(node%iPart(i))) ! Regularization floor uses max eps in this cell end do ! There is no vorticity, we make it a empty node and we exit if(EqualRealNos(abs(wTot),0.0_ReKi)) then @@ -925,6 +927,7 @@ subroutine grow_tree_segment(Tree_Seg, nSeg, SegPoints, SegConnct, SegGamma, Seg node%radius=0 node%center(1:3)=0.5_ReKi*(Seg%SP(1:3,1)+Seg%SP(1:3,2)) node%Moments=0.0_ReKi + node%maxRegParam = Seg%RegParam(1) nullify(node%iPart) nullify(node%branches) allocate(node%leaves(1:1)) @@ -973,7 +976,6 @@ subroutine grow_tree_segment(Tree_Seg, nSeg, SegPoints, SegConnct, SegGamma, Seg endif Tree_Seg%iStep = iStep Tree_Seg%bGrown = .true. - Tree_Seg%DistanceDirect = 2*sum(SegRegParam)/size(SegRegParam) ! 2*mean(eps), below that distance eps has a strong effect ! TODO REMOVE end subroutine grow_tree_segment !> Recursive function to grow/setup a tree. @@ -1024,6 +1026,7 @@ subroutine grow_tree_segment_substep(node, Seg) GeomC = node%center ! NOTE: we rely on the fact that our parent has set this to the Geometric value VortC = 0.0_ReKi wTot = 0.0_ReKi + node%maxRegParam = 0.0_ReKi ! --- Barycenter of vorticity of the node do i = 1,node%nPart P1 = Seg%SP(1:3,Seg%SConnct(1,node%iPart(i))) @@ -1031,6 +1034,7 @@ subroutine grow_tree_segment_substep(node, Seg) SegCenter = 0.5_ReKi*(P1+P2) VortC = VortC + abs(Seg%SGamma(node%iPart(i)))*SegCenter ! Sum coordinates weighted by vorticity wTot = wTot + abs(Seg%SGamma(node%iPart(i))) ! Total vorticity + node%maxRegParam = max(node%maxRegParam, Seg%RegParam(node%iPart(i))) ! Regularization floor uses max eps in this cell end do ! There is no vorticity, we make it a empty node and we exit if(EqualRealNos(abs(wTot),0.0_ReKi)) then @@ -1501,7 +1505,7 @@ recursive subroutine ui_tree_part_11(node, CP, Uind) enddo endif else - distDirect = max(BranchFactor*node%radius, DistanceDirect) ! Under this distance-> Direct eval., Above it -> quadrupole calculation + distDirect = max(BranchFactor*node%radius + 2.0_ReKi*node%maxRegParam, DistanceDirect) ! Direct eval. below this distance; floor = branch radius + 2*max(eps) in cell DeltaP = - node%center + CP(1:3) ! Vector between the control point and the center of the branch r = sqrt( DeltaP(1)**2 + DeltaP(2)**2 + DeltaP(3)**2) ! Test if the control point is too close from the branch node so that a direct evaluation is needed @@ -1704,7 +1708,7 @@ recursive subroutine ui_tree_segment_11(node, CP, Uind) enddo endif else - distDirect = max(BranchFactor*node%radius, DistanceDirect) ! Under this distance-> Direct eval., Above it -> quadrupole calculation + distDirect = max(BranchFactor*node%radius + 2.0_ReKi*node%maxRegParam, DistanceDirect) ! Direct eval. below this distance; floor = branch radius + 2*max(eps) in cell DeltaP = - node%center + CP(1:3) ! Vector between the control point and the center of the branch r = sqrt( DeltaP(1)**2 + DeltaP(2)**2 + DeltaP(3)**2) ! Test if the control point is too close from the branch node so that a direct evaluation is needed diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index 43f21947e0..4684f346f7 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -789,7 +789,7 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & if (ErrStat >= AbortErrLev) return !---------------------------------------------------------------------------- - ! Extract interpolation cells from grids based on poisiont + ! Extract interpolation cells from grids based on position !---------------------------------------------------------------------------- ! If position is inside grid @@ -1278,7 +1278,7 @@ subroutine GetBoundsT(PosX, DT) ! so take modulus again to ensure that T_GRID is less than NSteps T_GRID = MODULO(T_GRID, real(G3D%NSteps, ReKi)) end if - + ! Calculate bounding grid indices IT_LO = floor(T_GRID, IntKi) + 1 IT_HI = IT_LO + 1 @@ -1289,6 +1289,11 @@ subroutine GetBoundsT(PosX, DT) ! Adjust indices and interpolant if (IT_LO >= 1 .and. IT_HI <= G3D%NSteps) then ! Point is within grid + else if (IT_LO == 0 .and. T_GRID >= -GridTol) then + ! Within tolerance of the first time step + IT_LO = 1 + IT_HI = 1 + DT = -1.0_ReKi else if (IT_LO == G3D%NSteps) then if (G3D%Periodic) then ! Time wraps back to beginning @@ -1306,7 +1311,7 @@ subroutine GetBoundsT(PosX, DT) ! Time exceeds array bounds call SetErrStat(ErrID_Fatal, ' Error: GF wind array was exhausted at '// & TRIM(Num2LStr(TIME))//' seconds (trying to access data at '// & - TRIM(Num2LStr(TimeShifted))//' seconds). IT_Lo='//TRIM(Num2LStr(IT_Lo))// & + TRIM(Num2LStr(TimeShifted))//' seconds). IT_LO='//TRIM(Num2LStr(IT_Lo))// & ', IT_HI='//TRIM(Num2LStr(IT_Hi)), & ErrStat, ErrMsg, RoutineName) end if diff --git a/modules/lindyn/src/LinDyn.f90 b/modules/lindyn/src/LinDyn.f90 index 799c0d2fd3..22d6ce6e2f 100644 --- a/modules/lindyn/src/LinDyn.f90 +++ b/modules/lindyn/src/LinDyn.f90 @@ -724,9 +724,9 @@ subroutine Init_Lin(p, InitOut, errStat, errMsg) ! LinNames_y {:} - - "Names of the outputs used in linearization" - ! LinNames_x {:} - - "Names of the continuous states used in linearization" - ! LinNames_u {:} - - "Names of the inputs used in linearization" - -! RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - -! RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame" - -! RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +! RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - +! RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame" - +! RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - ! IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - ! DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - !Appropriate Jacobian row/column names and rotating-frame flags here: diff --git a/modules/moordyn/src/MoorDyn_Line.f90 b/modules/moordyn/src/MoorDyn_Line.f90 index 5a0461e9a9..a898e70119 100644 --- a/modules/moordyn/src/MoorDyn_Line.f90 +++ b/modules/moordyn/src/MoorDyn_Line.f90 @@ -1926,7 +1926,7 @@ SUBROUTINE Line_GetStateDeriv(Line, Xd, m, p, ErrStat, ErrMsg) !, FairFtot, Fai ! DO I = N-4, N ! print*, "I =", I, "rdd_old =", Line%rdd_old(:,I) ! enddo - ! endif + ! endif ! check for NaNs DO J = 1, 6*(N-1) diff --git a/modules/nwtc-library/Old_test/Test_MeshMapping/Test_MeshMapping_Mod.f90 b/modules/nwtc-library/Old_test/Test_MeshMapping/Test_MeshMapping_Mod.f90 index c770a5ab68..3e04d66484 100644 --- a/modules/nwtc-library/Old_test/Test_MeshMapping/Test_MeshMapping_Mod.f90 +++ b/modules/nwtc-library/Old_test/Test_MeshMapping/Test_MeshMapping_Mod.f90 @@ -1257,7 +1257,7 @@ subroutine CreateOutputMeshes_Test10 Mesh1_O%TranslationVel(:,3) = (/-0.000275392638286576, 1.26055965665728e-09,-0.00660990970209241/) Mesh1_O%TranslationVel(:,4) = (/-0.000295042205834761,-5.36239895154722e-07,-0.00463324552401900/) Mesh1_O%TranslationVel(:,5) = (/ 0, 0, 0 /) - + Mesh1_O%RotationVel(:,1) = (/2.96345683636901e-06,-2.34051149163861e-05,-5.91553508400011e-08 /) Mesh1_O%RotationVel(:,2) = (/4.80349626741372e-09, 2.67697760136798e-05, 2.29704255616525e-09 /) Mesh1_O%RotationVel(:,3) = (/1.04646687759669e-07,-4.83136973343790e-05,-1.12983400413214e-09 /) @@ -1275,7 +1275,7 @@ subroutine CreateOutputMeshes_Test10 Mesh1_O%RotationAcc(:,3) = (/ 0.000204067997401580,-0.0911907851696014, -1.95350694411900e-05/) Mesh1_O%RotationAcc(:,4) = (/ 7.36967340344563e-05, 0.0997802764177322, 7.97090106061660e-05/) Mesh1_O%RotationAcc(:,5) = (/ 0, 0, 0 /) - + ! test: diff --git a/modules/nwtc-library/src/NWTC_Num.f90 b/modules/nwtc-library/src/NWTC_Num.f90 index c07c5aad35..70b84d4e5a 100644 --- a/modules/nwtc-library/src/NWTC_Num.f90 +++ b/modules/nwtc-library/src/NWTC_Num.f90 @@ -1077,7 +1077,7 @@ END SUBROUTINE CubicSplineInterpM !! 0 & \lambda_3 & -\lambda_2 \\ !! -\lambda_3 & 0 & \lambda_1 \\ !! \lambda_2 & -\lambda_1 & 0 -!! \end{bmatrix} +!! \end{bmatrix} !! \f} !! The angle of rotation for \f$\lambda\f$ is !! \f{equation}{ \theta = \sqrt{{\lambda_1}^2+{\lambda_2}^2+{\lambda_3}^2} \f} diff --git a/modules/servodyn/src/StrucCtrl_Registry.txt b/modules/servodyn/src/StrucCtrl_Registry.txt index 9329bc07d0..f8d3245418 100644 --- a/modules/servodyn/src/StrucCtrl_Registry.txt +++ b/modules/servodyn/src/StrucCtrl_Registry.txt @@ -138,7 +138,7 @@ typedef ^ MiscVarType ReKi a_G {:}{:} - - "Gravitational acceleration vecto typedef ^ MiscVarType ReKi rdisp_P {:}{:} - - "Translational displacement vector, local coordinates for point" m typedef ^ MiscVarType ReKi rdot_P {:}{:} - - "Translational velocity vector, local coordinates for point" m/s typedef ^ MiscVarType ReKi rddot_P {:}{:} - - "Translational acceleration vector, local coordinates for point" m/s^2 -typedef ^ MiscVarType ReKi omega_P {:}{:} - - "Rotational velocity vector, local coordinates for point" rad/s +typedef ^ MiscVarType ReKi omega_P {:}{:} - - "Rotational velocity vector, local coordinates for point" rad/s typedef ^ MiscVarType ReKi alpha_P {:}{:} - - "Rotational aceeleration vector, local coordinates for point" rad/s^2 typedef ^ MiscVarType ReKi F_P {:}{:} - - "StC force vector, local coordinates for point" N typedef ^ MiscVarType ReKi M_P {:}{:} - - "StC moment vector, local coordinates for point" N-m diff --git a/modules/servodyn/src/StrucCtrl_Types.f90 b/modules/servodyn/src/StrucCtrl_Types.f90 index c25d951de6..6031746333 100644 --- a/modules/servodyn/src/StrucCtrl_Types.f90 +++ b/modules/servodyn/src/StrucCtrl_Types.f90 @@ -176,7 +176,7 @@ MODULE StrucCtrl_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rdisp_P !< Translational displacement vector, local coordinates for point [m] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rdot_P !< Translational velocity vector, local coordinates for point [m/s] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: rddot_P !< Translational acceleration vector, local coordinates for point [m/s^2] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: omega_P !< Rotational velocity vector, local coordinates for point [rad/s] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: omega_P !< Rotational velocity vector, local coordinates for point [rad/s] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: alpha_P !< Rotational aceeleration vector, local coordinates for point [rad/s^2] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_P !< StC force vector, local coordinates for point [N] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: M_P !< StC moment vector, local coordinates for point [N-m] diff --git a/reg_tests/r-test b/reg_tests/r-test index 8aefcb0e74..fbe583ae55 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 8aefcb0e74b711bc7eebf77fab246d2f9bb7c817 +Subproject commit fbe583ae5595a116c216afeec2025c57723e5186