From bbded1bf7484f23781730f3bc91527fad4a51293 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Mon, 4 Nov 2024 14:05:24 +0000 Subject: [PATCH 01/31] CMAKE_INSTALL_PREFIX was incorrectly being prepended to the install directory for the ftnmod folder which caused it to be in the wrong place when importing OpenFAST as a library in AMR-Wind --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2dc54651d..3299153263 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -232,8 +232,8 @@ endforeach(IDIR IN ITEMS ${OPENFAST_MODULES}) add_subdirectory(glue-codes) # Install fortran .mod files also to installation directory -install(DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY}/ - DESTINATION ${CMAKE_INSTALL_PREFIX}/include/openfast/ +install(DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY} + DESTINATION include/openfast/ FILES_MATCHING PATTERN "*.mod" ) From 309832aa26edc2ecf8e895958886773b2cc14226 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 4 Nov 2024 10:06:00 -0700 Subject: [PATCH 02/31] Docker: typo was preventing docker build upload to GH --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 180969d6fa..b94a541b10 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -77,7 +77,7 @@ jobs: file: ${{ env.DOCKERFILE_PATH }} platforms: linux/amd64,linux/aarch64 tags: | - ${{ env.GH_REGISTRY }}:${{ steps.extract-tag.outputs.openfast-tag }},${{ env.DOCKERHUB_REPOSITORY }}:latest + ${{ env.GH_REGISTRY }}:${{ steps.extract-tag.outputs.openfast-tag }},${{ env.GH_REGISTRY }}:latest # ${{ env.DOCKERHUB_REPOSITORY }}:${{ steps.extract-tag.outputs.openfast-tag }},${{ env.DOCKERHUB_REPOSITORY }}:latest push: true cache-from: type=gha From a6268d3cb4d18e186555b557273baa14720e3a85 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 5 Nov 2024 16:46:57 +0000 Subject: [PATCH 03/31] Remove OpenMP statements from AeroDyn_Inflow.f90 because it causes compilation to fail when using the Intel oneAPI 2024.1.0 compiler --- modules/aerodyn/src/AeroDyn_Inflow.f90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn_Inflow.f90 b/modules/aerodyn/src/AeroDyn_Inflow.f90 index 6dd7773665..17ad2f4bbc 100644 --- a/modules/aerodyn/src/AeroDyn_Inflow.f90 +++ b/modules/aerodyn/src/AeroDyn_Inflow.f90 @@ -488,16 +488,12 @@ subroutine ADI_CalcOutput_IW(t, u_IfW, IW, errStat, errMsg) call InflowWind_CalcOutput(t, u_IfW, IW%p, IW%x, IW%xd, IW%z, IW%OtherSt, IW%y, IW%m, errStat2, errMsg2) call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'ADI_CalcOutput_IW') else - !$OMP PARALLEL DEFAULT(SHARED) - !$OMP DO PRIVATE(j,z) schedule(runtime) do j=1,size(u_IfW%PositionXYZ,2) z = u_IfW%PositionXYZ(3,j) IW%y%VelocityUVW(1,j) = IW%HWindSpeed*(z/IW%RefHt)**IW%PLExp IW%y%VelocityUVW(2,j) = 0.0_ReKi !V IW%y%VelocityUVW(3,j) = 0.0_ReKi !W end do - !$OMP END DO - !$OMP END PARALLEL endif end subroutine ADI_CalcOutput_IW !---------------------------------------------------------------------------------------------------------------------------------- From ee1726c348941662371b9823e4420c2464c9dc96 Mon Sep 17 00:00:00 2001 From: Mayank Chetan Date: Wed, 6 Nov 2024 15:30:12 -0700 Subject: [PATCH 04/31] change to tag tracking --- .github/workflows/deploy.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b94a541b10..f28aee59ce 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,7 +41,7 @@ jobs: env: DOCKERFILE_PATH: share/docker/Dockerfile DOCKERHUB_REPOSITORY: nrel/openfast - GH_REGISTRY: ghcr.io/OpenFAST/openfast + GH_REGISTRY: ghcr.io/openfast/openfast permissions: contents: read packages: write @@ -68,7 +68,11 @@ jobs: - name: Extract tag from release candidate branch name id: extract-tag - run: echo "openfast-tag=$(expr substr "${{ github.head_ref }}" 4 100)" >> $GITHUB_OUTPUT + run: | + TAG="${{ github.event.release.tag_name }}" + CLEAN_TAG="${TAG#v}" + echo "openfast-tag=$CLEAN_TAG" >> $GITHUB_OUTPUT + echo "Extracted tag $CLEAN_TAG" - name: Build and push to registry uses: docker/build-push-action@v5 From 3acba023b3280424a7abbdc9706f6b0b8f00b2eb Mon Sep 17 00:00:00 2001 From: Mayank Chetan Date: Fri, 8 Nov 2024 11:08:40 -0700 Subject: [PATCH 05/31] repository name must be lowercase --- .github/workflows/build-docker-image-manual.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-docker-image-manual.yml b/.github/workflows/build-docker-image-manual.yml index 608bd02307..a017443a06 100644 --- a/.github/workflows/build-docker-image-manual.yml +++ b/.github/workflows/build-docker-image-manual.yml @@ -20,9 +20,9 @@ jobs: timeout-minutes: 300 env: DOCKERFILE_PATH: share/docker/Dockerfile - DOCKERFILE_PERMALINK: https://raw.githubusercontent.com/OpenFAST/openfast/main/share/docker/Dockerfile + DOCKERFILE_PERMALINK: https://raw.githubusercontent.com/openfast/openfast/main/share/docker/Dockerfile DOCKERHUB_REPOSITORY: nrel/openfast - GH_REGISTRY: ghcr.io/OpenFAST/openfast + GH_REGISTRY: ghcr.io/openfast/openfast permissions: contents: read packages: write From 15bafa4d4830749b6cff6fa0f89278f7fd1c5180 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 14 Nov 2024 16:36:26 -0700 Subject: [PATCH 06/31] AD bugfix: Segmentation fault with ifx When OLAF was used with the AeroDyn Driver compiled with ifx (IFX) 2023.2.0 20230622 (release only), there would be a segmentation fault when SetInputsForFVW was called. The root issue was that passing an array of `u` as `(/u/)` doesn't work correctly with this compiler. So to work around this, the SetInputsForFVW routine was reworked to only operate on a single `u`. In my opinion this is a hack of a solution to accomodate a compiler bug. --- modules/aerodyn/src/AeroDyn.f90 | 52 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index e631ea3fcb..658f12bce5 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -1623,8 +1623,10 @@ subroutine AD_UpdateStates( t, n, u, utimes, p, x, xd, z, OtherState, m, errStat else ! Call the FVW sub module ! This needs to extract the inputs from the AD data types (mesh) and copy pieces for the FVW module - call SetInputsForFVW(p, u, m, errStat2, errMsg2) - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + do i=1,size(u) + call SetInputsForFVW(p, u(i), i, m, errStat2, errMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + enddo ! Note: the setup is handled above in the SetInputs routine call FVW_UpdateStates( t, n, m%FVW_u, utimes, p%FVW, x%FVW, xd%FVW, z%FVW, OtherState%FVW, p%AFI, m%FVW, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1696,7 +1698,7 @@ subroutine AD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, if (p%WakeMod == WakeMod_FVW) then ! This needs to extract the inputs from the AD data types (mesh) and copy pieces for the FVW module - call SetInputsForFVW(p, (/u/), m, errStat2, errMsg2) + call SetInputsForFVW(p, u, 1, m, errStat2, errMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) ! Calculate Outputs at time t CALL FVW_CalcOutput( t, m%FVW_u(1), p%FVW, x%FVW, xd%FVW, z%FVW, OtherState%FVW, m%FVW_y, m%FVW, ErrStat2, ErrMsg2 ) @@ -3091,10 +3093,11 @@ subroutine Calculate_MeshOrientation_LiftingLine(p, u, m, thetaBladeNds, toeBlad end subroutine Calculate_MeshOrientation_LiftingLine !---------------------------------------------------------------------------------------------------------------------------------- !> This subroutine sets m%FVW_u(indx). -subroutine SetInputsForFVW(p, u, m, errStat, errMsg) +subroutine SetInputsForFVW(p, u, tIndx, m, errStat, errMsg) type(AD_ParameterType), intent(in ) :: p !< AD parameters - type(AD_InputType), intent(in ) :: u(:) !< AD Inputs at Time + type(AD_InputType), intent(in ) :: u !< AD Inputs at Time + integer(intKi), intent(in ) :: tIndx !< index of m%FVW_u() array type(AD_MiscVarType), intent(inout) :: m !< Misc/optimization variables integer(IntKi), intent( out) :: ErrStat !< Error status of the operation character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None @@ -3102,7 +3105,6 @@ subroutine SetInputsForFVW(p, u, m, errStat, errMsg) real(R8Ki) :: x_hat_disk(3) real(R8Ki), allocatable :: thetaBladeNds(:,:) - integer(intKi) :: tIndx integer(intKi) :: iR ! Loop on rotors integer(intKi) :: j, k ! loop counter for blades integer(intKi) :: ErrStat2 @@ -3113,55 +3115,54 @@ subroutine SetInputsForFVW(p, u, m, errStat, errMsg) ErrStat = ErrID_None ErrMsg = "" - do tIndx=1,size(u) do iR =1, size(p%rotors) allocate(thetaBladeNds(p%rotors(iR)%NumBlNds, p%rotors(iR)%NumBlades)) ! Get disk average values and orientations ! NOTE: needed because it sets m%V_diskAvg and m%V_dot_x, needed by CalcOutput.. - call DiskAvgValues(p%rotors(iR), u(tIndx)%rotors(iR), m%rotors(iR), x_hat_disk) ! also sets m%V_diskAvg and m%V_dot_x + call DiskAvgValues(p%rotors(iR), u%rotors(iR), m%rotors(iR), x_hat_disk) ! also sets m%V_diskAvg and m%V_dot_x if (p%rotors(iR)%AeroProjMod==APM_BEM_NoSweepPitchTwist) then - call Calculate_MeshOrientation_NoSweepPitchTwist(p%rotors(iR),u(tIndx)%rotors(iR), m%rotors(iR), thetaBladeNds,ErrStat=ErrStat2,ErrMsg=ErrMsg2) ! sets m%orientationAnnulus, m%Curve + call Calculate_MeshOrientation_NoSweepPitchTwist(p%rotors(iR),u%rotors(iR), m%rotors(iR), thetaBladeNds,ErrStat=ErrStat2,ErrMsg=ErrMsg2) ! sets m%orientationAnnulus, m%Curve else if (p%rotors(iR)%AeroProjMod==APM_LiftingLine) then - call Calculate_MeshOrientation_LiftingLine (p%rotors(iR),u(tIndx)%rotors(iR), m%rotors(iR), thetaBladeNds,ErrStat=ErrStat2,ErrMsg=ErrMsg2) ! sets m%orientationAnnulus, m%Curve + call Calculate_MeshOrientation_LiftingLine (p%rotors(iR),u%rotors(iR), m%rotors(iR), thetaBladeNds,ErrStat=ErrStat2,ErrMsg=ErrMsg2) ! sets m%orientationAnnulus, m%Curve endif - call StorePitchAndAzimuth(p%rotors(iR), u(tIndx)%rotors(iR), m%rotors(iR), ErrStat2, ErrMsg2) + call StorePitchAndAzimuth(p%rotors(iR), u%rotors(iR), m%rotors(iR), ErrStat2, ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat >= AbortErrLev) return - + ! Rather than use a meshcopy, we will just copy what we need to the WingsMesh ! NOTE: MeshCopy requires the source mesh to be INOUT intent ! NOTE2: If we change the WingsMesh to not be identical to the BladeMotion mesh, add the mapping stuff here. do k=1,p%rotors(iR)%NumBlades iW=p%FVW%Bld2Wings(iR,k) - - if ( u(tIndx)%rotors(iR)%BladeMotion(k)%nNodes /= m%FVW_u(tIndx)%WingsMesh(iW)%nNodes ) then + + if ( u%rotors(iR)%BladeMotion(k)%nNodes /= m%FVW_u(tIndx)%WingsMesh(iW)%nNodes ) then call SetErrStat(ErrID_Fatal,"WingsMesh contains different number of nodes than the BladeMotion mesh",ErrStat,ErrMsg,RoutineName) return endif m%FVW%W(iW)%PitchAndTwist(:) = thetaBladeNds(:,k) ! local pitch + twist (aerodyanmic + elastic) angle of the jth node in the kth blade - m%FVW_u(tIndx)%WingsMesh(iW)%TranslationDisp = u(tIndx)%rotors(iR)%BladeMotion(k)%TranslationDisp - m%FVW_u(tIndx)%WingsMesh(iW)%Orientation = u(tIndx)%rotors(iR)%BladeMotion(k)%Orientation - m%FVW_u(tIndx)%WingsMesh(iW)%TranslationVel = u(tIndx)%rotors(iR)%BladeMotion(k)%TranslationVel - m%FVW_u(tIndx)%rotors(iR)%HubPosition = u(tIndx)%rotors(iR)%HubMotion%Position(:,1) + u(tIndx)%rotors(iR)%HubMotion%TranslationDisp(:,1) - m%FVW_u(tIndx)%rotors(iR)%HubOrientation = u(tIndx)%rotors(iR)%HubMotion%Orientation(:,:,1) - + m%FVW_u(tIndx)%WingsMesh(iW)%TranslationDisp = u%rotors(iR)%BladeMotion(k)%TranslationDisp + m%FVW_u(tIndx)%WingsMesh(iW)%Orientation = u%rotors(iR)%BladeMotion(k)%Orientation + m%FVW_u(tIndx)%WingsMesh(iW)%TranslationVel = u%rotors(iR)%BladeMotion(k)%TranslationVel + m%FVW_u(tIndx)%rotors(iR)%HubPosition = u%rotors(iR)%HubMotion%Position(:,1) + u%rotors(iR)%HubMotion%TranslationDisp(:,1) + m%FVW_u(tIndx)%rotors(iR)%HubOrientation = u%rotors(iR)%HubMotion%Orientation(:,:,1) + ! Inputs for dynamic stall (see SetInputsForBEMT) do j=1,p%rotors(iR)%NumBlNds ! inputs for CUA, section pitch/torsion rate - m%FVW_u(tIndx)%W(iW)%omega_z(j) = dot_product( u(tIndx)%rotors(iR)%BladeMotion(k)%RotationVel( :,j), m%rotors(iR)%orientationAnnulus(3,:,j,k) ) ! rotation of no-sweep-pitch coordinate system around z of the jth node in the kth blade + m%FVW_u(tIndx)%W(iW)%omega_z(j) = dot_product( u%rotors(iR)%BladeMotion(k)%RotationVel( :,j), m%rotors(iR)%orientationAnnulus(3,:,j,k) ) ! rotation of no-sweep-pitch coordinate system around z of the jth node in the kth blade end do !j=nodes enddo ! k blades if (allocated(thetaBladeNds)) deallocate(thetaBladeNds) enddo ! iR, rotors - + if (ALLOCATED(m%FVW_u(tIndx)%V_wind)) then - m%FVW_u(tIndx)%V_wind = u(tIndx)%InflowWakeVel + m%FVW_u(tIndx)%V_wind = u%InflowWakeVel ! Applying tower shadow to V_wind based on r_wind positions ! NOTE: m%DisturbedInflow also contains tower shadow and we need it for CalcOutput if (p%FVW%TwrShadowOnWake) then do iR =1, size(p%rotors) if (p%rotors(iR)%TwrPotent /= TwrPotent_none .or. p%rotors(iR)%TwrShadow /= TwrShadow_none) then - call TwrInflArray( p%rotors(iR), u(tIndx)%rotors(iR), m%rotors(iR), m%FVW%r_wind, m%FVW_u(tIndx)%V_wind, ErrStat2, ErrMsg2 ) + call TwrInflArray( p%rotors(iR), u%rotors(iR), m%rotors(iR), m%FVW%r_wind, m%FVW_u(tIndx)%V_wind, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (ErrStat >= AbortErrLev) return endif @@ -3170,14 +3171,13 @@ subroutine SetInputsForFVW(p, u, m, errStat, errMsg) endif do iR =1, size(p%rotors) ! Disturbed inflow for UA on Lifting line Mesh Points - call SetDisturbedInflow(p%rotors(iR), p, u(tIndx)%rotors(iR), m%rotors(iR), errStat2, errMsg2) + call SetDisturbedInflow(p%rotors(iR), p, u%rotors(iR), m%rotors(iR), errStat2, errMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) do k=1,p%rotors(iR)%NumBlades iW=p%FVW%Bld2Wings(iR,k) m%FVW_u(tIndx)%W(iW)%Vwnd_LL(1:3,:) = m%rotors(iR)%DisturbedInflow(1:3,:,k) enddo enddo - enddo end subroutine SetInputsForFVW !---------------------------------------------------------------------------------------------------------------------------------- From d4ea5ffb8df45b0228c33aab651dfb5b9ddb7b2d Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 15 Nov 2024 14:40:48 -0700 Subject: [PATCH 07/31] ADI bugfix: BoxExceed was not enabled for OLAF with ADI Neither the C-bindings nor AD driver could use the BoxExceedAllow option with OLAF --- modules/aerodyn/src/AeroDyn_Inflow.f90 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/aerodyn/src/AeroDyn_Inflow.f90 b/modules/aerodyn/src/AeroDyn_Inflow.f90 index 17ad2f4bbc..c83971db0b 100644 --- a/modules/aerodyn/src/AeroDyn_Inflow.f90 +++ b/modules/aerodyn/src/AeroDyn_Inflow.f90 @@ -4,7 +4,7 @@ module AeroDyn_Inflow use NWTC_Library use AeroDyn_Inflow_Types use AeroDyn_Types - use AeroDyn, only: AD_Init, AD_ReInit, AD_CalcOutput, AD_UpdateStates, AD_End + use AeroDyn, only: AD_Init, AD_ReInit, AD_CalcOutput, AD_UpdateStates, AD_End, AD_BoxExceedPointsIdx use AeroDyn, only: AD_NumWindPoints, AD_GetExternalWind, AD_SetExternalWindPositions use AeroDyn_IO, only: AD_SetVTKSurface use InflowWind, only: InflowWind_Init, InflowWind_CalcOutput, InflowWind_End @@ -344,6 +344,11 @@ subroutine ADI_InitInflowWind(Root, i_IW, u_AD, o_AD, IW, dt, InitOutData, errSt InitInData%InputFileName = i_IW%InputFile InitInData%Linearize = i_IW%Linearize InitInData%UseInputFile = i_IW%UseInputFile + ! Box exceed allow for OLAF poitns + if (allocated(o_AD%WakeLocationPoints)) then + InitInData%BoxExceedAllowF = .true. + InitInData%BoxExceedAllowIdx = min(InitInData%BoxExceedAllowIdx, AD_BoxExceedPointsIdx(u_AD, o_AD)) + endif if (.not. i_IW%UseInputFile) then call NWTC_Library_Copyfileinfotype( i_IW%PassedFileData, InitInData%PassedFileData, MESH_NEWCOPY, errStat2, errMsg2 ); if (Failed()) return endif From 901e3b325a42dc7768c75846aa22bd908690e1d0 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 22 Nov 2024 15:12:36 -0700 Subject: [PATCH 08/31] Incorrect initial value for `BoxExceedAllowIdx` This was introduced in PR #2518. The result was that anytime the driver was used with OLAF, all points were allowed outside the box, not just the wake as intended. --- modules/aerodyn/src/AeroDyn_Inflow.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/aerodyn/src/AeroDyn_Inflow.f90 b/modules/aerodyn/src/AeroDyn_Inflow.f90 index c83971db0b..0418fa019b 100644 --- a/modules/aerodyn/src/AeroDyn_Inflow.f90 +++ b/modules/aerodyn/src/AeroDyn_Inflow.f90 @@ -347,7 +347,7 @@ subroutine ADI_InitInflowWind(Root, i_IW, u_AD, o_AD, IW, dt, InitOutData, errSt ! Box exceed allow for OLAF poitns if (allocated(o_AD%WakeLocationPoints)) then InitInData%BoxExceedAllowF = .true. - InitInData%BoxExceedAllowIdx = min(InitInData%BoxExceedAllowIdx, AD_BoxExceedPointsIdx(u_AD, o_AD)) + InitInData%BoxExceedAllowIdx = AD_BoxExceedPointsIdx(u_AD, o_AD) endif if (.not. i_IW%UseInputFile) then call NWTC_Library_Copyfileinfotype( i_IW%PassedFileData, InitInData%PassedFileData, MESH_NEWCOPY, errStat2, errMsg2 ); if (Failed()) return From 5bbddd98e934ad61fbd3900fcface1ec94841886 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 22 Nov 2024 15:18:31 -0700 Subject: [PATCH 09/31] Fix error in BoxExceedAllowIdx in glue code IfW defaults this to -1, so if OLAF is used it would simply pass -1 for the index rather than the correct location from the AD_BoxExceedPointsIdx routine. --- modules/openfast-library/src/FAST_Subs.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 7fc3954ec9..e23cfe2e04 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -578,7 +578,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, ! Wake -- we allow the wake positions to exceed the wind box if (allocated(AD%OtherSt(STATE_CURR)%WakeLocationPoints)) then Init%InData_IfW%BoxExceedAllowF = .true. - Init%InData_IfW%BoxExceedAllowIdx = min(Init%InData_IfW%BoxExceedAllowIdx, AD_BoxExceedPointsIdx(AD%Input(1), AD%OtherSt(STATE_CURR))) + Init%InData_IfW%BoxExceedAllowIdx = AD_BoxExceedPointsIdx(AD%Input(1), AD%OtherSt(STATE_CURR)) endif END IF From 239316f415234380ce149a2ef8c7d01d5b9a5305 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Sat, 23 Nov 2024 16:48:08 -0700 Subject: [PATCH 10/31] bugfix: IfW rotor points for disk average incorrect The calculations for the rotor disk average wind speed use a set of point projected on the disk perpindular to the hub at ~0.7 rotor radius in the hub YZ plane. However, the indices for this calculation were incorrect and projected the points onto disk in the hub XY plane. This was discovered after one of the cases used in the curled wake paper failed to run correctly with 3.5.4 for a turbine very close to the back edge of the high resolution domain. Also added some additional information about the location of points causing outside box bound errors. --- modules/inflowwind/src/IfW_FlowField.f90 | 8 +++++--- modules/inflowwind/src/InflowWind_Subs.f90 | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index a71b75dffc..d20e1815d5 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -1591,6 +1591,7 @@ subroutine Grid4DField_GetVel(G4D, Time, Position, Velocity, ErrStat, ErrMsg) real(ReKi) :: P(3, 16) ! Point values real(ReKi) :: tmp integer(IntKi) :: i + character(60) :: PtLoc ErrStat = ErrID_None ErrMsg = "" @@ -1627,11 +1628,12 @@ subroutine Grid4DField_GetVel(G4D, Time, Position, Velocity, ErrStat, ErrMsg) do i = 1, 4 if (Indx_Lo(i) <= 0) then Indx_Lo(i) = 1 - call SetErrStat(ErrID_Fatal, 'Outside the grid bounds.', ErrStat, ErrMsg, RoutineName) + write(PtLoc,'(A1,3(f8.2,A1))') '(',Position(1),',',Position(2),',',Position(3),')' + call SetErrStat(ErrID_Fatal, 'Outside the grid bounds: '//trim(PtLoc), ErrStat, ErrMsg, RoutineName) return elseif (Indx_Lo(i) >= G4D%n(i)) then - Indx_Lo(i) = max(G4D%n(i) - 1, 1) ! make sure it's a valid index - call SetErrStat(ErrID_Fatal, 'Outside the grid bounds.', ErrStat, ErrMsg, RoutineName) + write(PtLoc,'(A1,3(f8.2,A1))') '(',Position(1),',',Position(2),',',Position(3),')' + call SetErrStat(ErrID_Fatal, 'Outside the grid bounds: '//trim(PtLoc), ErrStat, ErrMsg, RoutineName) return end if Indx_Hi(i) = min(Indx_Lo(i) + 1, G4D%n(i)) ! make sure it's a valid index diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index de910b24c8..8b5a18b0c6 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -1047,9 +1047,9 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM do i=1,IfW_NumPtsAvg theta = pi +(i-1)*TwoPi/IfW_NumPtsAvg - p%PositionAvg(1,i) = R*cos(theta) - p%PositionAvg(2,i) = R*sin(theta) - p%PositionAvg(3,i) = 0.0_ReKi + p%PositionAvg(1,i) = 0.0_ReKi ! Hub X (perpindicular to rotor plane) + p%PositionAvg(2,i) = R*cos(theta) ! Hub Y + p%PositionAvg(3,i) = R*sin(theta) ! Hub Z (in vertical plane when azimuth=0) end do p%OutputAccel = InitInp%OutputAccel From ce8351ea2fbb356ae105d6e38ae00a630268c305 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 25 Nov 2024 13:05:51 -0700 Subject: [PATCH 11/31] IfW: use single point for disk average if no radius given --- modules/inflowwind/src/InflowWind_Subs.f90 | 39 +++++++++++++--------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index 8b5a18b0c6..c8349ffbd3 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -967,6 +967,7 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM ! Temporary variables INTEGER(IntKi) :: TmpErrStat !< Temporary error status for subroutine and function calls CHARACTER(ErrMsgLen) :: TmpErrMsg !< Temporary error message for subroutine and function calls + integer(IntKi) :: NumPtsAvg !< Number of points to use for disk average vel (1 if no radius) ! Local variables INTEGER(IntKi) :: I !< Generic counter @@ -1029,28 +1030,34 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM CALL AllocAry( m%y_Hub%VelocityUVW, 3, 1, "Array of velocities for hub values", TmpErrStat, TmpErrMsg ) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( m%u_Avg%PositionXYZ, 3, IfW_NumPtsAvg, "Array of positions for rotor-averaged values", TmpErrStat, TmpErrMsg ) + ! Disk Velocity calculations + if (InitInp%RadAvg < 0.0_ReKi) then + NumPtsAvg = 1_IntKi ! Use only hub point + else + NumPtsAvg = IfW_NumPtsAvg ! Use a field of points for disk average calculations + endif + + CALL AllocAry( m%u_Avg%PositionXYZ, 3, NumPtsAvg, "Array of positions for rotor-averaged values", TmpErrStat, TmpErrMsg ) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( m%y_Avg%VelocityUVW, 3, IfW_NumPtsAvg, "Array of velocities for rotor-averaged values", TmpErrStat, TmpErrMsg ) + CALL AllocAry( m%y_Avg%VelocityUVW, 3, NumPtsAvg, "Array of velocities for rotor-averaged values", TmpErrStat, TmpErrMsg ) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%PositionAvg, 3, IfW_NumPtsAvg, "Array of positions for computing average wind speed", TmpErrStat, TmpErrMsg ) + CALL AllocAry( p%PositionAvg, 3, NumPtsAvg, "Array of positions for computing average wind speed", TmpErrStat, TmpErrMsg ) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) IF ( ErrStat>= AbortErrLev ) RETURN if (InitInp%RadAvg < 0.0_ReKi) then - R = max(1.0_ReKi, InputFileData%Uniform_RefLength)/2.0_ReKi ! We'll use this as a guess for the rotor radius + p%PositionAvg = 0.0_ReKi ! Use only hub else - R = InitInp%RadAvg + ! Calculate a ring of points at 70 rotor radius + R = InitInp%RadAvg * 0.7_ReKi !70% radius + do i=1,NumPtsAvg + theta = pi +(i-1)*TwoPi/NumPtsAvg + p%PositionAvg(1,i) = 0.0_ReKi ! Hub X (perpindicular to rotor plane) + p%PositionAvg(2,i) = R*cos(theta) ! Hub Y + p%PositionAvg(3,i) = R*sin(theta) ! Hub Z (in vertical plane when azimuth=0) + end do end if - R = R * 0.7_ReKi !70% radius - - do i=1,IfW_NumPtsAvg - theta = pi +(i-1)*TwoPi/IfW_NumPtsAvg - p%PositionAvg(1,i) = 0.0_ReKi ! Hub X (perpindicular to rotor plane) - p%PositionAvg(2,i) = R*cos(theta) ! Hub Y - p%PositionAvg(3,i) = R*sin(theta) ! Hub Z (in vertical plane when azimuth=0) - end do p%OutputAccel = InitInp%OutputAccel @@ -1709,17 +1716,17 @@ SUBROUTINE InflowWind_GetSpatialAverage( Time, InputData, p, x, xd, z, OtherStat m%u_Avg%HubPosition = InputData%HubPosition m%u_Avg%HubOrientation = InputData%HubOrientation - do i=1,IfW_NumPtsAvg + do i=1,size(m%u_Avg%PositionXYZ,DIM=2) m%u_Avg%PositionXYZ(:,i) = matmul(InputData%HubOrientation,p%PositionAvg(:,i)) + InputData%HubPosition end do CALL CalculateOutput( Time, m%u_Avg, p, x, xd, z, OtherStates, m%y_Avg, m, FillWrOut, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - do i=1,IfW_NumPtsAvg + do i=1,size(m%u_Avg%PositionXYZ,DIM=2) MeanVelocity = MeanVelocity + m%y_Avg%VelocityUVW(:,i) end do - MeanVelocity = MeanVelocity / REAL(IfW_NumPtsAvg,ReKi) + MeanVelocity = MeanVelocity / REAL(size(m%u_Avg%PositionXYZ,DIM=2),ReKi) RETURN From 28c15b043687229ecc46890470a4fde955a283d7 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 25 Nov 2024 13:37:53 -0700 Subject: [PATCH 12/31] Update AD14 cases using disk average velocity --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index f282c79af7..a820ba376e 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit f282c79af7152d20ec7becb7a7c9edbf65cca71c +Subproject commit a820ba376e4f38413e01cacf461eaf5eb3c21154 From 84537f7d017aeef70170c4b1e89a87b5e61fb73c Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 25 Nov 2024 15:27:41 -0700 Subject: [PATCH 13/31] FF: increase number of output planes to 999 --- glue-codes/fast-farm/src/FAST_Farm_Subs.f90 | 14 +++++++------- modules/awae/src/AWAE.f90 | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/glue-codes/fast-farm/src/FAST_Farm_Subs.f90 b/glue-codes/fast-farm/src/FAST_Farm_Subs.f90 index 1ee45ea21e..0727b70b07 100644 --- a/glue-codes/fast-farm/src/FAST_Farm_Subs.f90 +++ b/glue-codes/fast-farm/src/FAST_Farm_Subs.f90 @@ -44,7 +44,7 @@ MODULE FAST_Farm_Subs integer, parameter :: maxOutputPoints = 9 - integer, parameter :: maxOutputPlanes = 99 ! Allow up to 99 outpt planes + integer, parameter :: maxOutputPlanes = 999 ! Allow up to 999 outpt planes CONTAINS @@ -1140,7 +1140,7 @@ SUBROUTINE Farm_ReadPrimaryFile( InputFile, p, WD_InitInp, AWAE_InitInp, SC_Init end if ! NOutDisWindXY - Number of XY planes for output of disturbed wind data across the low-resolution domain to .Low.DisXY..t.vtk (-) [0 to 9]: - CALL ReadVar( UnIn, InputFile, AWAE_InitInp%NOutDisWindXY, "NOutDisWindXY", "Number of XY planes for output of disturbed wind data across the low-resolution domain to .Low.DisXY..t.vtk (-) [0 to 99]", ErrStat2, ErrMsg2, UnEc) + CALL ReadVar( UnIn, InputFile, AWAE_InitInp%NOutDisWindXY, "NOutDisWindXY", "Number of XY planes for output of disturbed wind data across the low-resolution domain to .Low.DisXY..t.vtk (-) [0 to 999]", ErrStat2, ErrMsg2, UnEc) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if ( ErrStat >= AbortErrLev ) then call cleanup() @@ -1163,7 +1163,7 @@ SUBROUTINE Farm_ReadPrimaryFile( InputFile, p, WD_InitInp, AWAE_InitInp, SC_Init end if ! NOutDisWindYZ - Number of YZ planes for output of disturbed wind data across the low-resolution domain to .Low.DisYZ..t.vtk (-) [0 to 9]: - CALL ReadVar( UnIn, InputFile, AWAE_InitInp%NOutDisWindYZ, "NOutDisWindYZ", "Number of YZ planes for output of disturbed wind data across the low-resolution domain to .Low.DisYZ..t.vtk (-) [0 to 99]", ErrStat2, ErrMsg2, UnEc) + CALL ReadVar( UnIn, InputFile, AWAE_InitInp%NOutDisWindYZ, "NOutDisWindYZ", "Number of YZ planes for output of disturbed wind data across the low-resolution domain to .Low.DisYZ..t.vtk (-) [0 to 999]", ErrStat2, ErrMsg2, UnEc) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if ( ErrStat >= AbortErrLev ) then call cleanup() @@ -1186,7 +1186,7 @@ SUBROUTINE Farm_ReadPrimaryFile( InputFile, p, WD_InitInp, AWAE_InitInp, SC_Init end if ! NOutDisWindXZ - Number of XZ planes for output of disturbed wind data across the low-resolution domain to .Low/DisXZ..t.vtk (-) [0 to 9]: - CALL ReadVar( UnIn, InputFile, AWAE_InitInp%NOutDisWindXZ, "NOutDisWindXZ", "Number of XZ planes for output of disturbed wind data across the low-resolution domain to .Low/DisXZ..t.vtk (-) [0 to 99]", ErrStat2, ErrMsg2, UnEc) + CALL ReadVar( UnIn, InputFile, AWAE_InitInp%NOutDisWindXZ, "NOutDisWindXZ", "Number of XZ planes for output of disturbed wind data across the low-resolution domain to .Low/DisXZ..t.vtk (-) [0 to 999]", ErrStat2, ErrMsg2, UnEc) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if ( ErrStat >= AbortErrLev ) then call cleanup() @@ -1546,9 +1546,9 @@ SUBROUTINE Farm_ValidateInput( p, WD_InitInp, AWAE_InitInp, SC_InitInp, ErrStat, AWAE_InitInp%WrDisDT = p%DT_low * n_disDT_dt - if (AWAE_InitInp%NOutDisWindXY < 0 .or. AWAE_InitInp%NOutDisWindXY > maxOutputPlanes ) CALL SetErrStat( ErrID_Fatal, 'NOutDisWindXY must be in the range [0, 99].', ErrStat, ErrMsg, RoutineName ) - if (AWAE_InitInp%NOutDisWindYZ < 0 .or. AWAE_InitInp%NOutDisWindYZ > maxOutputPlanes ) CALL SetErrStat( ErrID_Fatal, 'NOutDisWindYZ must be in the range [0, 99].', ErrStat, ErrMsg, RoutineName ) - if (AWAE_InitInp%NOutDisWindXZ < 0 .or. AWAE_InitInp%NOutDisWindXZ > maxOutputPlanes ) CALL SetErrStat( ErrID_Fatal, 'NOutDisWindXZ must be in the range [0, 99].', ErrStat, ErrMsg, RoutineName ) + if (AWAE_InitInp%NOutDisWindXY < 0 .or. AWAE_InitInp%NOutDisWindXY > maxOutputPlanes ) CALL SetErrStat( ErrID_Fatal, 'NOutDisWindXY must be in the range [0, 999].', ErrStat, ErrMsg, RoutineName ) + if (AWAE_InitInp%NOutDisWindYZ < 0 .or. AWAE_InitInp%NOutDisWindYZ > maxOutputPlanes ) CALL SetErrStat( ErrID_Fatal, 'NOutDisWindYZ must be in the range [0, 999].', ErrStat, ErrMsg, RoutineName ) + if (AWAE_InitInp%NOutDisWindXZ < 0 .or. AWAE_InitInp%NOutDisWindXZ > maxOutputPlanes ) CALL SetErrStat( ErrID_Fatal, 'NOutDisWindXZ must be in the range [0, 999].', ErrStat, ErrMsg, RoutineName ) if (p%NOutDist < 0 .or. p%NOutDist > maxOutputPoints ) then CALL SetErrStat( ErrID_Fatal, 'NOutDist must be in the range [0, 9].', ErrStat, ErrMsg, RoutineName ) else diff --git a/modules/awae/src/AWAE.f90 b/modules/awae/src/AWAE.f90 index 86c882e235..29fc543112 100644 --- a/modules/awae/src/AWAE.f90 +++ b/modules/awae/src/AWAE.f90 @@ -1613,7 +1613,7 @@ subroutine AWAE_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg character(ErrMsgLen) :: errMsg2 character(*), parameter :: RoutineName = 'AWAE_CalcOutput' integer(intKi) :: n, n_high - character(2) :: PlaneNumStr ! 2 digit number of the output plane + character(3) :: PlaneNumStr ! 2 digit number of the output plane CHARACTER(1024) :: FileName INTEGER(IntKi) :: Un ! unit number of opened file @@ -1651,7 +1651,7 @@ subroutine AWAE_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg ! XY plane slices do k = 1,p%NOutDisWindXY - write(PlaneNumStr, '(i2.2)') k + write(PlaneNumStr, '(i3.3)') k call ExtractSlice( XYSlice, p%OutDisWindZ(k), p%Z0_low, p%nZ_low, p%nX_low, p%nY_low, p%dZ_low, m%Vdist_low_full, m%outVizXYPlane(:,:,:,1)) ! Create the output vtk file with naming /Low/DisXY.t.vtk FileName = trim(p%OutFileVTKRoot)//".Low.DisXY"//PlaneNumStr//"."//trim(Tstr)//".vtk" @@ -1665,7 +1665,7 @@ subroutine AWAE_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg ! YZ plane slices do k = 1,p%NOutDisWindYZ - write(PlaneNumStr, '(i2.2)') k + write(PlaneNumStr, '(i3.3)') k call ExtractSlice( YZSlice, p%OutDisWindX(k), p%X0_low, p%nX_low, p%nY_low, p%nZ_low, p%dX_low, m%Vdist_low_full, m%outVizYZPlane(:,:,:,1)) ! Create the output vtk file with naming /Low/DisYZ.t.vtk FileName = trim(p%OutFileVTKRoot)//".Low.DisYZ"//PlaneNumStr//"."//trim(Tstr)//".vtk" @@ -1679,7 +1679,7 @@ subroutine AWAE_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg ! XZ plane slices do k = 1,p%NOutDisWindXZ - write(PlaneNumStr, '(i2.2)') k + write(PlaneNumStr, '(i3.3)') k call ExtractSlice( XZSlice, p%OutDisWindY(k), p%Y0_low, p%nY_low, p%nX_low, p%nZ_low, p%dY_low, m%Vdist_low_full, m%outVizXZPlane(:,:,:,1)) ! Create the output vtk file with naming /Low/DisXZ.t.vtk FileName = trim(p%OutFileVTKRoot)//".Low.DisXZ"//PlaneNumStr//"."//trim(Tstr)//".vtk" From 17ac3c7658bcfcfb71ba3d07ea3b68cc808a8e20 Mon Sep 17 00:00:00 2001 From: Andy Platt Date: Tue, 26 Nov 2024 08:57:24 -0700 Subject: [PATCH 14/31] AWAE: update comment Co-authored-by: Derek Slaughter --- modules/awae/src/AWAE.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/awae/src/AWAE.f90 b/modules/awae/src/AWAE.f90 index 29fc543112..5a19a7315c 100644 --- a/modules/awae/src/AWAE.f90 +++ b/modules/awae/src/AWAE.f90 @@ -1613,7 +1613,7 @@ subroutine AWAE_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg character(ErrMsgLen) :: errMsg2 character(*), parameter :: RoutineName = 'AWAE_CalcOutput' integer(intKi) :: n, n_high - character(3) :: PlaneNumStr ! 2 digit number of the output plane + character(3) :: PlaneNumStr ! 3 digit number of the output plane CHARACTER(1024) :: FileName INTEGER(IntKi) :: Un ! unit number of opened file From ada86f4b8d5c106a73ec5771408f73270ca4be63 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 26 Nov 2024 16:11:22 +0000 Subject: [PATCH 15/31] Add BUILD_OPENFAST_CFD_DRIVER to build C++ driver for CFD interface (AMR-Wind/Nalu-Wind) --- .github/workflows/automated-dev-tests.yml | 1 + CMakeLists.txt | 1 + glue-codes/openfast-cpp/CMakeLists.txt | 2 +- reg_tests/CTestList.cmake | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/automated-dev-tests.yml b/.github/workflows/automated-dev-tests.yml index 7ca5d3dffa..1b370ab80a 100644 --- a/.github/workflows/automated-dev-tests.yml +++ b/.github/workflows/automated-dev-tests.yml @@ -199,6 +199,7 @@ jobs: -DBUILD_FASTFARM:BOOL=ON \ -DBUILD_OPENFAST_CPP_API:BOOL=ON \ -DBUILD_OPENFAST_CPP_DRIVER:BOOL=ON \ + -DBUILD_OPENFAST_CFD_DRIVER:BOOL=ON \ -DBUILD_SHARED_LIBS:BOOL=OFF \ -DBUILD_TESTING:BOOL=ON \ -DCTEST_PLOT_ERRORS:BOOL=ON \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3299153263..88cdeb08e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ option(ORCA_DLL_LOAD "Enable OrcaFlex Library Load" on) option(BUILD_FASTFARM "Enable building FAST.Farm" off) option(BUILD_OPENFAST_CPP_API "Enable building OpenFAST - C++ API" off) option(BUILD_OPENFAST_CPP_DRIVER "Enable building OpenFAST C++ driver using C++ API" off) +option(BUILD_OPENFAST_CFD_DRIVER "Enable building OpenFAST CFD driver using C++ CFD API" off) option(BUILD_OPENFAST_SIMULINK_API "Enable building OpenFAST for use with Simulink" off) option(OPENMP "Enable OpenMP support" off) option(USE_LOCAL_STATIC_LAPACK "Enable downloading and building static LAPACK and BLAS libs" off) diff --git a/glue-codes/openfast-cpp/CMakeLists.txt b/glue-codes/openfast-cpp/CMakeLists.txt index 6405e48cc6..f85f91e1e1 100644 --- a/glue-codes/openfast-cpp/CMakeLists.txt +++ b/glue-codes/openfast-cpp/CMakeLists.txt @@ -56,7 +56,7 @@ install(TARGETS openfastcpplib ) # Build driver if requested -if (BUILD_OPENFAST_CPP_DRIVER) +if (BUILD_OPENFAST_CFD_DRIVER) find_package(yaml-cpp REQUIRED) add_executable(openfastcpp src/FAST_Prog.cpp) diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake index 360133f860..b9c6dbf882 100644 --- a/reg_tests/CTestList.cmake +++ b/reg_tests/CTestList.cmake @@ -285,7 +285,7 @@ of_regression("MHK_RM1_Floating" "openfast;elastodyn;aerod of_regression("Tailfin_FreeYaw1DOF_PolarBased" "openfast;elastodyn;aerodyn15") # OpenFAST C++ API test -if(BUILD_OPENFAST_CPP_API) +if(BUILD_OPENFAST_CFD_DRIVER) of_cpp_interface_regression("5MW_Land_DLL_WTurb_cpp" "openfast;fastlib;cpp") endif() From dbfff8cddec3f797a2205997c4a746b486aa33f0 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 26 Nov 2024 17:03:07 +0000 Subject: [PATCH 16/31] Use CPP driver for CFD and LIB for the openfastlib C++ interface --- .github/workflows/automated-dev-tests.yml | 2 +- glue-codes/openfast-cpp/CMakeLists.txt | 2 +- glue-codes/openfast/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/automated-dev-tests.yml b/.github/workflows/automated-dev-tests.yml index 1b370ab80a..92402268bf 100644 --- a/.github/workflows/automated-dev-tests.yml +++ b/.github/workflows/automated-dev-tests.yml @@ -198,8 +198,8 @@ jobs: -DVARIABLE_TRACKING=OFF \ -DBUILD_FASTFARM:BOOL=ON \ -DBUILD_OPENFAST_CPP_API:BOOL=ON \ + -DBUILD_OPENFAST_LIB_DRIVER:BOOL=ON \ -DBUILD_OPENFAST_CPP_DRIVER:BOOL=ON \ - -DBUILD_OPENFAST_CFD_DRIVER:BOOL=ON \ -DBUILD_SHARED_LIBS:BOOL=OFF \ -DBUILD_TESTING:BOOL=ON \ -DCTEST_PLOT_ERRORS:BOOL=ON \ diff --git a/glue-codes/openfast-cpp/CMakeLists.txt b/glue-codes/openfast-cpp/CMakeLists.txt index f85f91e1e1..6405e48cc6 100644 --- a/glue-codes/openfast-cpp/CMakeLists.txt +++ b/glue-codes/openfast-cpp/CMakeLists.txt @@ -56,7 +56,7 @@ install(TARGETS openfastcpplib ) # Build driver if requested -if (BUILD_OPENFAST_CFD_DRIVER) +if (BUILD_OPENFAST_CPP_DRIVER) find_package(yaml-cpp REQUIRED) add_executable(openfastcpp src/FAST_Prog.cpp) diff --git a/glue-codes/openfast/CMakeLists.txt b/glue-codes/openfast/CMakeLists.txt index bc2e132339..402a790f69 100644 --- a/glue-codes/openfast/CMakeLists.txt +++ b/glue-codes/openfast/CMakeLists.txt @@ -33,7 +33,7 @@ endif() install(TARGETS openfast RUNTIME DESTINATION bin) -if(BUILD_OPENFAST_CPP_DRIVER) +if(BUILD_OPENFAST_LIB_DRIVER) add_executable(openfast_cpp_driver src/FAST_Prog.cpp src/FastLibAPI.cpp) target_link_libraries(openfast_cpp_driver openfastlib) From 9df336380a139f1359622ec4f3a761b3a320c503 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 26 Nov 2024 17:31:28 +0000 Subject: [PATCH 17/31] Missed an instance of BUILD_OPENFAST_LIB_DRIVER --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88cdeb08e2..0bd22f12a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,8 +44,8 @@ option(FPE_TRAP_ENABLED "Enable FPE trap in compiler options" off) option(ORCA_DLL_LOAD "Enable OrcaFlex Library Load" on) option(BUILD_FASTFARM "Enable building FAST.Farm" off) option(BUILD_OPENFAST_CPP_API "Enable building OpenFAST - C++ API" off) -option(BUILD_OPENFAST_CPP_DRIVER "Enable building OpenFAST C++ driver using C++ API" off) -option(BUILD_OPENFAST_CFD_DRIVER "Enable building OpenFAST CFD driver using C++ CFD API" off) +option(BUILD_OPENFAST_CPP_DRIVER "Enable building OpenFAST C++ driver using C++ CFD API" off) +option(BUILD_OPENFAST_LIB_DRIVER "Enable building OpenFAST driver using C++ Library API" off) option(BUILD_OPENFAST_SIMULINK_API "Enable building OpenFAST for use with Simulink" off) option(OPENMP "Enable OpenMP support" off) option(USE_LOCAL_STATIC_LAPACK "Enable downloading and building static LAPACK and BLAS libs" off) From 4943c199f30ccc00fe8ee610620951d606236188 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 27 Nov 2024 16:24:22 -0700 Subject: [PATCH 18/31] Update r-test pointer --- reg_tests/r-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg_tests/r-test b/reg_tests/r-test index a820ba376e..d9691df033 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit a820ba376e4f38413e01cacf461eaf5eb3c21154 +Subproject commit d9691df0339bbc718c63e1de8a1aaa642e978398 From 61549fcc2d9d638d74df6fa7eb304841a1447478 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 10 Dec 2024 14:38:32 -0700 Subject: [PATCH 19/31] Add `!$OMP critical` directives around some GetNewUnit/Open*File calls --- modules/aerodyn/src/AeroDyn_IO.f90 | 4 ++ modules/aerodyn/src/UnsteadyAero.f90 | 16 ++++--- modules/awae/src/AWAE_IO.f90 | 2 + modules/beamdyn/src/BeamDyn_IO.f90 | 6 +++ modules/elastodyn/src/ElastoDyn.f90 | 8 ++-- modules/elastodyn/src/ElastoDyn_IO.f90 | 39 +++++++-------- modules/hydrodyn/src/HydroDyn_Output.f90 | 8 ++++ modules/hydrodyn/src/Morison_Output.f90 | 2 + modules/hydrodyn/src/WAMIT2.f90 | 37 +++++---------- modules/inflowwind/src/InflowWind_IO.f90 | 34 +++++++------ modules/inflowwind/src/InflowWind_Subs.f90 | 2 + modules/nwtc-library/src/NWTC_IO.f90 | 8 ++++ modules/nwtc-library/src/VTK.f90 | 12 +++-- modules/openfast-library/src/FAST_Solver.f90 | 10 ++++ modules/openfast-library/src/FAST_Subs.f90 | 50 +++++++++++++------- modules/servodyn/src/ServoDyn_IO.f90 | 2 + modules/subdyn/src/SubDyn.f90 | 5 ++ 17 files changed, 155 insertions(+), 90 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn_IO.f90 b/modules/aerodyn/src/AeroDyn_IO.f90 index 24e56b0ab2..532fc55d2e 100644 --- a/modules/aerodyn/src/AeroDyn_IO.f90 +++ b/modules/aerodyn/src/AeroDyn_IO.f90 @@ -1080,6 +1080,7 @@ SUBROUTINE ReadBladeInputs ( ADBlFile, BladeKInputFileData, AeroProjMod, UnEc, E ErrMsg = "" UnIn = -1 + !$OMP critical(filename) CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1087,6 +1088,7 @@ SUBROUTINE ReadBladeInputs ( ADBlFile, BladeKInputFileData, AeroProjMod, UnEc, E ! Open the input file for blade K. CALL OpenFInpFile ( UnIn, ADBlFile, ErrStat2, ErrMsg2 ) + !$OMP end critical(filename) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) RETURN @@ -1324,8 +1326,10 @@ SUBROUTINE AD_PrintSum( InputFileData, p, p_AD, u, y, ErrStat, ErrMsg ) ! Open the summary file and give it a heading. + !$OMP critical(filename) CALL GetNewUnit( UnSu, ErrStat, ErrMsg ) CALL OpenFOutFile ( UnSu, TRIM( p%RootName )//'.sum', ErrStat, ErrMsg ) + !$OMP end critical(filename) IF ( ErrStat >= AbortErrLev ) RETURN ! Heading: diff --git a/modules/aerodyn/src/UnsteadyAero.f90 b/modules/aerodyn/src/UnsteadyAero.f90 index 84f0addf1c..a6686580f4 100644 --- a/modules/aerodyn/src/UnsteadyAero.f90 +++ b/modules/aerodyn/src/UnsteadyAero.f90 @@ -1328,10 +1328,12 @@ subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & p%Delim ='' if (p%NumOuts > 0) then + !$OMP critical(filename) CALL GetNewUnit( p%unOutFile, ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return - CALL OpenFOutFile ( p%unOutFile, trim(InitInp%OutRootName)//'.UA.out', ErrStat2, ErrMsg2 ) + if (ErrStat2 < AbortErrLev) then + CALL OpenFOutFile ( p%unOutFile, trim(InitInp%OutRootName)//'.UA.out', ErrStat2, ErrMsg2 ) + endif + !$OMP end critical(filename) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -3685,10 +3687,12 @@ subroutine UA_WriteAFIParamsToFile(InitInp, AFInfo, ErrStat, ErrMsg) ChanName(i) = 'c_Rate'; ChanUnit(i) = '(-/rad)'; i = i+1; ChanName(i) = 'c_RateUpper'; ChanUnit(i) = '(-/rad)'; i = i+1; + !$OMP critical(filename) CALL GetNewUnit( unOutFile, ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) RETURN - - CALL OpenFOutFile ( unOutFile, trim(InitInp%OutRootName)//'.UA.sum', ErrStat2, ErrMsg2 ) + if (ErrStat < AbortErrLev) then + CALL OpenFOutFile ( unOutFile, trim(InitInp%OutRootName)//'.UA.sum', ErrStat2, ErrMsg2 ) + endif + !$OMP end critical(filename) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return diff --git a/modules/awae/src/AWAE_IO.f90 b/modules/awae/src/AWAE_IO.f90 index 5d89f40978..a4b2720cf3 100644 --- a/modules/awae/src/AWAE_IO.f90 +++ b/modules/awae/src/AWAE_IO.f90 @@ -548,8 +548,10 @@ SUBROUTINE AWAE_PrintSum( p, u, y, ErrStat, ErrMsg ) ! Open the summary file and give it a heading. + !$OMP critical(fileopen) CALL GetNewUnit( UnSu, ErrStat, ErrMsg ) CALL OpenFOutFile ( UnSu, TRIM( p%OutFileRoot )//'.sum', ErrStat, ErrMsg ) + !$OMP end critical(fileopen) IF ( ErrStat >= AbortErrLev ) RETURN diff --git a/modules/beamdyn/src/BeamDyn_IO.f90 b/modules/beamdyn/src/BeamDyn_IO.f90 index 15ed92d7d6..d50d333122 100644 --- a/modules/beamdyn/src/BeamDyn_IO.f90 +++ b/modules/beamdyn/src/BeamDyn_IO.f90 @@ -588,9 +588,11 @@ SUBROUTINE BD_ReadPrimaryFile(InputFile,InputFileData,OutFileRoot,UnEc,ErrStat,E CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !$OMP critical(filename) CALL GetNewUnit(UnIn,ErrStat2,ErrMsg2) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL OpenFInpFile(UnIn,InputFile,ErrStat2,ErrMsg2) + !$OMP end critical(filename) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF (ErrStat >= AbortErrLev) then call cleanup() @@ -1048,9 +1050,11 @@ SUBROUTINE BD_ReadBladeFile(BldFile,BladeInputFileData,UnEc,ErrStat,ErrMsg) ErrStat = ErrID_None ErrMsg = "" + !$OMP critical(filename) CALL GetNewUnit(UnIn,ErrStat2,ErrMsg2) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL OpenFInpFile (UnIn,BldFile,ErrStat2,ErrMsg2) + !$OMP end critical(filename) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) if (ErrStat >= AbortErrLev) then return @@ -1940,8 +1944,10 @@ SUBROUTINE BD_PrintSum( p, x, OtherState, m, InitInp, ErrStat, ErrMsg ) ! Open the summary file and give it a heading. + !$OMP critical(filename) CALL GetNewUnit( UnSu, ErrStat, ErrMsg ) CALL OpenFOutFile ( UnSu, TRIM( InitInp%RootName )//'.sum.yaml', ErrStat, ErrMsg ) + !$OMP end critical(filename) IF ( ErrStat >= AbortErrLev ) RETURN ! Heading: diff --git a/modules/elastodyn/src/ElastoDyn.f90 b/modules/elastodyn/src/ElastoDyn.f90 index 28db59d3d5..061dbb3c11 100644 --- a/modules/elastodyn/src/ElastoDyn.f90 +++ b/modules/elastodyn/src/ElastoDyn.f90 @@ -9634,10 +9634,12 @@ SUBROUTINE ED_PrintSum( p, OtherState, ErrStat, ErrMsg ) ! Open the summary file and give it a heading. + !$OMP critical(filename) CALL GetNewUnit( UnSu, ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) RETURN - - CALL OpenFOutFile ( UnSu, TRIM( p%RootName )//'.sum', ErrStat, ErrMsg ) + if (ErrStat < AbortErrLev) then + CALL OpenFOutFile ( UnSu, TRIM( p%RootName )//'.sum', ErrStat, ErrMsg ) + endif + !$OMP end critical(filename) IF ( ErrStat /= ErrID_None ) RETURN diff --git a/modules/elastodyn/src/ElastoDyn_IO.f90 b/modules/elastodyn/src/ElastoDyn_IO.f90 index 698c57fe12..6e793c5c02 100644 --- a/modules/elastodyn/src/ElastoDyn_IO.f90 +++ b/modules/elastodyn/src/ElastoDyn_IO.f90 @@ -1582,12 +1582,13 @@ SUBROUTINE ReadBladeFile ( BldFile, BladeKInputFileData, UnEc, ErrStat, ErrMsg ) ErrMsg = "" UnIn = -1 + !$OMP critical(filename) CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) - - + IF (ErrStat2 < AbortErrLev) THEN ! Open the input file for blade K. - - CALL OpenFInpFile ( UnIn, BldFile, ErrStat2, ErrMsg2 ) + CALL OpenFInpFile ( UnIn, BldFile, ErrStat2, ErrMsg2 ) + ENDIF + !$OMP end critical(filename) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() @@ -1888,13 +1889,13 @@ SUBROUTINE ReadBladeMeshFileAD( BladeKInputFileMesh, MeshFile, UnEc, ErrStat, Er ! Get an available unit number for the file. + !$OMP critical(filename) CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN - - + IF ( ErrStat < AbortErrLev ) THEN ! Open the AeroDyn input file. - - CALL OpenFInpFile ( UnIn, MeshFile, ErrStat2, ErrMsg2 ) + CALL OpenFInpFile ( UnIn, MeshFile, ErrStat2, ErrMsg2 ) + ENDIF + !$OMP end critical(filename) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() @@ -2179,12 +2180,13 @@ SUBROUTINE ReadTowerFile( TwrFile, InputFileData, UnEc, ErrStat, ErrMsg ) ErrMsg = "" + !$OMP critical(filename) CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN - + IF ( ErrStat < AbortErrLev ) THEN ! Open the tower input file. - - CALL OpenFInpFile ( UnIn, TwrFile, ErrStat2, ErrMsg2 ) + CALL OpenFInpFile ( UnIn, TwrFile, ErrStat2, ErrMsg2 ) + ENDIF + !$OMP end critical(filename) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() @@ -2521,14 +2523,13 @@ SUBROUTINE ReadPrimaryFile( InputFile, InputFileData, BldFile, FurlFile, TwrFile ! Get an available unit number for the file. - + !$OMP critical(filename) CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN - - + IF ( ErrStat < AbortErrLev ) THEN ! Open the Primary input file. - - CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + ENDIF + !$OMP end critical(filename) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() diff --git a/modules/hydrodyn/src/HydroDyn_Output.f90 b/modules/hydrodyn/src/HydroDyn_Output.f90 index a48f6429ef..39addf3406 100644 --- a/modules/hydrodyn/src/HydroDyn_Output.f90 +++ b/modules/hydrodyn/src/HydroDyn_Output.f90 @@ -979,9 +979,11 @@ SUBROUTINE HDOut_OpenSum( UnSum, SummaryName, HD_Prog, ErrStat, ErrMsg ) ErrMsg = "" + !$OMP critical(fileopen) CALL GetNewUnit( UnSum ) CALL OpenFOutFile ( UnSum, SummaryName, ErrStat, ErrMsg ) + !$OMP end critical(fileopen) IF (ErrStat >=AbortErrLev) RETURN @@ -1033,10 +1035,12 @@ SUBROUTINE HDOut_WriteWvKinFiles( Rootname, HD_Prog, NStepWave, NNodes, NWaveEle DO iFile = 1,7 + !$OMP critical(fileopen) CALL GetNewUnit( UnWv ) WvName = Rootname // TRIM(extension(iFile)) CALL OpenFOutFile ( UnWv, WvName, ErrStat, ErrMsg ) + !$OMP end critical(fileopen) IF (ErrStat >=AbortErrLev) RETURN @@ -1084,10 +1088,12 @@ SUBROUTINE HDOut_WriteWvKinFiles( Rootname, HD_Prog, NStepWave, NNodes, NWaveEle IF ( NWaveElev > 0 ) THEN + !$OMP critical(fileopen) CALL GetNewUnit( UnWv ) WvName = Rootname // '.Elev' CALL OpenFOutFile ( UnWv, WvName, ErrStat, ErrMsg ) + !$OMP end critical(fileopen) IF (ErrStat >=AbortErrLev) RETURN @@ -1463,9 +1469,11 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta ! Open the file for output OutFileName = TRIM(OutRootName)//'.HD.out' + !$OMP critical(fileopen) CALL GetNewUnit( p%UnOutFile ) CALL OpenFOutFile ( p%UnOutFile, OutFileName, ErrStat, ErrMsg ) + !$OMP end critical(fileopen) IF (ErrStat >=AbortErrLev) RETURN diff --git a/modules/hydrodyn/src/Morison_Output.f90 b/modules/hydrodyn/src/Morison_Output.f90 index 4ec1db451a..d98a4565d2 100644 --- a/modules/hydrodyn/src/Morison_Output.f90 +++ b/modules/hydrodyn/src/Morison_Output.f90 @@ -6610,9 +6610,11 @@ SUBROUTINE MrsnOut_OpenOutput( ProgName, OutRootName, p, InitOut, ErrStat, ErrM ! Open the file for output OutFileName = TRIM(OutRootName)//'.MRSN.out' + !$OMP critical(fileopen) CALL GetNewUnit( p%UnOutFile ) CALL OpenFOutFile ( p%UnOutFile, OutFileName, ErrStat, ErrMsg ) + !$OMP end critical(fileopen) IF (ErrStat >=AbortErrLev) RETURN diff --git a/modules/hydrodyn/src/WAMIT2.f90 b/modules/hydrodyn/src/WAMIT2.f90 index 47653312a2..8cfe1026b2 100644 --- a/modules/hydrodyn/src/WAMIT2.f90 +++ b/modules/hydrodyn/src/WAMIT2.f90 @@ -3649,20 +3649,13 @@ SUBROUTINE Read_DataFile3D( InitInp, Filename3D, Data3D, ErrStat, Errmsg ) !------------------------------------------------------------------------------ ! Find a unit number to use + !$OMP critical(fileopen) CALL GetNewUnit(UnitDataFile,ErrStatTmp,ErrMsgTmp) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) - IF (ALLOCATED(RawData3D)) DEALLOCATE(RawData3D,STAT=ErrStatTmp) - IF (ALLOCATED(RawData3DTmp)) DEALLOCATE(RawData3DTmp,STAT=ErrStatTmp) - IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) - IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) - CALL CleanUp - RETURN - ENDIF - - ! Open the file - CALL OpenFInpFile( UnitDataFile, TRIM(Filename3D), ErrStat, ErrMsg ) ! Open file containing mean drift information + if (ErrStatTmp < AbortErrLev) then + ! Open the file + CALL OpenFInpFile( UnitDataFile, TRIM(Filename3D), ErrStat, ErrMsg ) ! Open file containing mean drift information + endif + !$OMP end critical(fileopen) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CLOSE( UnitDataFile ) @@ -4423,21 +4416,13 @@ SUBROUTINE Read_DataFile4D( InitInp, Filename4D, Data4D, ErrStat, Errmsg ) !------------------------------------------------------------------------------ ! Find a unit number to use + !$OMP critical(fileopen) CALL GetNewUnit(UnitDataFile,ErrStatTmp,ErrMsgTmp) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - IF (ALLOCATED(RawData4D)) DEALLOCATE(RawData4D,STAT=ErrStatTmp) - IF (ALLOCATED(RawData4DTmp)) DEALLOCATE(RawData4DTmp,STAT=ErrStatTmp) - IF (ALLOCATED(TmpRealArr)) DEALLOCATE(TmpRealArr,STAT=ErrStatTmp) - IF (ALLOCATED(TmpDataRow)) DEALLOCATE(TmpDataRow,STAT=ErrStatTmp) - IF (ALLOCATED(TmpWvFreq1)) DEALLOCATE(TmpWvFreq1,STAT=ErrStatTmp) - IF (ALLOCATED(TmpWvFreq2)) DEALLOCATE(TmpWvFreq2,STAT=ErrStatTmp) - CALL CleanUp - RETURN - ENDIF - + if (ErrStatTmp < AbortErrLev) then ! Open the file - CALL OpenFInpFile( UnitDataFile, TRIM(Filename4D), ErrStat, ErrMsg ) ! Open file containing mean drift information + CALL OpenFInpFile( UnitDataFile, TRIM(Filename4D), ErrStat, ErrMsg ) ! Open file containing mean drift information + endif + !$OMP end critical(fileopen) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CLOSE( UnitDataFile ) diff --git a/modules/inflowwind/src/InflowWind_IO.f90 b/modules/inflowwind/src/InflowWind_IO.f90 index e1b0f64547..b74a2e5143 100644 --- a/modules/inflowwind/src/InflowWind_IO.f90 +++ b/modules/inflowwind/src/InflowWind_IO.f90 @@ -518,12 +518,13 @@ subroutine IfW_TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) !---------------------------------------------------------------------------- ! Get a unit number to use for the wind file + !$OMP critical(fileopen) call GetNewUnit(WindFileUnit, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return - - ! Open binary file - call OpenBInpFile(WindFileUnit, TRIM(InitInp%WindFileName), TmpErrStat, TmpErrMsg) + if (TmpErrStat < AbortErrLev) then + ! Open binary file + call OpenBInpFile(WindFileUnit, TRIM(InitInp%WindFileName), TmpErrStat, TmpErrMsg) + endif + !$OMP end critical(fileopen) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -883,16 +884,17 @@ subroutine IfW_HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) TRIM(Num2LStr(G3D%GridBase + G3D%ZHWid*2))// & ' m above ground) with a characteristic wind speed of '//TRIM(Num2LStr(G3D%MeanWS))//' m/s. ') - ! Get a unit number to use for the wind file - call GetNewUnit(WindFileUnit, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return - ! Loop through wind components (X, Y, Z) do IC = 1, G3D%NComp - ! Open wind file for this component - call OpenBInpFile(WindFileUnit, InitInp%WindFileName(IC), TmpErrStat, TmpErrMsg) + ! Get a unit number to use for the wind file + !$OMP critical(fileopen) + call GetNewUnit(WindFileUnit, TmpErrStat, TmpErrMsg) + if (TmpErrStat < AbortErrLev) then + ! Open wind file for this component + call OpenBInpFile(WindFileUnit, InitInp%WindFileName(IC), TmpErrStat, TmpErrMsg) + endif + !$OMP end critical(fileopen) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -1132,16 +1134,18 @@ subroutine IfW_Bladed_Init(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, end if ! Get a unit number to use + !$OMP critical(fileopen) call GetNewUnit(UnitWind, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return + if (TmpErrStat < AbortErrLev) then !---------------------------------------------------------------------------- ! Open the binary file, read its "header" (first 2-byte integer) to ! determine what format binary file it is, and close it. !---------------------------------------------------------------------------- - call OpenBInpFile(UnitWind, TRIM(BinFileName), TmpErrStat, TmpErrMsg) + call OpenBInpFile(UnitWind, TRIM(BinFileName), TmpErrStat, TmpErrMsg) + endif + !$OMP end critical(fileopen) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index c8349ffbd3..e99dae4377 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -1575,8 +1575,10 @@ SUBROUTINE InflowWind_OpenSumFile( SumFileUnit, SummaryName, IfW_Prog, WindType, ErrMsg = "" SumFileUnit = -1 + !$OMP critical(fileopen) CALL GetNewUnit( SumFileUnit ) CALL OpenFOutFile ( SumFileUnit, SummaryName, ErrStat, ErrMsg ) + !$OMP end critical(fileopen) IF (ErrStat >=AbortErrLev) RETURN diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index 931aaf76e7..656f46840d 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -2409,6 +2409,7 @@ SUBROUTINE OpenEcho ( Un, OutFile, ErrStat, ErrMsg, ProgVer ) ! Get a unit number for the echo file: + !$OMP critical(fileopenNWTCio) IF ( Un < 0 ) THEN CALL GetNewUnit( Un, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat, ErrMsg, RoutineName ) @@ -2419,6 +2420,7 @@ SUBROUTINE OpenEcho ( Un, OutFile, ErrStat, ErrMsg, ProgVer ) CALL OpenFOutFile( Un, OutFile, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2,ErrStat, ErrMsg, RoutineName ) + !$OMP end critical(fileopenNWTCio) IF ( ErrStat >= AbortErrLev ) RETURN @@ -4615,11 +4617,13 @@ RECURSIVE SUBROUTINE ReadComFile ( FileInfo, FileIndx, AryInd, StartLine, LastLi RETURN END IF + !$OMP critical(fileopenNWTCio) CALL GetNewUnit ( UnIn, ErrStatLcl, ErrMsg2 ) CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL OpenFInpFile ( UnIn, FileInfo%FileList(FileIndx), ErrStatLcl, ErrMsg2 ) CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !$OMP end critical(fileopenNWTCio) IF ( ErrStat >= AbortErrLev ) RETURN @@ -6410,9 +6414,11 @@ RECURSIVE SUBROUTINE ScanComFile ( FirstFile, ThisFile, LastFile, StartLine, Las ! Open the input file. UnIn = -1 + !$OMP critical(fileopenNWTCio) CALL GetNewUnit ( UnIn, ErrStatLcl, ErrMsg2 ) CALL OpenFInpFile ( UnIn, Filename, ErrStatLcl, ErrMsg2 ) + !$OMP end critical(fileopenNWTCio) IF ( ErrStatLcl /= 0 ) THEN CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL Cleanup() @@ -6720,6 +6726,7 @@ SUBROUTINE WrBinFAST(FileName, FileID, DescStr, ChanName, ChanUnit, TimeData, Al ! Generate the unit number for the binary file UnIn = 0 + !$OMP critical(fileopenNWTCio) CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) @@ -6729,6 +6736,7 @@ SUBROUTINE WrBinFAST(FileName, FileID, DescStr, ChanName, ChanUnit, TimeData, Al CALL OpenBOutFile ( UnIn, TRIM(FileName), ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + !$OMP end critical(fileopenNWTCio) IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() RETURN diff --git a/modules/nwtc-library/src/VTK.f90 b/modules/nwtc-library/src/VTK.f90 index fb57a5781b..0083582caf 100644 --- a/modules/nwtc-library/src/VTK.f90 +++ b/modules/nwtc-library/src/VTK.f90 @@ -94,8 +94,10 @@ SUBROUTINE WrVTK_header( FileName, NumberOfPoints, NumberOfLines, NumberOfPolys, INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< error level/status of OpenFOutFile operation CHARACTER(*) , INTENT( OUT) :: ErrMsg !< message when error occurs + !$OMP critical(fileopen) CALL GetNewUnit( Un, ErrStat, ErrMsg ) CALL OpenFOutFile ( Un, TRIM(FileName), ErrStat, ErrMsg ) + !$OMP end critical(fileopen) if (ErrStat >= AbortErrLev) return ! Write a VTP mesh file (Polygonal VTK file) with positions and polygons (surfaces) @@ -158,10 +160,10 @@ SUBROUTINE ReadVTK_SP_info( FileName, descr, dims, origin, gridSpacing, vecLabel closeOnReturn = .FALSE. END IF - !$OMP critical + !$OMP critical(fileopen) CALL GetNewUnit( Un, ErrStat, ErrMsg ) CALL OpenFInpFile ( Un, TRIM(FileName), ErrStat, ErrMsg ) - !$OMP end critical + !$OMP end critical(fileopen) if (ErrStat >= AbortErrLev) return CALL ReadCom( Un, FileName, 'File header: Module Version (line 1)', ErrStat2, ErrMsg2, 0 ) @@ -360,10 +362,10 @@ SUBROUTINE WrVTK_SP_header( FileName, descr, Un, ErrStat, ErrMsg ) INTEGER(IntKi) , INTENT( OUT) :: ErrStat !< error level/status of OpenFOutFile operation CHARACTER(*) , INTENT( OUT) :: ErrMsg !< message when error occurs - !$OMP critical + !$OMP critical(fileopen) CALL GetNewUnit( Un, ErrStat, ErrMsg ) CALL OpenFOutFile ( Un, TRIM(FileName), ErrStat, ErrMsg ) - !$OMP end critical + !$OMP end critical(fileopen) if (ErrStat >= AbortErrLev) return WRITE(Un,'(A)') '# vtk DataFile Version 3.0' @@ -451,6 +453,7 @@ logical function vtk_new_ascii_file(filename,label,mvtk) logical :: b if (.not. mvtk%bFileOpen) then + !$OMP critical(fileopen) CALL GetNewUnit( mvtk%vtk_unit ) if (mvtk%bBinary) then ! Fortran 2003 stream, otherwise intel fortran ! @@ -466,6 +469,7 @@ logical function vtk_new_ascii_file(filename,label,mvtk) else open(mvtk%vtk_unit,file=trim(adjustl(filename)),iostat=iostatvar,action="write",status='replace') endif + !$OMP end critical(fileopen) if (iostatvar == 0) then if (mvtk%bBinary) then write(mvtk%vtk_unit)'# vtk DataFile Version 3.0'//NewLine diff --git a/modules/openfast-library/src/FAST_Solver.f90 b/modules/openfast-library/src/FAST_Solver.f90 index 1f6653285c..01138be3f1 100644 --- a/modules/openfast-library/src/FAST_Solver.f90 +++ b/modules/openfast-library/src/FAST_Solver.f90 @@ -1839,8 +1839,10 @@ SUBROUTINE ED_HD_InputOutputSolve( this_time, p_FAST, calcJacobian & #ifdef OUTPUT_ADDEDMASS UnAM = -1 + !$OMP critical(fileopen) CALL GetNewUnit( UnAM, ErrStat, ErrMsg ) CALL OpenFOutFile( UnAM, TRIM(p_FAST%OutFileRoot)//'.AddedMassMatrix', ErrStat2, ErrMsg2) + !$OMP end critical(fileopen) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp() @@ -1853,8 +1855,10 @@ SUBROUTINE ED_HD_InputOutputSolve( this_time, p_FAST, calcJacobian & #endif #ifdef OUTPUT_JACOBIAN UnJac = -1 + !$OMP critical(fileopen) CALL GetNewUnit( UnJac, ErrStat2, ErrMsg2 ) CALL OpenFOutFile( UnJac, TRIM(p_FAST%OutFileRoot)//'.'//TRIM(num2lstr(this_time))//'.Jacobian2', ErrStat2, ErrMsg2) + !$OMP end critical(fileopen) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) THEN CALL CleanUp() @@ -2608,8 +2612,10 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & #ifdef OUTPUT_ADDEDMASS IF (p_FAST%CompHydro == Module_HD ) THEN UnAM = -1 + !$OMP critical(fileopen) CALL GetNewUnit( UnAM, ErrStat2, ErrMsg2 ) CALL OpenFOutFile( UnAM, TRIM(p_FAST%OutFileRoot)//'.AddedMassMatrix', ErrStat2, ErrMsg2) + !$OMP end critical(fileopen) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) RETURN @@ -2621,8 +2627,10 @@ SUBROUTINE FullOpt1_InputOutputSolve( this_time, p_FAST, calcJacobian & #endif #ifdef OUTPUT_JACOBIAN UnJac = -1 + !$OMP critical(fileopen) CALL GetNewUnit( UnJac, ErrStat2, ErrMsg2 ) CALL OpenFOutFile( UnJac, TRIM(p_FAST%OutFileRoot)//'.'//TRIM(num2lstr(this_time))//'.Jacobian', ErrStat2, ErrMsg2) + !$OMP end critical(fileopen) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) RETURN @@ -5095,8 +5103,10 @@ SUBROUTINE CalcOutputs_And_SolveForInputs( n_t_global, this_time, this_state, ca #ifdef OUTPUT_MASS_MATRIX if (n_t_global == 0) then UnMM = -1 + !$OMP critical(fileopen) CALL GetNewUnit( UnMM, ErrStat2, ErrMsg2 ) CALL OpenFOutFile( UnMM, TRIM(p_FAST%OutFileRoot)//'.EDMassMatrix', ErrStat2, ErrMsg2) + !$OMP end critical(fileopen) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) RETURN CALL WrMatrix(ED%m%AugMat,UnMM, p_FAST%OutFmt) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index e23cfe2e04..9e0af8c935 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -2280,11 +2280,13 @@ SUBROUTINE FAST_InitOutput( p_FAST, y_FAST, Init, ErrStat, ErrMsg ) y_FAST%OutFmt_a = trim(y_FAST%OutFmt_a)//','//trim(num2lstr(y_FAST%ActualChanLen - p_FAST%FmtWidth))//'x' end if + !$OMP critical(fileopen) CALL GetNewUnit( y_FAST%UnOu, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN - - CALL OpenFOutFile ( y_FAST%UnOu, TRIM(p_FAST%OutFileRoot)//'.out', ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN + IF ( ErrStat < AbortErrLev ) then + CALL OpenFOutFile ( y_FAST%UnOu, TRIM(p_FAST%OutFileRoot)//'.out', ErrStat, ErrMsg ) + ENDIF + !$OMP end critical(fileopen) + IF ( ErrStat >= AbortErrLev ) RETURN ! Add some file information: @@ -2415,18 +2417,18 @@ SUBROUTINE FAST_ReadPrimaryFile( InputFile, p, m_FAST, OverrideAbortErrLev, ErrS ! Get an available unit number for the file. + !$OMP critical(fileopen) CALL GetNewUnit( UnIn, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN - - + if ( ErrStat < AbortErrLev ) then ! Open the Primary input file. - - CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2,ErrStat,ErrMsg,RoutineName) - if ( ErrStat >= AbortErrLev ) then - call cleanup() - RETURN - end if + endif + !$OMP end critical(fileopen) + if ( ErrStat >= AbortErrLev ) then + call cleanup() + RETURN + end if ! Read the lines up/including to the "Echo" simulation control variable @@ -3929,11 +3931,13 @@ SUBROUTINE FAST_WrSum( p_FAST, y_FAST, MeshMapData, ErrStat, ErrMsg ) ! Get a unit number and open the file: + !$OMP critical(fileopen) CALL GetNewUnit( y_FAST%UnSum, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN - - CALL OpenFOutFile ( y_FAST%UnSum, TRIM(p_FAST%OutFileRoot)//'.sum', ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN + if ( ErrStat < AbortErrLev ) then + CALL OpenFOutFile ( y_FAST%UnSum, TRIM(p_FAST%OutFileRoot)//'.sum', ErrStat, ErrMsg ) + endif + !$OMP end critical(fileopen) + IF ( ErrStat >= AbortErrLev ) RETURN ! Add some file information: @@ -6173,8 +6177,10 @@ SUBROUTINE WriteInputMeshesToFile(u_ED, u_AD, u_SD, u_HD, u_MAP, u_BD, FileName, ! Open the binary output file: unOut=-1 + !$OMP critical(fileopen) CALL GetNewUnit( unOut, ErrStat, ErrMsg ) CALL OpenBOutFile ( unOut, TRIM(FileName), ErrStat, ErrMsg ) + !$OMP end critical(fileopen) IF (ErrStat /= ErrID_None) RETURN ! note that I'm not doing anything with the errors here, so it won't tell @@ -6252,9 +6258,11 @@ SUBROUTINE WriteMotionMeshesToFile(time, y_ED, u_SD, y_SD, u_HD, u_MAP, y_BD, u_ ! Open the binary output file and write a header: if (unOut<0) then + !$OMP critical(fileopen) CALL GetNewUnit( unOut, ErrStat, ErrMsg ) CALL OpenBOutFile ( unOut, TRIM(FileName), ErrStat, ErrMsg ) + !$OMP end critical(fileopen) IF (ErrStat /= ErrID_None) RETURN ! Add a file identification number (in case we ever have to change this): @@ -7045,8 +7053,10 @@ SUBROUTINE FAST_CreateCheckpoint_T(t_initial, n_t_global, NumTurbines, Turbine, IF ( unOut < 0 ) THEN + !$OMP critical(fileopen) CALL GetNewUnit( unOut, ErrStat2, ErrMsg2 ) CALL OpenBOutFile ( unOut, FileName, ErrStat2, ErrMsg2) + !$OMP end critical(fileopen) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) if (ErrStat >= AbortErrLev ) then call cleanup() @@ -7213,9 +7223,11 @@ SUBROUTINE FAST_RestoreFromCheckpoint_T(t_initial, n_t_global, NumTurbines, Turb IF ( unIn < 0 ) THEN + !$OMP critical(fileopen) CALL GetNewUnit( unIn, ErrStat2, ErrMsg2 ) CALL OpenBInpFile ( unIn, FileName, ErrStat2, ErrMsg2) + !$OMP end critical(fileopen) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF (ErrStat >= AbortErrLev ) RETURN @@ -7617,9 +7629,11 @@ SUBROUTINE ReadModeShapeMatlabFile(p_FAST, ErrStat, ErrMsg) ErrMsg = "" ! Open data file. + !$OMP critical(fileopen) CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) CALL OpenBInpFile ( UnIn, trim(p_FAST%VTK_modes%MatlabFileName), ErrStat2, ErrMsg2 ) + !$OMP end critical(fileopen) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF (ErrStat >= AbortErrLev) RETURN @@ -7743,9 +7757,11 @@ SUBROUTINE ReadModeShapeFile(p_FAST, InputFile, ErrStat, ErrMsg, checkpointOnly) CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. ! Open data file. + !$OMP critical(fileopen) CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) + !$OMP end critical(fileopen) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF (ErrStat >= AbortErrLev) RETURN diff --git a/modules/servodyn/src/ServoDyn_IO.f90 b/modules/servodyn/src/ServoDyn_IO.f90 index cb900579ec..373440979a 100644 --- a/modules/servodyn/src/ServoDyn_IO.f90 +++ b/modules/servodyn/src/ServoDyn_IO.f90 @@ -2400,8 +2400,10 @@ subroutine InitializeSummaryFile(InputFileData,OutfileRoot,UnSum,ErrStat,ErrMsg) ErrStat = ErrID_None ErrMsg = '' if ( InputFileData%SumPrint ) then + !$OMP critical(fileopen) call GetNewUnit( UnSum ) CALL OpenEcho ( UnSum, TRIM(OutFileRoot)//'.sum', ErrStat2, ErrMsg2 ) + !$OMP end critical(fileopen) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) IF (ErrStat >= AbortErrLev) RETURN else diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 1258379d05..e2f7bc7e8d 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -866,9 +866,11 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) UnEc = -1 Echo = .FALSE. +!$OMP critical(fileopen) CALL GetNewUnit( UnIn ) CALL OpenFInpfile(UnIn, TRIM(SDInputFile), ErrStat2, ErrMsg2) +!$OMP end critical(fileopen) IF ( ErrStat2 /= ErrID_None ) THEN Call Fatal('Could not open SubDyn input file') @@ -3470,6 +3472,7 @@ END SUBROUTINE OutModes !> Write the common part of the JSON file (Nodes, Connectivity, Element prop) +!FIXME: error handling is broken here!!! SUBROUTINE WriteJSONCommon(FileName, Init, p, m, InitInput, FileKind, UnSum, ErrStat, ErrMsg) use JSON, only: json_write_array TYPE(SD_InitType), INTENT(INOUT) :: Init !< Input data for initialization routine @@ -3491,8 +3494,10 @@ SUBROUTINE WriteJSONCommon(FileName, Init, p, m, InitInput, FileKind, UnSum, Err ! --- Create file and get unit UnSum = -1 ! we haven't opened the summary file, yet. + !$OMP critical(fileopen) call GetNewUnit( UnSum ) call OpenFOutFile ( UnSum, FileName, ErrStat2, ErrMsg2 ) + !$OMP end critical(fileopen) write(UnSum, '(A)')'{' ! --- Misc From 6bacfca574416e1837e9fd0ad99b6e251059c0c1 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 11 Dec 2024 21:53:38 +0000 Subject: [PATCH 20/31] Modify NWTC_IO's GetWords function to handle quoted strings properly --- modules/nwtc-library/src/NWTC_IO.f90 | 117 +++++++++++++++------------ 1 file changed, 67 insertions(+), 50 deletions(-) diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index 931aaf76e7..a248bf54f6 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -62,7 +62,7 @@ MODULE NWTC_IO CHARACTER(99) :: ProgVer = ' ' !< The version (including date) of the calling program. DO NOT USE THIS IN NEW PROGRAMS CHARACTER(1), PARAMETER :: Tab = CHAR( 9 ) !< The tab character. CHARACTER(*), PARAMETER :: CommChars = '!#%' !< Comment characters that mark the end of useful input - INTEGER(IntKi), PARAMETER :: NWTC_SizeOfNumWord = 200 !< maximum length of the words containing numeric input (for ParseVar routines) + INTEGER(IntKi), PARAMETER :: NWTC_SizeOfNumWord = 256 !< maximum length of the words containing numeric input (for ParseVar routines) ! Parameters for writing to echo files (in this module only) @@ -2068,70 +2068,87 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) INTEGER, INTENT(IN) :: NumWords !< The maximum number of words to look for (and size of Words) CHARACTER(*), INTENT(IN) :: Line !< The string to search. - CHARACTER(*), INTENT(OUT) :: Words(NumWords) !< The array of found words. + CHARACTER(*), INTENT(OUT) :: Words(:) !< The array of found words. INTEGER, OPTIONAL, INTENT(OUT) :: NumFound !< The number of words found - ! Local declarations. - - INTEGER :: Ch ! Character position within the string. - INTEGER :: IW ! Word index. - INTEGER :: NextWhite ! The location of the next whitespace in the string. + INTEGER :: iWord ! Word index. + INTEGER :: i ! Character index in line. + INTEGER :: iChar ! Character index in word. + CHARACTER(len=1) :: Char ! Current character + LOGICAL :: InQuotes ! Flag indicating text is within quotes + ! If no text on line, return + if (len_trim(Line) == 0) return + ! Let's prefill the array with blanks. + do iWord = 1, NumWords + Words(iWord) = ' ' + end do - ! Let's prefill the array with blanks. - - DO IW=1,NumWords - Words(IW) = ' ' - END DO ! IW + ! Initialize number of words found to zero if present + if (present(NumFound)) NumFound = 0 - IW = 0 + ! If no text on line, return + if (len_trim(Line) == 0) return + ! Initialize word index to first word + iWord = 1 - ! Let's make sure we have text on this line. - - IF ( LEN_TRIM( Line ) > 0 ) THEN - - ! Parse words separated by any combination of spaces, tabs, commas, - ! semicolons, single quotes, and double quotes ("whitespace"). - - Ch = 0 - - DO - - NextWhite = SCAN( Line(Ch+1:) , ' ,;''"'//Tab ) - - IF ( NextWhite > 1 ) THEN - - IW = IW + 1 - Words(IW) = Line(Ch+1:Ch+NextWhite-1) - if (NextWhite > len(words(iw)) ) then - call ProgWarn('Error reading field from file. There are too many characters in the input file to store in the field. Value may be truncated.') - end if - - IF ( IW == NumWords ) EXIT - - Ch = Ch + NextWhite - - ELSE IF ( NextWhite == 1 ) THEN - - Ch = Ch + 1 + ! Initialize index within word + iChar = 0 + + ! Initialize in quotes to false + InQuotes = .false. + + ! Loop through characters in line + do i = 1, len_trim(line) + + ! Get current character + Char = Line(i:i) + + ! Select based on character + select case (Char) + case ('"', "'") ! Double quotes, single quotes + if (InQuotes) then + InQuotes = .false. + if (iChar > 0) then + iWord = iWord + 1 + iChar = 0 + end if + else + InQuotes = .true. + end if + cycle + + case (' ', ',', ';', Tab) ! Whitespace, comma, semicolon + if (.not. InQuotes) then + if (iChar > 0) then + iWord = iWord + 1 + iChar = 0 + end if + cycle + end if + end select - CYCLE + ! If sufficient words have been collected, exit loop + if (iWord > NumWords) exit - ELSE + ! Increment character index + iChar = iChar + 1 - EXIT + ! If index is larger than length of word, continue + if (iChar > len(words(iWord))) then + call ProgWarn('Error reading field from file. There are too many characters in the input file to store in the field. Value may be truncated.') + cycle + end if - END IF + ! Add character to word + Words(iWord)(iChar:iChar) = Char - END DO - - END IF + end do - IF (PRESENT(NumFound)) NumFound = IW + if (present(NumFound)) NumFound = iWord - RETURN END SUBROUTINE GetWords !======================================================================= !> This routine converts an ASCII array of integers into an equivalent string From 4c6aad12795000b63cbdd82d1e398d5259df4c73 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 11 Dec 2024 21:55:42 +0000 Subject: [PATCH 21/31] Use NumWords for length of array --- modules/nwtc-library/src/NWTC_IO.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index a248bf54f6..e9a2da6958 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -2068,7 +2068,7 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) INTEGER, INTENT(IN) :: NumWords !< The maximum number of words to look for (and size of Words) CHARACTER(*), INTENT(IN) :: Line !< The string to search. - CHARACTER(*), INTENT(OUT) :: Words(:) !< The array of found words. + CHARACTER(*), INTENT(OUT) :: Words(NumWords) !< The array of found words. INTEGER, OPTIONAL, INTENT(OUT) :: NumFound !< The number of words found INTEGER :: iWord ! Word index. From 7ffff7ebc09ca02f946cdc329fed1ad4e91a11e6 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 12 Dec 2024 15:29:58 +0000 Subject: [PATCH 22/31] GetWords: always break on ',' and ';' --- modules/nwtc-library/src/NWTC_IO.f90 | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index e9a2da6958..500dcde4fc 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -2120,7 +2120,8 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) end if cycle - case (' ', ',', ';', Tab) ! Whitespace, comma, semicolon + case (' ', Tab) ! Whitespace + ! If between quotes, keep whitespace; otherwise separate words if (.not. InQuotes) then if (iChar > 0) then iWord = iWord + 1 @@ -2128,6 +2129,14 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) end if cycle end if + + case (',', ';') ! Comma, semicolon + ! Always separate words on these characters + if (iChar > 0) then + iWord = iWord + 1 + iChar = 0 + end if + cycle end select ! If sufficient words have been collected, exit loop @@ -2138,7 +2147,7 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) ! If index is larger than length of word, continue if (iChar > len(words(iWord))) then - call ProgWarn('Error reading field from file. There are too many characters in the input file to store in the field. Value may be truncated.') + call ProgWarn('Error reading field from file. There are too many characters in the input file to store in the field. Value may be truncated. '//Line) cycle end if From 892756db5d0b86480d74fb2ee832b38a1b7984d8 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 12 Dec 2024 16:46:57 +0000 Subject: [PATCH 23/31] Add IgnoreQuotes arg to GetWords and add IsPath arg to ParseChVar --- modules/nwtc-library/src/NWTC_IO.f90 | 34 +++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index 500dcde4fc..602fad45da 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -2061,7 +2061,7 @@ END SUBROUTINE GetTokens !! It uses spaces, tabs, commas, semicolons, single quotes, and double quotes ("whitespace") !! as word separators. If there aren't NumWords in the line, the remaining array elements will remain empty. !! Use CountWords (nwtc_io::countwords) to count the number of words in a line. - SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) + SUBROUTINE GetWords ( Line, Words, NumWords, NumFound, IgnoreQuotes ) ! Argument declarations. @@ -2070,16 +2070,25 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) CHARACTER(*), INTENT(IN) :: Line !< The string to search. CHARACTER(*), INTENT(OUT) :: Words(NumWords) !< The array of found words. INTEGER, OPTIONAL, INTENT(OUT) :: NumFound !< The number of words found + LOGICAL, OPTIONAL, INTENT(OUT) :: IgnoreQuotes !< Flag to ignore quotes (process as whitespace) INTEGER :: iWord ! Word index. INTEGER :: i ! Character index in line. INTEGER :: iChar ! Character index in word. CHARACTER(len=1) :: Char ! Current character LOGICAL :: InQuotes ! Flag indicating text is within quotes + LOGICAL :: IgnoreQuotesLoc ! Local flag to ignore quotes ! If no text on line, return if (len_trim(Line) == 0) return + ! If ignore quotes is present, set local flag, otherwise true + if (present(IgnoreQuotes)) then + IgnoreQuotesLoc = IgnoreQuotes + else + IgnoreQuotesLoc = .true. + end if + ! Let's prefill the array with blanks. do iWord = 1, NumWords Words(iWord) = ' ' @@ -2109,9 +2118,11 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) ! Select based on character select case (Char) case ('"', "'") ! Double quotes, single quotes - if (InQuotes) then + if (IgnoreQuotesLoc .or. InQuotes) then InQuotes = .false. if (iChar > 0) then + ! If requested number of words found, exit + if (iWord == NumWords) exit iWord = iWord + 1 iChar = 0 end if @@ -2124,6 +2135,8 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) ! If between quotes, keep whitespace; otherwise separate words if (.not. InQuotes) then if (iChar > 0) then + ! If requested number of words found, exit + if (iWord == NumWords) exit iWord = iWord + 1 iChar = 0 end if @@ -2133,15 +2146,14 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound ) case (',', ';') ! Comma, semicolon ! Always separate words on these characters if (iChar > 0) then + ! If requested number of words found, exit + if (iWord == NumWords) exit iWord = iWord + 1 iChar = 0 end if cycle end select - ! If sufficient words have been collected, exit loop - if (iWord > NumWords) exit - ! Increment character index iChar = iChar + 1 @@ -2910,7 +2922,7 @@ END SUBROUTINE ParseCom !! !! WARNING: This routine assumes the "words" containing the variable name and value are <= 20 characters. \n !! Use ParseVar (nwtc_io::parsevar) instead of directly calling a specific routine in the generic interface. - SUBROUTINE ParseChVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnEc ) + SUBROUTINE ParseChVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnEc, IsPath ) ! Arguments declarations. @@ -2919,6 +2931,7 @@ SUBROUTINE ParseChVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnE INTEGER(IntKi), INTENT(INOUT) :: LineNum !< The number of the line to parse. INTEGER, INTENT(IN), OPTIONAL :: UnEc !< I/O unit for echo file. If present and > 0, write to UnEc. + LOGICAL, INTENT(IN), OPTIONAL :: IsPath !< Flag indicating that string is a path. CHARACTER(*), INTENT(OUT) :: Var !< The variable to receive the input value. CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if ErrStat /= 0. @@ -2931,6 +2944,7 @@ SUBROUTINE ParseChVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnE INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. INTEGER(IntKi) :: NameIndx ! The index into the Words array that points to the variable name. + LOGICAL :: IgnoreQuotes CHARACTER(NWTC_SizeOfNumWord) :: Words (2) ! The two "words" parsed from the line. CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -2950,8 +2964,12 @@ SUBROUTINE ParseChVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnE RETURN END IF - - CALL GetWords ( FileInfo%Lines(LineNum), Words, 2 ) ! Read the first two words in Line. + if (present(IsPath)) then + IgnoreQuotes = .not. IsPath + else + IgnoreQuotes = .true. + end if + CALL GetWords ( FileInfo%Lines(LineNum), Words, 2, IgnoreQuotes=IgnoreQuotes ) ! Read the first two words in Line. IF ( Words(2) == '' .and. (LEN_TRIM(ExpVarName) > 0) ) THEN CALL SetErrStat ( ErrID_Fatal, 'A fatal error occurred when parsing data from "' & //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & From f77571df724e24c505ba2f5d3dd27444f129451f Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 12 Dec 2024 16:47:19 +0000 Subject: [PATCH 24/31] Add IsPath=.true. where ParseVar is used to parse a file path --- modules/aerodyn/src/AeroDyn_Driver_Subs.f90 | 4 ++-- modules/aerodyn/src/AeroDyn_IO.f90 | 6 +++--- modules/aerodyn/src/AirfoilInfo.f90 | 2 +- modules/hydrodyn/src/HydroDyn_Input.f90 | 2 +- modules/inflowwind/src/InflowWind_Subs.f90 | 12 ++++++------ modules/servodyn/src/ServoDyn_IO.f90 | 6 +++--- modules/servodyn/src/StrucCtrl.f90 | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 index 8227a8252a..a43ae3356a 100644 --- a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 @@ -958,7 +958,7 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) call ParseVar(FileInfo_In, CurLine, "analysisType", dvr%analysisType, errStat2, errMsg2, unEc); if (Failed()) return call ParseVar(FileInfo_In, CurLine, "tMax" , dvr%tMax , errStat2, errMsg2, unEc); if (Failed()) return call ParseVar(FileInfo_In, CurLine, "dt" , dvr%dt , errStat2, errMsg2, unEc); if (Failed()) return - call ParseVar(FileInfo_In, CurLine, "AeroFile" , dvr%AD_InputFile, errStat2, errMsg2, unEc); if (Failed()) return + call ParseVar(FileInfo_In, CurLine, "AeroFile" , dvr%AD_InputFile, errStat2, errMsg2, unEc, IsPath=.true.); if (Failed()) return ! --- Environmental conditions call ParseCom(FileInfo_In, CurLine, Line, errStat2, errMsg2, unEc); if (Failed()) return @@ -973,7 +973,7 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) ! --- Inflow data call ParseCom(FileInfo_In, CurLine, Line, errStat2, errMsg2, unEc); if (Failed()) return call ParseVar(FileInfo_In, CurLine, "compInflow", dvr%IW_InitInp%compInflow , errStat2, errMsg2, unEc); if (Failed()) return - call ParseVar(FileInfo_In, CurLine, "InflowFile", dvr%IW_InitInp%InputFile, errStat2, errMsg2, unEc); if (Failed()) return + call ParseVar(FileInfo_In, CurLine, "InflowFile", dvr%IW_InitInp%InputFile, errStat2, errMsg2, unEc, IsPath=.true.); if (Failed()) return if (dvr%IW_InitInp%compInflow==0) then call ParseVar(FileInfo_In, CurLine, "HWindSpeed", dvr%IW_InitInp%HWindSpeed , errStat2, errMsg2, unEc); if (Failed()) return call ParseVar(FileInfo_In, CurLine, "RefHt" , dvr%IW_InitInp%RefHt , errStat2, errMsg2, unEc); if (Failed()) return diff --git a/modules/aerodyn/src/AeroDyn_IO.f90 b/modules/aerodyn/src/AeroDyn_IO.f90 index 24e56b0ab2..815e147458 100644 --- a/modules/aerodyn/src/AeroDyn_IO.f90 +++ b/modules/aerodyn/src/AeroDyn_IO.f90 @@ -730,7 +730,7 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade call ParseVar( FileInfo_In, CurLine, "CompAA", InputFileData%CompAA, ErrStat2, ErrMsg2, UnEc ) if (Failed()) return ! AA_InputFile - Aeroacoustics input file - call ParseVar( FileInfo_In, CurLine, "AA_InputFile", InputFileData%AA_InputFile, ErrStat2, ErrMsg2, UnEc ) + call ParseVar( FileInfo_In, CurLine, "AA_InputFile", InputFileData%AA_InputFile, ErrStat2, ErrMsg2, UnEc, IsPath=.true. ) if (Failed()) return IF ( PathIsRelative( InputFileData%AA_InputFile ) ) InputFileData%AA_InputFile = TRIM(PriPath)//TRIM(InputFileData%AA_InputFile) @@ -802,7 +802,7 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo CurLine = CurLine + 1 ! OLAFInputFileName - Input file for OLAF [used only when WakeMod=3] - call ParseVar( FileInfo_In, CurLine, "OLAFInputFileName", InputFileData%FVWFileName, ErrStat2, ErrMsg2, UnEc ) + call ParseVar( FileInfo_In, CurLine, "OLAFInputFileName", InputFileData%FVWFileName, ErrStat2, ErrMsg2, UnEc, IsPath=.true. ) if (Failed()) return IF ( PathIsRelative( InputFileData%FVWFileName ) ) InputFileData%FVWFileName = TRIM(PriPath)//TRIM(InputFileData%FVWFileName) @@ -906,7 +906,7 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade ! NOTE: being nice with legacy input file. Uncomment in next release call ParseVar(FileInfo_In, CurLine, "TFinAero", InputFileData%rotors(iR)%TFinAero, ErrStat2, ErrMsg2, UnEc); if (ErrStat2==ErrID_None) then - call ParseVar(FileInfo_In, CurLine, "TFinFile", InputFileData%rotors(iR)%TFinFile, ErrStat2, ErrMsg2, UnEc); if (Failed()) return + call ParseVar(FileInfo_In, CurLine, "TFinFile", InputFileData%rotors(iR)%TFinFile, ErrStat2, ErrMsg2, UnEc, IsPath=.true.); if (Failed()) return InputFileData%rotors(iR)%TFinFile = trim(PriPath) // trim(InputFileData%rotors(iR)%TFinFile) else call LegacyWarning('Tail Fin section (TFinAero, TFinFile) is missing from input file.') diff --git a/modules/aerodyn/src/AirfoilInfo.f90 b/modules/aerodyn/src/AirfoilInfo.f90 index 477d46ca50..7d3d0742e7 100644 --- a/modules/aerodyn/src/AirfoilInfo.f90 +++ b/modules/aerodyn/src/AirfoilInfo.f90 @@ -479,7 +479,7 @@ SUBROUTINE ReadAFfile ( InitInp, NumCoefsIn, p, ErrStat, ErrMsg, UnEc ) ENDIF ! Reading Boundary layer file for aeroacoustics - CALL ParseVar ( FileInfo, CurLine, 'BL_file' , p%BL_file , ErrStat2, ErrMsg2, UnEc ) + CALL ParseVar ( FileInfo, CurLine, 'BL_file' , p%BL_file , ErrStat2, ErrMsg2, UnEc, IsPath=.true. ) IF (ErrStat2 >= AbortErrLev) p%BL_file = "NOT_SET_IN_AIRFOIL_FILE" !CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( PathIsRelative( p%BL_file ) ) p%BL_file=trim(PriPath)//trim(p%BL_file) diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index a9fe940189..8c5cd4dab5 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -359,7 +359,7 @@ SUBROUTINE HydroDyn_ParseInput( InputFileName, OutRootName, defWtrDens, defWtrDp if (Failed()) return; ! WvKinFile - call ParseVar( FileInfo_In, CurLine, 'WvKinFile', InputFileData%Waves%WvKinFile, ErrStat2, ErrMsg2, UnEc ) + call ParseVar( FileInfo_In, CurLine, 'WvKinFile', InputFileData%Waves%WvKinFile, ErrStat2, ErrMsg2, UnEc, IsPath=.true. ) if (Failed()) return; ! NWaveElev diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index c8349ffbd3..4f4169a1fc 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -317,7 +317,7 @@ SUBROUTINE InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, In !------------------------------------------------------------------------------------------------- CurLine = CurLine + 1 ! Skip section break - CALL ParseVar( InFileInfo, CurLine, "FileName_Uni", InputFileData%Uniform_FileName, TmpErrStat, TmpErrMsg, UnEc ) + CALL ParseVar( InFileInfo, CurLine, "FileName_Uni", InputFileData%Uniform_FileName, TmpErrStat, TmpErrMsg, UnEc, IsPath=.true. ) if (Failed()) return IF ( PathIsRelative( InputFileData%Uniform_FileName ) ) InputFileData%Uniform_FileName = TRIM(PriPath)//TRIM(InputFileData%Uniform_FileName) IF ( FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data @@ -339,7 +339,7 @@ SUBROUTINE InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, In !------------------------------------------------------------------------------------------------- CurLine = CurLine + 1 ! Skip section break - CALL ParseVar( InFileInfo, CurLine, "FileName_BTS", InputFileData%TSFF_FileName, TmpErrStat, TmpErrMsg, UnEc ) + CALL ParseVar( InFileInfo, CurLine, "FileName_BTS", InputFileData%TSFF_FileName, TmpErrStat, TmpErrMsg, UnEc, IsPath=.true. ) if (Failed()) return IF ( PathIsRelative( InputFileData%TSFF_FileName ) ) InputFileData%TSFF_FileName = TRIM(PriPath)//TRIM(InputFileData%TSFF_FileName) IF ( FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data @@ -355,7 +355,7 @@ SUBROUTINE InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, In !------------------------------------------------------------------------------------------------- CurLine = CurLine + 1 ! Skip section break - CALL ParseVar( InFileInfo, CurLine, "FilenameRoot", InputFileData%BladedFF_FileName, TmpErrStat, TmpErrMsg, UnEc ) + CALL ParseVar( InFileInfo, CurLine, "FilenameRoot", InputFileData%BladedFF_FileName, TmpErrStat, TmpErrMsg, UnEc, IsPath=.true. ) if (Failed()) return IF ( PathIsRelative( InputFileData%BladedFF_FileName ) ) InputFileData%BladedFF_FileName = TRIM(PriPath)//TRIM(InputFileData%BladedFF_FileName) @@ -383,15 +383,15 @@ SUBROUTINE InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, In !------------------------------------------------------------------------------------------------- CurLine = CurLine + 1 ! Skip section break - CALL ParseVar( InFileInfo, CurLine, "FileName_u", InputFileData%HAWC_FileName_u, TmpErrStat, TmpErrMsg, UnEc ) + CALL ParseVar( InFileInfo, CurLine, "FileName_u", InputFileData%HAWC_FileName_u, TmpErrStat, TmpErrMsg, UnEc, IsPath=.true. ) if (Failed()) return IF ( PathIsRelative( InputFileData%HAWC_FileName_u ) ) InputFileData%HAWC_FileName_u = TRIM(PriPath)//TRIM(InputFileData%HAWC_FileName_u) - CALL ParseVar( InFileInfo, CurLine, "FileName_v", InputFileData%HAWC_FileName_v, TmpErrStat, TmpErrMsg, UnEc ) + CALL ParseVar( InFileInfo, CurLine, "FileName_v", InputFileData%HAWC_FileName_v, TmpErrStat, TmpErrMsg, UnEc, IsPath=.true. ) if (Failed()) return IF ( PathIsRelative( InputFileData%HAWC_FileName_v ) ) InputFileData%HAWC_FileName_v = TRIM(PriPath)//TRIM(InputFileData%HAWC_FileName_v) - CALL ParseVar( InFileInfo, CurLine, "FileName_w", InputFileData%HAWC_FileName_w, TmpErrStat, TmpErrMsg, UnEc ) + CALL ParseVar( InFileInfo, CurLine, "FileName_w", InputFileData%HAWC_FileName_w, TmpErrStat, TmpErrMsg, UnEc, IsPath=.true. ) if (Failed()) return IF ( PathIsRelative( InputFileData%HAWC_FileName_w ) ) InputFileData%HAWC_FileName_w = TRIM(PriPath)//TRIM(InputFileData%HAWC_FileName_w) diff --git a/modules/servodyn/src/ServoDyn_IO.f90 b/modules/servodyn/src/ServoDyn_IO.f90 index cb900579ec..1cbee9c9ef 100644 --- a/modules/servodyn/src/ServoDyn_IO.f90 +++ b/modules/servodyn/src/ServoDyn_IO.f90 @@ -1332,15 +1332,15 @@ subroutine ParseInputFileInfo( PriPath, InputFile, OutFileRoot, FileInfo_In, Inp if ( InputFileData%Echo ) WRITE(UnEcho, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo CurLine = CurLine + 1 ! DLL_FileName - Name/location of the dynamic library {.dll [Windows] or .so [Linux]} in the Bladed-DLL format (-) [used only with Bladed Interface] - call ParseVar( FileInfo_In, CurLine, 'DLL_FileName', InputFileData%DLL_FileName, ErrStat2, ErrMsg2, UnEcho ) + call ParseVar( FileInfo_In, CurLine, 'DLL_FileName', InputFileData%DLL_FileName, ErrStat2, ErrMsg2, UnEcho, IsPath=.true. ) if (Failed()) return; IF ( PathIsRelative( InputFileData%DLL_FileName ) ) InputFileData%DLL_FileName = TRIM(PriPath)//TRIM(InputFileData%DLL_FileName) ! DLL_InFile - Name of input file sent to the DLL (-) [used only with Bladed Interface] - call ParseVar( FileInfo_In, CurLine, 'DLL_InFile', InputFileData%DLL_InFile, ErrStat2, ErrMsg2, UnEcho ) + call ParseVar( FileInfo_In, CurLine, 'DLL_InFile', InputFileData%DLL_InFile, ErrStat2, ErrMsg2, UnEcho, IsPath=.true. ) if (Failed()) return; IF ( PathIsRelative( InputFileData%DLL_InFile ) ) InputFileData%DLL_InFile = TRIM(PriPath)//TRIM(InputFileData%DLL_InFile) ! DLL_ProcName - Name of procedure in DLL to be called (-) [case sensitive; used only with DLL Interface] - call ParseVar( FileInfo_In, CurLine, 'DLL_ProcName', InputFileData%DLL_ProcName, ErrStat2, ErrMsg2, UnEcho ) + call ParseVar( FileInfo_In, CurLine, 'DLL_ProcName', InputFileData%DLL_ProcName, ErrStat2, ErrMsg2, UnEcho, IsPath=.true. ) if (Failed()) return; ! DLL_DT - Communication interval for dynamic library (s) (or "default") [used only with Bladed Interface] call ParseVarWDefault( FileInfo_In, CurLine, 'DLL_DT', InputFileData%DLL_DT, InputFileData%DT, ErrStat2, ErrMsg2, UnEcho ) diff --git a/modules/servodyn/src/StrucCtrl.f90 b/modules/servodyn/src/StrucCtrl.f90 index 60c9efd530..0c0cea0da6 100644 --- a/modules/servodyn/src/StrucCtrl.f90 +++ b/modules/servodyn/src/StrucCtrl.f90 @@ -2115,7 +2115,7 @@ SUBROUTINE StC_ParseInputFileInfo( PriPath, InputFile, RootName, NumMeshPts, Fil call ParseVar( FileInfo_In, Curline, 'PrescribedForcesCoordSys', InputFileData%PrescribedForcesCoordSys, ErrStat2, ErrMsg2 ) If (Failed()) return; ! Prescribed input time series - call ParseVar( FileInfo_In, Curline, 'PrescribedForcesFile', InputFileData%PrescribedForcesFile, ErrStat2, ErrMsg2 ) + call ParseVar( FileInfo_In, Curline, 'PrescribedForcesFile', InputFileData%PrescribedForcesFile, ErrStat2, ErrMsg2, IsPath=.true. ) if (Failed()) return; if ( PathIsRelative( InputFileData%PrescribedForcesFile ) ) InputFileData%PrescribedForcesFile = TRIM(PriPath)//TRIM(InputFileData%PrescribedForcesFile) From fce5c223ae0d01a4eed18ecb90f0a9aa92a0dc89 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 12 Dec 2024 21:47:52 +0000 Subject: [PATCH 25/31] Allow , and ; in quoted words --- modules/nwtc-library/src/NWTC_IO.f90 | 29 +++++++++------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index 602fad45da..b69b375d2b 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -2079,6 +2079,9 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound, IgnoreQuotes ) LOGICAL :: InQuotes ! Flag indicating text is within quotes LOGICAL :: IgnoreQuotesLoc ! Local flag to ignore quotes + ! Initialize number of words found to zero if present + if (present(NumFound)) NumFound = 0 + ! If no text on line, return if (len_trim(Line) == 0) return @@ -2089,17 +2092,11 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound, IgnoreQuotes ) IgnoreQuotesLoc = .true. end if - ! Let's prefill the array with blanks. + ! Let's prefill the array with blanks do iWord = 1, NumWords Words(iWord) = ' ' end do - ! Initialize number of words found to zero if present - if (present(NumFound)) NumFound = 0 - - ! If no text on line, return - if (len_trim(Line) == 0) return - ! Initialize word index to first word iWord = 1 @@ -2121,7 +2118,7 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound, IgnoreQuotes ) if (IgnoreQuotesLoc .or. InQuotes) then InQuotes = .false. if (iChar > 0) then - ! If requested number of words found, exit + ! If requested number of words found, exit; otherwise, new word if (iWord == NumWords) exit iWord = iWord + 1 iChar = 0 @@ -2131,11 +2128,12 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound, IgnoreQuotes ) end if cycle - case (' ', Tab) ! Whitespace - ! If between quotes, keep whitespace; otherwise separate words + ! Word separator + case (',', ';', ' ', Tab) ! Comma, semicolon, space, tab + ! If in quotes, keep these in word if (.not. InQuotes) then if (iChar > 0) then - ! If requested number of words found, exit + ! If requested number of words found, exit; otherwise, new word if (iWord == NumWords) exit iWord = iWord + 1 iChar = 0 @@ -2143,15 +2141,6 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound, IgnoreQuotes ) cycle end if - case (',', ';') ! Comma, semicolon - ! Always separate words on these characters - if (iChar > 0) then - ! If requested number of words found, exit - if (iWord == NumWords) exit - iWord = iWord + 1 - iChar = 0 - end if - cycle end select ! Increment character index From a62d8772ee378d1ebb44a8f8c3d5beae9e8293d6 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Mon, 16 Dec 2024 17:57:17 +0000 Subject: [PATCH 26/31] Use INTENT(IN) for IgnoreQuotes in GetWords (NWTC_IO) --- modules/nwtc-library/src/NWTC_IO.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index b69b375d2b..25565afe9b 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -2070,7 +2070,7 @@ SUBROUTINE GetWords ( Line, Words, NumWords, NumFound, IgnoreQuotes ) CHARACTER(*), INTENT(IN) :: Line !< The string to search. CHARACTER(*), INTENT(OUT) :: Words(NumWords) !< The array of found words. INTEGER, OPTIONAL, INTENT(OUT) :: NumFound !< The number of words found - LOGICAL, OPTIONAL, INTENT(OUT) :: IgnoreQuotes !< Flag to ignore quotes (process as whitespace) + LOGICAL, OPTIONAL, INTENT(IN) :: IgnoreQuotes !< Flag to ignore quotes (process as whitespace) INTEGER :: iWord ! Word index. INTEGER :: i ! Character index in line. From 0e99c524043c8dfedc5200a025811d4513364acf Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 17 Dec 2024 15:12:41 +0000 Subject: [PATCH 27/31] Change openfast_cpp_driver to openfast_lib_driver to better separate openfast-cpp from the OpenFAST library C++ driver --- .github/workflows/automated-dev-tests.yml | 2 +- glue-codes/openfast/CMakeLists.txt | 6 +++--- reg_tests/CMakeLists.txt | 2 +- reg_tests/CTestList.cmake | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/automated-dev-tests.yml b/.github/workflows/automated-dev-tests.yml index 92402268bf..9028693e2a 100644 --- a/.github/workflows/automated-dev-tests.yml +++ b/.github/workflows/automated-dev-tests.yml @@ -243,7 +243,7 @@ jobs: - name: Build OpenFAST C-Interfaces working-directory: ${{runner.workspace}}/openfast/build run: | - cmake --build . --target openfastlib openfast_cpp_driver openfastcpp aerodyn_inflow_c_binding moordyn_c_binding ifw_c_binding hydrodyn_c_binding regression_test_controllers + cmake --build . --target openfastlib openfast_lib_driver openfastcpp aerodyn_inflow_c_binding moordyn_c_binding ifw_c_binding hydrodyn_c_binding regression_test_controllers - name: Cache the workspace uses: actions/cache@v4 with: diff --git a/glue-codes/openfast/CMakeLists.txt b/glue-codes/openfast/CMakeLists.txt index 402a790f69..a742b5972a 100644 --- a/glue-codes/openfast/CMakeLists.txt +++ b/glue-codes/openfast/CMakeLists.txt @@ -34,10 +34,10 @@ install(TARGETS openfast RUNTIME DESTINATION bin) if(BUILD_OPENFAST_LIB_DRIVER) - add_executable(openfast_cpp_driver src/FAST_Prog.cpp src/FastLibAPI.cpp) - target_link_libraries(openfast_cpp_driver openfastlib) + add_executable(openfast_lib_driver src/FAST_Prog.cpp src/FastLibAPI.cpp) + target_link_libraries(openfast_lib_driver openfastlib) - install(TARGETS openfast_cpp_driver + install(TARGETS openfast_lib_driver RUNTIME DESTINATION bin) endif() diff --git a/reg_tests/CMakeLists.txt b/reg_tests/CMakeLists.txt index 268e188f9d..70cbf67176 100644 --- a/reg_tests/CMakeLists.txt +++ b/reg_tests/CMakeLists.txt @@ -42,7 +42,7 @@ option(CTEST_NO_RUN_FLAG "Complete the regression test comparison but do not ex # Set the OpenFAST executable configuration option and default set(CTEST_OPENFAST_EXECUTABLE "${CMAKE_BINARY_DIR}/glue-codes/openfast/openfast${CMAKE_EXECUTABLE_SUFFIX}" CACHE FILEPATH "Specify the OpenFAST executable to use in testing.") -if(BUILD_OPENFAST_CPP_API) +if(BUILD_OPENFAST_CPP_DRIVER) # Set the OpenFAST executable configuration option and default set(CTEST_OPENFASTCPP_EXECUTABLE "${CMAKE_BINARY_DIR}/glue-codes/openfast-cpp/openfastcpp${CMAKE_EXECUTABLE_SUFFIX}" CACHE FILEPATH "Specify the OpenFAST C++ executable to use in testing.") endif() diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake index b9c6dbf882..163fa4f35f 100644 --- a/reg_tests/CTestList.cmake +++ b/reg_tests/CTestList.cmake @@ -85,7 +85,7 @@ endfunction(of_regression) function(of_fastlib_regression TESTNAME LABEL) set(TEST_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/executeOpenfastRegressionCase.py") - set(OPENFAST_EXECUTABLE "${CMAKE_BINARY_DIR}/glue-codes/openfast/openfast_cpp_driver") + set(OPENFAST_EXECUTABLE "${CMAKE_BINARY_DIR}/glue-codes/openfast/openfast_lib_driver") set(SOURCE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/..") set(BUILD_DIRECTORY "${CTEST_BINARY_DIR}/glue-codes/openfast") regression(${TEST_SCRIPT} ${OPENFAST_EXECUTABLE} ${SOURCE_DIRECTORY} ${BUILD_DIRECTORY} "${TESTNAME}_fastlib" "${LABEL}" ${TESTNAME}) @@ -285,15 +285,15 @@ of_regression("MHK_RM1_Floating" "openfast;elastodyn;aerod of_regression("Tailfin_FreeYaw1DOF_PolarBased" "openfast;elastodyn;aerodyn15") # OpenFAST C++ API test -if(BUILD_OPENFAST_CFD_DRIVER) +if(BUILD_OPENFAST_CPP_DRIVER) of_cpp_interface_regression("5MW_Land_DLL_WTurb_cpp" "openfast;fastlib;cpp") endif() -# OpenFAST C++ Driver test for OpenFAST Library +# OpenFAST Driver test for OpenFAST C++ Library # This tests the FAST Library and FAST_Library.h -if(BUILD_OPENFAST_CPP_DRIVER) +if(BUILD_OPENFAST_LIB_DRIVER) of_fastlib_regression("AWT_YFree_WSt" "fastlib;elastodyn;aerodyn15;servodyn") -endif(BUILD_OPENFAST_CPP_DRIVER) +endif() # OpenFAST Python API test of_regression_py("5MW_Land_DLL_WTurb_py" "openfast;fastlib;python;elastodyn;aerodyn15;servodyn") From 8193c7a732aa9af48d57449b88618d04d0c19fef Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 18 Dec 2024 14:48:49 -0700 Subject: [PATCH 28/31] Disable LiDAR in IfW at FAST.Farm level --- modules/inflowwind/src/InflowWind.f90 | 11 ++++++++++- modules/inflowwind/src/InflowWind.txt | 1 + modules/inflowwind/src/InflowWind_Types.f90 | 7 +++++++ modules/openfast-library/src/FAST_Subs.f90 | 1 + 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 103ddb948b..9c0c0276f6 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -224,7 +224,16 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons p%lidar%PulseSpacing = InputFileData%PulseSpacing p%lidar%URefLid = InputFileData%URefLid p%lidar%ConsiderHubMotion = InputFileData%ConsiderHubMotion - + + ! Disable Lidar if not allowed (FAST.Farm doesn't allow this) + if (InitInp%LidarDisable) then + if (p%lidar%SensorType /= SensorType_None) then + call WrScr(' WARNING: LiDAR cannot be used with this instance of InflowWind (not usable with FAST.Farm).') + call WrScr(' --> Disabling LiDAR.') + p%lidar%SensorType = SensorType_None + end if + endif + CALL Lidar_Init( InitInp, InputGuess, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & y, m, TimeInterval, InitOutData, TmpErrStat, TmpErrMsg ) diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 3ab0940982..5fbe8e6c0e 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -101,6 +101,7 @@ typedef ^ ^ ReKi WtrDpth typedef ^ ^ ReKi MSL2SWL - - - "Mean sea level to still water level" m typedef ^ ^ IntKi BoxExceedAllowIdx - -1 - "Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim)" - typedef ^ ^ LOGICAL BoxExceedAllowF - .FALSE. - "Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim)" - +typedef ^ ^ LOGICAL LidarDisable - .true. - "Disable LiDAR for this instance of InflowWind? (FAST.Farm not compatible)" - # Init Output diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index 605bfe2228..8ac1bfc93f 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -119,6 +119,7 @@ MODULE InflowWind_Types REAL(ReKi) :: MSL2SWL !< Mean sea level to still water level [m] INTEGER(IntKi) :: BoxExceedAllowIdx = -1 !< Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim) [-] LOGICAL :: BoxExceedAllowF = .FALSE. !< Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim) [-] + LOGICAL :: LidarDisable = .true. !< Disable LiDAR for this instance of InflowWind? (FAST.Farm not compatible) [-] END TYPE InflowWind_InitInputType ! ======================= ! ========= InflowWind_InitOutputType ======= @@ -1110,6 +1111,7 @@ SUBROUTINE InflowWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCod DstInitInputData%MSL2SWL = SrcInitInputData%MSL2SWL DstInitInputData%BoxExceedAllowIdx = SrcInitInputData%BoxExceedAllowIdx DstInitInputData%BoxExceedAllowF = SrcInitInputData%BoxExceedAllowF + DstInitInputData%LidarDisable = SrcInitInputData%LidarDisable END SUBROUTINE InflowWind_CopyInitInput SUBROUTINE InflowWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -1263,6 +1265,7 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Re_BufSz = Re_BufSz + 1 ! MSL2SWL Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowIdx Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowF + Int_BufSz = Int_BufSz + 1 ! LidarDisable IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1438,6 +1441,8 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedAllowF, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%LidarDisable, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_PackInitInput SUBROUTINE InflowWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1662,6 +1667,8 @@ SUBROUTINE InflowWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS Int_Xferred = Int_Xferred + 1 OutData%BoxExceedAllowF = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedAllowF) Int_Xferred = Int_Xferred + 1 + OutData%LidarDisable = TRANSFER(IntKiBuf(Int_Xferred), OutData%LidarDisable) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_UnPackInitInput SUBROUTINE InflowWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 9e0af8c935..09f532a022 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -583,6 +583,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, END IF ! lidar + Init%InData_IfW%LidarDisable = .false. ! allowed with OF, but not FF Init%InData_IfW%lidar%Tmax = p_FAST%TMax Init%InData_IfW%lidar%HubPosition = ED%y%HubPtMotion%Position(:,1) From 5c30c4233999af01b46bca7f88296efda271c954 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 18 Dec 2024 15:45:40 -0700 Subject: [PATCH 29/31] Update release notes and changelog for 3.5.5 --- docs/changelogs/v3.5.5.md | 105 ++++++++++++++++++++++++++++++++ docs/conf.py | 2 +- docs/source/user/api_change.rst | 6 ++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 docs/changelogs/v3.5.5.md diff --git a/docs/changelogs/v3.5.5.md b/docs/changelogs/v3.5.5.md new file mode 100644 index 0000000000..8043f3a3bd --- /dev/null +++ b/docs/changelogs/v3.5.5.md @@ -0,0 +1,105 @@ +**Feature or improvement description** +Pull request to merge `rc-3.5.5` into `main` and create a tagged release for v3.5.5. + +See the milestone and project pages for additional information + + https://github.com/OpenFAST/openfast/milestone/15 + +Test results, if applicable +See GitHub Actions + +### Release checklist: +- [ ] Update the documentation version in docs/conf.py +- [ ] Update the versions in docs/source/user/api_change.rst +- [ ] Verify readthedocs builds correctly +- [ ] Create a tag in OpenFAST +- [ ] Create a merge commit in r-test and add a corresponding annotated tag +- [ ] Compile executables for Windows builds + - [ ] AeroDyn_Driver_x64.exe + - [ ] AeroDyn_Driver_x64_OpenMP.exe + - [ ] AeroDyn_Inflow_C_Binding_x64.dll + - [ ] AeroDyn_Inflow_C_Binding_x64_OpenMP.dll + - [ ] BeamDyn_Driver_x64.exe + - [ ] DISCON.dll (x64) + - [ ] DISCON_ITIBarge.dll (x64) + - [ ] DISCON_OC3Hywind.dll (x64) + - [ ] DISCON_SC.dll (x64) + - [ ] FAST.Farm_x64.exe + - [ ] FAST.Farm_x64_OMP.exe + - [ ] FAST_SFunc.mexw64 + - [ ] HydroDynDriver_x64.exe + - [ ] HydroDyn_C_Binding_x64.dll + - [ ] IfW_C_Binding_x64.dll + - [ ] InflowWind_Driver_x64.exe + - [ ] InflowWind_Driver_x64_OpenMP.exe + - [ ] MoorDyn_Driver_x64.exe + - [ ] MoorDyn_C_Binding_x64.dll + - [ ] OpenFAST-Simulink_x64.dll + - [ ] openfast_x64.exe + - [ ] Turbsim_x64.exe + +# Changelog + +## Overview + +This release includes performance + + + +## General + +### Build systems + +#2497 `CMAKE_INSTALL_PREFIX` was incorrectly being prepended to the install direcotry (@deslaughter) Derek Slaughter + +#2564 Create `BUILD_OPENFAST_LIB_DRIVER` flag for the OpenFAST C++ Library Interface (not CFD) (@deslaughter) + + +### Docker + +#2498 Docker: typo was preventing docker build upload to GH (@andrew-platt) + + + +## Solvers + +### FAST.Farm + +#2536 FAST.Farm: increase number of output planes to 999 (@andrew-platt) + +#2554 Add `!$OMP critical` directives around some `GetNewUnit/Open*File` to reduce probability of file unit conflicts (@andrew-platt) + +#2569 Disable LiDAR in IfW at FAST.Farm level (@andrew-platt) + + +## Module changes + +### AeroDyn + +#2501 Remove `$OMP` directives from `AeroDyn_Inflow` due to Intel compiler bug (@deslaughter) + +#2516 AD bugfix: Segmentation fault with ifx compiler (@andrew-platt) + + +### InflowWind + +#2518, #2530 ADI bugfix: BoxExceed was not enabled for OLAF with ADI (@andrew-platt) + +#2532 bugfix: IfW rotor points for disk average incorrect (@andrew-platt) + + +### NWTC-Library + +#2558 Allow ParseVar to parse file paths containing spaces. (@deslaughter) + + + + +## Input file changes + +No input files change with this release as this only includes minor bugfixes (input files are identical across all 3.5.x releases). + +Full list of changes: https://openfast.readthedocs.io/en/main/source/user/api_change.html + +Full input file sets: https://github.com/OpenFAST/r-test/tree/v3.5.5 (example input files from the regression testing) + diff --git a/docs/conf.py b/docs/conf.py index f1b3d9f221..a1ce010114 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -130,7 +130,7 @@ def runDoxygen(sourcfile, doxyfileIn, doxyfileOut): # The short X.Y version. version = u'3.5' # The full version, including alpha/beta/rc tags. -release = u'v3.5.4' +release = u'v3.5.5' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index cf16f2fe4c..242ab07a03 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -9,6 +9,12 @@ The changes are tabulated according to the module input file, line number, and f The line number corresponds to the resulting line number after all changes are implemented. Thus, be sure to implement each in order so that subsequent line numbers are correct. +OpenFAST v3.5.4 to OpenFAST v3.5.5 +---------------------------------- + +No input file changes were made. + + OpenFAST v3.5.3 to OpenFAST v3.5.4 ---------------------------------- From a8fe70e498f7827bc6fdda4c8e34247427ddb08b Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 19 Dec 2024 09:40:06 -0700 Subject: [PATCH 30/31] IfW: change logic flag for LidarEnabled --- modules/inflowwind/src/InflowWind.f90 | 2 +- modules/inflowwind/src/InflowWind.txt | 2 +- modules/inflowwind/src/InflowWind_Types.f90 | 10 +++++----- modules/openfast-library/src/FAST_Subs.f90 | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 9c0c0276f6..a0ddc5e713 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -226,7 +226,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons p%lidar%ConsiderHubMotion = InputFileData%ConsiderHubMotion ! Disable Lidar if not allowed (FAST.Farm doesn't allow this) - if (InitInp%LidarDisable) then + if (.not. InitInp%LidarEnabled) then if (p%lidar%SensorType /= SensorType_None) then call WrScr(' WARNING: LiDAR cannot be used with this instance of InflowWind (not usable with FAST.Farm).') call WrScr(' --> Disabling LiDAR.') diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 5fbe8e6c0e..c4ea6c56e3 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -101,7 +101,7 @@ typedef ^ ^ ReKi WtrDpth typedef ^ ^ ReKi MSL2SWL - - - "Mean sea level to still water level" m typedef ^ ^ IntKi BoxExceedAllowIdx - -1 - "Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim)" - typedef ^ ^ LOGICAL BoxExceedAllowF - .FALSE. - "Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim)" - -typedef ^ ^ LOGICAL LidarDisable - .true. - "Disable LiDAR for this instance of InflowWind? (FAST.Farm not compatible)" - +typedef ^ ^ LOGICAL LidarEnabled - .false. - "Enable LiDAR for this instance of InflowWind? (FAST.Farm, ADI, and InflowWind driver/library are not compatible)" - # Init Output diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index 8ac1bfc93f..a4384becf7 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -119,7 +119,7 @@ MODULE InflowWind_Types REAL(ReKi) :: MSL2SWL !< Mean sea level to still water level [m] INTEGER(IntKi) :: BoxExceedAllowIdx = -1 !< Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim) [-] LOGICAL :: BoxExceedAllowF = .FALSE. !< Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim) [-] - LOGICAL :: LidarDisable = .true. !< Disable LiDAR for this instance of InflowWind? (FAST.Farm not compatible) [-] + LOGICAL :: LidarEnabled = .false. !< Enable LiDAR for this instance of InflowWind? (FAST.Farm, ADI, and InflowWind driver/library are not compatible) [-] END TYPE InflowWind_InitInputType ! ======================= ! ========= InflowWind_InitOutputType ======= @@ -1111,7 +1111,7 @@ SUBROUTINE InflowWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCod DstInitInputData%MSL2SWL = SrcInitInputData%MSL2SWL DstInitInputData%BoxExceedAllowIdx = SrcInitInputData%BoxExceedAllowIdx DstInitInputData%BoxExceedAllowF = SrcInitInputData%BoxExceedAllowF - DstInitInputData%LidarDisable = SrcInitInputData%LidarDisable + DstInitInputData%LidarEnabled = SrcInitInputData%LidarEnabled END SUBROUTINE InflowWind_CopyInitInput SUBROUTINE InflowWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -1265,7 +1265,7 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Re_BufSz = Re_BufSz + 1 ! MSL2SWL Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowIdx Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowF - Int_BufSz = Int_BufSz + 1 ! LidarDisable + Int_BufSz = Int_BufSz + 1 ! LidarEnabled IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1441,7 +1441,7 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedAllowF, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%LidarDisable, IntKiBuf(1)) + IntKiBuf(Int_Xferred) = TRANSFER(InData%LidarEnabled, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_PackInitInput @@ -1667,7 +1667,7 @@ SUBROUTINE InflowWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS Int_Xferred = Int_Xferred + 1 OutData%BoxExceedAllowF = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedAllowF) Int_Xferred = Int_Xferred + 1 - OutData%LidarDisable = TRANSFER(IntKiBuf(Int_Xferred), OutData%LidarDisable) + OutData%LidarEnabled = TRANSFER(IntKiBuf(Int_Xferred), OutData%LidarEnabled) Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_UnPackInitInput diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 09f532a022..7aec9c44f6 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -583,7 +583,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, END IF ! lidar - Init%InData_IfW%LidarDisable = .false. ! allowed with OF, but not FF + Init%InData_IfW%LidarEnabled = .true. ! allowed with OF, but not FF Init%InData_IfW%lidar%Tmax = p_FAST%TMax Init%InData_IfW%lidar%HubPosition = ED%y%HubPtMotion%Position(:,1) From 0b4a550e2e6b1b23f7e0ac58afd7772622c3e22e Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Thu, 19 Dec 2024 11:55:29 -0700 Subject: [PATCH 31/31] Update v3.5.5.md with summary --- docs/changelogs/v3.5.5.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/changelogs/v3.5.5.md b/docs/changelogs/v3.5.5.md index 8043f3a3bd..0ac516dbc0 100644 --- a/docs/changelogs/v3.5.5.md +++ b/docs/changelogs/v3.5.5.md @@ -42,7 +42,9 @@ See GitHub Actions ## Overview -This release includes performance +This release includes multiple small bug-fixes for compilation with CMake, compilation with the IFX compilers, file opening issues when OpenMP is used, and a couple of infrequent segmentation faults from improper usage. One minor feature improvement is the increase in the number of output planes available in _FAST.Farm_ from 99 to 999. + +We recommend all users currently using any 3.5.x version to update to this version. There are no input files changes or API changes for calling from other codes since version 3.5.0.