From f80d45c3aaf9f3e06b02528eff34a9306f22ef08 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 22 Dec 2022 22:05:36 +0000 Subject: [PATCH 01/51] nwtc-library: adding FlowField module The FlowField module provides a generic way to represent Uniform, Full-Field, User, and External wind data. This module is part of the effort to provide Inflow data to AeroDyn and HydroDyn via pointers instead of calling InflowWind. --- modules/nwtc-library/CMakeLists.txt | 6 + modules/nwtc-library/src/FlowField.f90 | 863 ++++++ modules/nwtc-library/src/FlowField.txt | 90 + modules/nwtc-library/src/FlowField_Types.f90 | 2510 ++++++++++++++++++ modules/nwtc-library/src/NWTC_Library.f90 | 1 + 5 files changed, 3470 insertions(+) create mode 100644 modules/nwtc-library/src/FlowField.f90 create mode 100644 modules/nwtc-library/src/FlowField.txt create mode 100644 modules/nwtc-library/src/FlowField_Types.f90 diff --git a/modules/nwtc-library/CMakeLists.txt b/modules/nwtc-library/CMakeLists.txt index 4078fbe223..33dd8e2d9a 100644 --- a/modules/nwtc-library/CMakeLists.txt +++ b/modules/nwtc-library/CMakeLists.txt @@ -14,11 +14,17 @@ # limitations under the License. # +if (GENERATE_TYPES) + generate_f90_types(src/FlowField.txt ${CMAKE_CURRENT_LIST_DIR}/src/FlowField_Types.f90 -noextrap) +endif() + set(NWTCLIBS_SOURCES src/JSON.f90 src/ModMesh.f90 src/ModMesh_Mapping.f90 src/ModMesh_Types.f90 + src/FlowField.f90 + src/FlowField_Types.f90 src/NWTC_Base.f90 src/NWTC_IO.f90 src/NWTC_Library.f90 diff --git a/modules/nwtc-library/src/FlowField.f90 b/modules/nwtc-library/src/FlowField.f90 new file mode 100644 index 0000000000..d295f5a99e --- /dev/null +++ b/modules/nwtc-library/src/FlowField.f90 @@ -0,0 +1,863 @@ +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2022 National Renewable Energy Laboratory +! +! This file is part of the NWTC Subroutine Library. +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +!********************************************************************************************************************************** + +module FlowField + +use NWTC_Library +use FlowField_Types + +implicit none + +public FlowField_GetVelAcc + +integer(IntKi), parameter :: WindProfileType_None = -1 !< don't add wind profile; already included in input +integer(IntKi), parameter :: WindProfileType_Constant = 0 !< constant wind +integer(IntKi), parameter :: WindProfileType_Log = 1 !< logarithmic +integer(IntKi), parameter :: WindProfileType_PL = 2 !< power law + +integer(IntKi), parameter :: ScaleMethod_None = 0 !< no scaling +integer(IntKi), parameter :: ScaleMethod_Direct = 1 !< direct scaling factors +integer(IntKi), parameter :: ScaleMethod_StdDev = 2 !< requested standard deviation + +real(ReKi), parameter :: GridTol = 1.0E-3 ! Tolerance for determining if position is within grid + +contains + +!> FlowField_GetVelAcc gets the velocities (and accelerations) at the given point positions. +!! Accelerations are only calculated if the AccelUVW array is allocated. +subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, AccelUVW, ErrStat, ErrMsg) + type(FlowFieldType), intent(in) :: FF !< FlowField data structure + integer(IntKi), intent(in) :: IStart !< Start index for returning velocities for external field + real(DbKi), intent(in) :: Time !< Time to evaluate velocities/accelerations + real(ReKi), dimension(:, :), intent(in) :: PositionXYZ !< Array of positions to evaluate velocites/accelerations + real(ReKi), dimension(:, :), intent(inout) :: VelocityUVW !< Array of velocity outputs + real(ReKi), dimension(:, :), allocatable, intent(inout) :: AccelUVW !< Array of acceleration outputs + integer(IntKi), intent(out) :: ErrStat !< Error status + character(*), intent(out) :: ErrMsg !< Error message + + character(*), parameter :: RoutineName = "FlowField_GetVelAcc" + integer(IntKi) :: i + integer(IntKi) :: NumPoints + real(ReKi), dimension(3) :: PositionPrime + type(UniformField_Interp) :: UFop + type(UniformField_Interp) :: UFopdt + real(ReKi) :: DY, DZ, DT + real(ReKi), dimension(3, 8) :: P + logical :: Interp3D + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + + ErrStat = ErrID_None + ErrMsg = "" + + ! Get number of points to evaluate + NumPoints = size(PositionXYZ, dim=2) + + !TODO: Check that position, velocity, and acceleration are all the same shape + + + !---------------------------------------------------------------------------- + ! Wind speed coordinate transforms from Wind file coordinates to global + !---------------------------------------------------------------------------- + + ! The VelocityUVW array data that has been returned from the sub-modules is + ! in the wind file (X'Y'Z') coordinates. These must be rotated to the global + ! XYZ coordinates if PropagationDir or UpflowAngle is nonzero. Apply the + ! coordinate transformation to the VelocityUVW(prime) coordinates + ! (in wind X'Y'Z' coordinate frame) returned from the submodules to the XYZ + ! coordinate frame, if PropagationDir is not zero. This is only a rotation + ! of the returned wind field, so UVW contains the direction components of + ! the wind at XYZ after translation from the U'V'W' wind velocity components + ! in the X'Y'Z' (wind file) coordinate frame. + ! NOTE: rotations are about the hub at [ 0 0 H ]. + + ! Switch based on flow type + select case (FF%FieldType) + case (Uniform_FieldType) + + !------------------------------------------------------------------------- + ! Uniform Flow Field + !------------------------------------------------------------------------- + + ! Get uniform flow operating point values at current time + UFop = UniformField_GetOP(FF%Uniform, Time) + + ! If getting accel, get change in operating point values wrt time + if (allocated(AccelUVW)) then + UFopdt%VelH = (FF%Uniform%VelH(Ufop%IData) - FF%Uniform%VelH(Ufop%IData - 1))/Ufop%dt + UFopdt%AngleH = (FF%Uniform%AngleH(Ufop%IData) - FF%Uniform%AngleH(Ufop%IData - 1))/Ufop%dt + UFopdt%AngleV = (FF%Uniform%AngleV(Ufop%IData) - FF%Uniform%AngleV(Ufop%IData - 1))/Ufop%dt + UFopdt%VelV = (FF%Uniform%VelV(Ufop%IData) - FF%Uniform%VelV(Ufop%IData - 1))/Ufop%dt + UFopdt%ShrH = (FF%Uniform%ShrH(Ufop%IData) - FF%Uniform%ShrH(Ufop%IData - 1))/Ufop%dt + UFopdt%ShrV = (FF%Uniform%ShrV(Ufop%IData) - FF%Uniform%ShrV(Ufop%IData - 1))/Ufop%dt + UFopdt%LinShrV = (FF%Uniform%LinShrV(Ufop%IData) - FF%Uniform%LinShrV(Ufop%IData - 1))/Ufop%dt + UFopdt%VelGust = (FF%Uniform%VelGust(Ufop%IData) - FF%Uniform%VelGust(Ufop%IData - 1))/Ufop%dt + end if + + if (.not. FF%RotateWindBox) then + if (.not. allocated(AccelUVW)) then + ! Velocity + do i = 1, NumPoints + VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionXYZ(:, i)) + end do + else + ! Velocity and acceleration + do i = 1, NumPoints + VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionXYZ(:, i)) + AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, UFopdt, PositionXYZ(:, i)) + end do + end if + + else ! Rotated wind box + + if (.not. allocated(AccelUVW)) then + ! Rotation, velocity + do i = 1, NumPoints + PositionPrime = GetPrimePosition(PositionXYZ(:, i)) + VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionPrime) + end do + else + ! Rotation, velocity, and acceleration + do i = 1, NumPoints + PositionPrime = GetPrimePosition(PositionXYZ(:, i)) + VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionPrime) + AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, UFopdt, PositionPrime) + end do + end if + + end if + + case (Grid_FieldType) + + !------------------------------------------------------------------------- + ! Grid Flow Field + !------------------------------------------------------------------------- + + if (.not. FF%RotateWindBox) then + + if (.not. allocated(AccelUVW)) then + ! Velocity + do i = 1, NumPoints + if (PositionXYZ(3, i) <= 0.0_ReKi) then + VelocityUVW(:, i) = 0.0_ReKi + cycle + end if + call GridField_GetInterp(FF%Grid, Time, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D, TmpErrStat, TmpErrMsg) + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + VelocityUVW(:, i) = GridField_GetVel(FF%Grid, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D) + end do + else + ! Velocity and acceleration + do i = 1, NumPoints + if (PositionXYZ(3, i) <= 0.0_ReKi) then + VelocityUVW(:, i) = 0.0_ReKi + AccelUVW(:, i) = 0.0_Reki + cycle + end if + call GridField_GetInterp(FF%Grid, Time, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D, TmpErrStat, TmpErrMsg) + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + VelocityUVW(:, i) = GridField_GetVel(FF%Grid, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D) + AccelUVW(:, i) = GridField_GetAcc(FF%Grid, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D) + end do + end if + + else ! Rotated wind box + + if (.not. allocated(AccelUVW)) then + ! Velocity (rotated) + do i = 1, NumPoints + PositionPrime = GetPrimePosition(PositionXYZ(:, i)) + if (PositionPrime(3) <= ReKi) then + VelocityUVW(:, i) = 0.0_ReKi + cycle + end if + call GridField_GetInterp(FF%Grid, Time, PositionPrime, DY, DZ, DT, P, Interp3D, TmpErrStat, TmpErrMsg) + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + VelocityUVW(:, i) = matmul(FF%RotFromWind, GridField_GetVel(FF%Grid, PositionPrime, DY, DZ, DT, P, Interp3D)) + end do + else + ! Velocity and acceleration (rotated) + do i = 1, NumPoints + ! Get rotated coordinates + PositionPrime = GetPrimePosition(PositionXYZ(:, i)) + if (PositionPrime(3) <= ReKi) then + VelocityUVW(:, i) = 0.0_ReKi + AccelUVW(:, i) = 0.0_ReKi + cycle + end if + call GridField_GetInterp(FF%Grid, Time, PositionPrime, DY, DZ, DT, P, Interp3D, TmpErrStat, TmpErrMsg) + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + VelocityUVW(:, i) = matmul(FF%RotFromWind, GridField_GetVel(FF%Grid, PositionPrime, DY, DZ, DT, P, Interp3D)) + AccelUVW(:, i) = matmul(FF%RotFromWind, GridField_GetAcc(FF%Grid, PositionPrime, DY, DZ, DT, P, Interp3D)) + end do + end if + end if + + case (User_FieldType) + + !------------------------------------------------------------------------- + ! User Flow Field + !------------------------------------------------------------------------- + + call SetErrStat(ErrID_Fatal, "User Field not implemented", ErrStat, ErrMsg, RoutineName) + return + + case (External_FieldType) + + !------------------------------------------------------------------------- + ! External Flow Field + !------------------------------------------------------------------------- + + ! If external field is not allocated, return error + if (.not. allocated(FF%external%Vel)) then + call SetErrStat(ErrID_Fatal, "External Field not allocated", ErrStat, ErrMsg, RoutineName) + return + end if + + VelocityUVW = FF%external%Vel(:, IStart:IStart + NumPoints - 1) + + case default + call SetErrStat(ErrID_Fatal, "Invalid FieldType "//trim(num2lstr(FF%FieldType)), ErrStat, ErrMsg, RoutineName) + return + end select + +contains + + pure function GetPrimePosition(Position) result(PrimePosition) + real(ReKi), dimension(3), intent(in) :: Position + real(ReKi), dimension(3) :: PrimePosition + PrimePosition = matmul(FF%RotToWind, (Position - FF%RefPosition)) + FF%RefPosition + end function + +end subroutine + +pure function UniformField_GetVel(UF, op, Position) result(Velocity) + use, intrinsic :: ieee_arithmetic + + type(UniformFieldType), intent(in) :: UF + type(UniformField_Interp), intent(in) :: op + real(ReKi), dimension(3), intent(in) :: Position + real(ReKi), dimension(3) :: Velocity + + character(*), parameter :: RoutineName = "UniformField_GetVel" + real(ReKi) :: V1 + real(ReKi) :: V1_rotate, VZ_rotate + + if (Position(3) > 0.0_ReKi) then + + ! Calculate horizontal velocity if position is above ground + V1 = op%VelH*((Position(3)/UF%RefHeight)**op%ShrV & ! power-law wind shear + + (op%ShrH*(Position(2)*op%CosAngleH + Position(1)*op%SinAngleH) & ! horizontal linear shear + + op%LinShrV*(Position(3) - UF%RefHeight))/UF%RefLength) & ! vertical linear shear + + op%VelGust ! gust speed + + ! Apply upflow angle + V1_rotate = op%CosAngleV*V1 - op%SinAngleV*op%VelV + VZ_rotate = op%SinAngleV*V1 + op%CosAngleV*op%VelV + + ! Apply wind direction + Velocity(1) = V1_rotate*op%CosAngleH + Velocity(2) = -V1_rotate*op%SinAngleH + Velocity(3) = VZ_rotate + + else + + ! Height is below ground, set velocity to zero. + ! Removed error check to be consistent with full field method + Velocity = 0.0_ReKi + + end if + +end function + +function UniformField_GetAcc(UF, op, opdt, Position) result(Accel) + type(UniformFieldType), intent(in) :: UF + type(UniformField_Interp), intent(in) :: op + type(UniformField_Interp), intent(in) :: opdt + real(ReKi), dimension(3), intent(in) :: Position + real(ReKi), dimension(3) :: Accel + + character(*), parameter :: RoutineName = "UniformField_GetAcc" + real(ReKi) :: C1, C2, C3, C4, C5 + + ! If only one data point or time is outside data range, acceleration is zero + if (op%IData == 1 .or. op%IData > UF%DataSize .or. Position(3) <= 0.0_Reki) then + Accel = 0.0_ReKi + else + + ! If change in time is negative or near zero, acceleration is zero + if (op%dt < 0.0_ReKi .or. EqualRealNos(op%dt, 0.0_ReKi)) then + Accel = 0.0_ReKi + return + end if + + C1 = (Position(3)/UF%RefHeight)**op%ShrV + & + (op%LinShrV*(Position(3) - UF%RefHeight) + & + op%ShrH*(Position(1)*op%SinAngleH + & + Position(2)*op%CosAngleH))/UF%RefLength + + C2 = op%CosAngleV*(op%VelGust + op%VelH*(C1)) + + C3 = opdt%AngleV*op%SinAngleV*(op%VelGust + op%VelH*(C1)) + + C4 = opdt%LinShrV*(Position(3) - UF%RefHeight) + & + opdt%ShrH*(Position(1)*op%SinAngleH + Position(2)*op%CosAngleH) + & + op%ShrH*(Position(1)*opdt%AngleH*op%CosAngleH - & + Position(2)*opdt%AngleH*op%SinAngleH) + + C5 = opdt%VelGust + opdt%VelH*C1 + & + op%VelH*(opdt%ShrV*(Position(3)/UF%RefHeight)**op%ShrV* & + log(Position(3)/UF%RefHeight) + C4/UF%RefLength) + + Accel(1) = -opdt%AngleH*op%SinAngleH*(C2 - op%SinAngleV*op%VelV) + & + op%CosAngleH*(-opdt%AngleV*op%CosAngleV*op%VelV - C3 - & + opdt%VelV*op%SinAngleV + op%CosAngleV*C5) + + Accel(2) = opdt%AngleH*op%CosAngleH*(-C2 + op%SinAngleV*op%VelV) + & + op%SinAngleH*(opdt%AngleV*op%CosAngleV*op%VelV + C3 + & + opdt%VelV*op%SinAngleV - op%CosAngleV*C5) + + Accel(3) = opdt%AngleV*C2 - opdt%AngleV*op%SinAngleV*op%VelV + & + opdt%VelV*op%CosAngleV + op%SinAngleV*C5 + end if + +end function + +pure function UniformField_GetOP(UF, Time) result(op) + + type(UniformFieldType), intent(in) :: UF + real(DbKi), intent(in) :: Time + type(UniformField_Interp) :: op + integer(IntKi) :: i + real(ReKi) :: alpha, OMalpha + + ! Save the time in operating point + op%Time = real(Time, ReKi) + + ! If only one data point or time is at or below first time, use first sample + if (UF%DataSize == 1 .or. Time < UF%Time(1)) then + + op%IData = 1 + op%dt = 0.0_ReKi + op%VelH = UF%VelH(1) + op%AngleH = UF%AngleH(1) + op%AngleV = UF%AngleV(1) + op%VelV = UF%VelV(1) + op%ShrH = UF%ShrH(1) + op%ShrV = UF%ShrV(1) + op%LinShrV = UF%LinShrV(1) + op%VelGust = UF%VelGust(1) + + ! If time is after end time, use last data point + else if (Time >= UF%Time(UF%DataSize)) then + + op%IData = UF%DataSize + 1 + op%dt = 0.0_ReKi + op%VelH = UF%VelH(UF%DataSize) + op%AngleH = UF%AngleH(UF%DataSize) + op%AngleV = UF%AngleV(UF%DataSize) + op%VelV = UF%VelV(UF%DataSize) + op%ShrH = UF%ShrH(UF%DataSize) + op%ShrV = UF%ShrV(UF%DataSize) + op%LinShrV = UF%LinShrV(UF%DataSize) + op%VelGust = UF%VelGust(UF%DataSize) + + else + + ! Find first index where current time is less than Time(i) + do i = 2, UF%DataSize + if (Time < UF%Time(i)) exit + end do + + op%IData = i + + ! Calculate interval delta time + op%dt = UF%Time(i) - UF%Time(i - 1) + + ! Calculate interpolation coefficient [0,1] + alpha = real((Time - UF%Time(i - 1))/op%dt, ReKi) + OMalpha = 1.0_ReKi - alpha + + ! Blend states before and after time based on alpha + op%VelH = UF%VelH(i - 1)*OMalpha + UF%VelH(i)*alpha + op%AngleH = UF%AngleH(i - 1)*OMalpha + UF%AngleH(i)*alpha + op%AngleV = UF%AngleV(i - 1)*OMalpha + UF%AngleV(i)*alpha + op%VelV = UF%VelV(i - 1)*OMalpha + UF%VelV(i)*alpha + op%ShrH = UF%ShrH(i - 1)*OMalpha + UF%ShrH(i)*alpha + op%ShrV = UF%ShrV(i - 1)*OMalpha + UF%ShrV(i)*alpha + op%LinShrV = UF%LinShrV(i - 1)*OMalpha + UF%LinShrV(i)*alpha + op%VelGust = UF%VelGust(i - 1)*OMalpha + UF%VelGust(i)*alpha + + end if + + op%CosAngleH = cos(op%AngleH) + op%SinAngleH = sin(op%AngleH) + op%CosAngleV = cos(op%AngleV) + op%SinAngleV = sin(op%AngleV) + +end function + +pure function UniformField_AD_DiskVel(op) result(DiskVel) + type(UniformField_Interp), intent(in) :: op + real(ReKi), dimension(3) :: DiskVel + + real(ReKi) :: V1_rotate, Vz_rotate + + V1_rotate = op%CosAngleV*op%VelH - op%SinAngleV*op%VelV + Vz_rotate = op%SinAngleV*op%VelH + op%CosAngleV*op%VelV + + DiskVel(1) = V1_rotate*op%CosAngleH + DiskVel(2) = -V1_rotate*op%SinAngleH + DiskVel(3) = Vz_rotate + +end function + +function GridField_GetVel(GF, Position, DY, DZ, DT, P, Interp3D) result(Velocity) + + type(GridFieldType), intent(in) :: GF !< Grid-Field data + real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value + real(ReKi), intent(in) :: DY, DZ, DT !< Weights [-1,1] + real(ReKi), dimension(3, 8), intent(in) :: P !< Interp points + logical, intent(in) :: Interp3D !< flag for 3D vs 2D interp + real(ReKi) :: Velocity(3) !< The U, V, W velocities + + character(*), parameter :: RoutineName = "GridField_GetVel" + + real(ReKi) :: N(8, 1) ! Shape function values + + if (Interp3D) then + + ! Get 3D interpolation weights + N(1, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) + N(2, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) + N(3, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) + N(4, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) + N(5, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) + N(6, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) + N(7, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) + N(8, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) + N(1:4, 1) = N(1:4, 1)*(1.0_ReKi - DT)/8.0_ReKi + N(5:8, 1) = N(5:8, 1)*(1.0_ReKi + DT)/8.0_ReKi + + ! Calculate velocity via matrix multiplication + Velocity = pack(matmul(P, N), .true.) + + else + + ! Get 2D interpolation weights + N(1, 1) = (1.0_ReKi - DZ)*(1.0_ReKi - DT)/4.0_ReKi + N(2, 1) = (1.0_ReKi + DZ)*(1.0_ReKi - DT)/4.0_ReKi + N(3, 1) = (1.0_ReKi - DZ)*(1.0_ReKi + DT)/4.0_ReKi + N(4, 1) = (1.0_ReKi + DZ)*(1.0_ReKi + DT)/4.0_ReKi + + ! Calculate velocity via matrix multiplication + Velocity = pack(matmul(P(:, 1:4), N(1:4, 1)), .true.) + + end if + + ! Add mean wind speed after interpolation if flag is set + if (GF%AddMeanAfterInterp) then + Velocity(1) = Velocity(1) + GetMeanVelocity(Position(3)) + end if + +contains + + function GetMeanVelocity(PosZ) result(U) + real(ReKi), intent(in) :: PosZ + real(ReKi) :: U + select case (GF%WindProfileType) + case (WindProfileType_None) + U = 0.0_ReKi + case (WindProfileType_PL) + U = GF%MeanWS*(PosZ/GF%RefHeight)**GF%PLExp ! [IEC 61400-1 6.3.1.2 (10)] + case (WindProfileType_Log) + if (.not. EqualRealNos(GF%RefHeight, GF%Z0) .and. PosZ > 0.0_ReKi) then + U = GF%MeanWS*log(PosZ/GF%Z0)/log(GF%RefHeight/GF%Z0) + else + U = 0.0_ReKi + end if + case (WindProfileType_Constant) + U = GF%MeanWS + case default + U = 0.0_ReKi + end select + end function + +end function + +function GridField_GetAcc(GF, Position, DY, DZ, DT, P, Interp3D) result(Accel) + + type(GridFieldType), intent(in) :: GF + real(ReKi), dimension(3), intent(in) :: Position + real(ReKi), intent(in) :: DY, DZ, DT !< Weights [-1,1] + real(ReKi), dimension(3, 8), intent(in) :: P !< Interp points + logical, intent(in) :: Interp3D !< flag for 3D vs 2D interp + real(ReKi), dimension(3) :: Accel + + character(*), parameter :: RoutineName = "GridField_GetAcc" + real(ReKi) :: N(8, 1) + + if (Interp3D) then + + ! Get 3D interpolation weights + N(1, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) + N(2, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) + N(3, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) + N(4, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) + N(5, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) + N(6, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) + N(7, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) + N(8, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) + N(1:4, 1) = N(1:4, 1)/(-4.0_ReKi*GF%DTime) + N(5:8, 1) = N(5:8, 1)/(4.0_ReKi*GF%DTime) + + ! Calculate Accel via matrix multiplication + Accel = pack(matmul(P, N), .true.) + + else + + ! Get 2D interpolation weights + N(1, 1) = (1.0_ReKi - DZ)/(-2.0_ReKi*GF%DTime) + N(2, 1) = (1.0_ReKi + DZ)/(-2.0_ReKi*GF%DTime) + N(3, 1) = (1.0_ReKi - DZ)/(2.0_ReKi*GF%DTime) + N(4, 1) = (1.0_ReKi + DZ)/(2.0_ReKi*GF%DTime) + + ! Calculate Accel via matrix multiplication + Accel = pack(matmul(P(:, 1:4), N(1:4, 1)), .true.) + + end if + +end function + +subroutine GridField_GetInterp(GF, Time, Position, DY, DZ, DT, P, Interp3D, ErrStat, ErrMsg) + + type(GridFieldType), intent(in) :: GF !< Grid-Field data + real(DbKi), intent(in) :: Time !< time (s) + real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value + real(ReKi), intent(out) :: DY, DZ, DT !< + real(ReKi), intent(out) :: P(3, 8) + logical, intent(out) :: Interp3D + integer(IntKi), intent(out) :: ErrStat !< error status + character(*), intent(out) :: ErrMsg !< error message + + character(*), parameter :: RoutineName = "GridField_GetInterp" + + integer(IntKi) :: IT_LO, IT_HI + integer(IntKi) :: IY_LO, IY_HI + integer(IntKi) :: IZ_LO, IZ_HI + + logical :: OnGrid + real(ReKi) :: TimeShifted + integer(IntKi) :: boundStat + + ErrStat = ErrID_None + ErrMsg = "" + + !---------------------------------------------------------------------------- + ! Find grid bounds in Time and Z + !---------------------------------------------------------------------------- + + ! Get grid time bounds + boundStat = GridField_GetBoundsT(GF, Time, Position(1), DT, IT_LO, IT_HI, TimeShifted) + if (boundStat > 0) then + ErrMsg = ' Error: GF wind array was exhausted at '//TRIM(Num2LStr(TIME))// & + ' seconds (trying to access data at '//TRIM(Num2LStr(TimeShifted))//' seconds).' + ErrStat = ErrID_Fatal + return + end if + + ! Get grid Z bounds + boundStat = GridField_GetBoundsZ(GF, Position(3), DZ, IZ_LO, IZ_HI, OnGrid) + if (boundStat < 0) then + ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction '// & + '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' + ErrStat = ErrID_Fatal + return + else if (boundStat > 0) then + ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction (Z='// & + TRIM(Num2LStr(Position(3)))//' m is above the grid).' + ErrStat = ErrID_Fatal + return + end if + + !---------------------------------------------------------------------------- + ! Interpolate + !---------------------------------------------------------------------------- + + if (OnGrid .or. GF%InterpTower) then + + ! Set flag for 3D interpolation to true + Interp3D = .true. + + ! Get grid Y bounds + boundStat = GridField_GetBoundsY(GF, Position(2), DY, IY_LO, IY_HI) + if (boundStat /= 0) then + ErrMsg = ' GF wind array boundaries violated: Grid too small in Y direction. Y='// & + TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*GF%YHWid))// & + ', '//TRIM(Num2LStr(GF%YHWid))//']' + ErrStat = ErrID_Fatal + return + end if + + if (OnGrid) then + + ! Get points from the grid + P(:, 1) = GF%Vel(:, IY_LO, IZ_LO, IT_LO) + P(:, 2) = GF%Vel(:, IY_HI, IZ_LO, IT_LO) + P(:, 3) = GF%Vel(:, IY_LO, IZ_HI, IT_LO) + P(:, 4) = GF%Vel(:, IY_HI, IZ_HI, IT_LO) + P(:, 5) = GF%Vel(:, IY_LO, IZ_LO, IT_HI) + P(:, 6) = GF%Vel(:, IY_HI, IZ_LO, IT_HI) + P(:, 7) = GF%Vel(:, IY_LO, IZ_HI, IT_HI) + P(:, 8) = GF%Vel(:, IY_HI, IZ_HI, IT_HI) + + else if (GF%InterpTower) then + + ! Get points from grid bottom and ground + P(:, 1) = 0.0_ReKi !GF%Vel(:, IY_LO, IZ_LO, IT_LO) + P(:, 2) = 0.0_ReKi !GF%Vel(:, IY_HI, IZ_LO, IT_LO) + P(:, 3) = GF%Vel(:, IY_LO, IZ_HI, IT_LO) + P(:, 4) = GF%Vel(:, IY_HI, IZ_HI, IT_LO) + P(:, 5) = 0.0_ReKi !GF%Vel(:, IY_HI, IZ_LO, IT_HI) + P(:, 6) = 0.0_ReKi !GF%Vel(:, IY_LO, IZ_LO, IT_HI) + P(:, 7) = GF%Vel(:, IY_LO, IZ_HI, IT_HI) + P(:, 8) = GF%Vel(:, IY_HI, IZ_HI, IT_HI) + + end if + + else + + ! Set flag for 3D interpolation to false for 2D + Interp3D = .false. + + if (IZ_HI <= GF%NTGrids) then + ! In tower grid + P(:, 1) = GF%VelTower(:, IZ_LO, IT_LO) + P(:, 2) = GF%VelTower(:, IZ_HI, IT_LO) + P(:, 3) = GF%VelTower(:, IZ_LO, IT_HI) + P(:, 4) = GF%VelTower(:, IZ_HI, IT_HI) + else + ! Between tower grid and ground + P(:, 1) = GF%VelTower(:, IZ_LO, IT_LO) + P(:, 2) = 0.0_ReKi + P(:, 3) = GF%VelTower(:, IZ_LO, IT_HI) + P(:, 4) = 0.0_ReKi + end if + + end if + +end subroutine + +function GridField_GetBoundsY(GF, PosY, DY, IY_LO, IY_HI) result(stat) + + type(GridFieldType), intent(in) :: GF + real(ReKi), intent(in) :: PosY + real(ReKi), intent(out) :: DY + integer(IntKi), intent(out) :: IY_LO, IY_HI + + real(ReKi) :: Y_Grid + integer(IntKi) :: stat + + ! Calculate position on Y grid + Y_Grid = (PosY + GF%YHWid)*GF%InvDY + 1 + + ! Calculate bounding grid indices + IY_LO = floor(Y_Grid, IntKi) + IY_HI = ceiling(Y_Grid, IntKi) + + ! Position location within interval [0,1] + DY = Y_Grid - aint(Y_Grid) + + ! Initialize stat to zero to indicate position is in bounds + stat = 0 + + if (IY_LO >= 1 .and. IY_HI <= GF%NYGrids) then + DY = 2.0_ReKi*DY - 1.0_ReKi + else if (IY_LO == 0 .and. DY >= 1.0_ReKi - GridTol) then + IY_LO = 1 + IY_HI = 2 + DY = -1.0_ReKi + else if (IY_LO == GF%NYGrids .and. DY <= GridTol) then + IY_LO = GF%NYGrids - 1 + IY_HI = GF%NYGrids + DY = 1.0_ReKi + else + ! Position outside + stat = -1 + end if + +end function + +function GridField_GetBoundsZ(GF, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) + + type(GridFieldType), intent(in) :: GF + real(ReKi), intent(in) :: PosZ + real(ReKi), intent(out) :: DZ + integer(IntKi), intent(out) :: IZ_LO, IZ_HI + logical, intent(out) :: OnGrid + + integer(IntKi) :: stat + real(ReKi) :: Z_GRID + real(ReKi) :: Z_twr(3) + + ! Calculate position on Z grid + Z_GRID = (PosZ - GF%GridBase)*GF%InvDZ + 1 + + ! Calculate bounding grid indices + IZ_LO = floor(Z_GRID, IntKi) + IZ_HI = ceiling(Z_GRID, IntKi) + + ! Position location within interval [-1,1] + DZ = Z_GRID - aint(Z_GRID) + + ! Initialize stat to zero to indicate position is in bounds + stat = 0 + + ! If indices are within grid, set on grid to true + if (IZ_LO >= 1 .and. IZ_HI <= GF%NZGrids) then + + OnGrid = .true. + DZ = 2.0_ReKi*DZ - 1.0_ReKi + + else if (IZ_LO < 1) then + + if (IZ_LO == 0 .and. DZ >= 1.0_ReKi - GridTol) then + OnGrid = .true. + IZ_LO = 1 + IZ_HI = 2 + DZ = -1.0_ReKi + else if (GF%InterpTower) then + ! Interp from bottom of grid to ground (zero velocity) + OnGrid = .false. + IZ_LO = 0 + IZ_HI = 1 + DZ = 2.0_ReKi*(PosZ/GF%GridBase) - 1.0_ReKi + else if (GF%NTGrids > 0) then + ! Interpolate with tower grid + OnGrid = .false. + ! Tower grid is reversed (lowest index is top of tower) + IZ_LO = int(-(Z_GRID - 1)) + 1 + if (IZ_LO >= GF%NTGrids) then + ! Between end of tower grid and ground (zero velocity) + IZ_LO = GF%NTGrids + DZ = 1.0_ReKi - 2.0_ReKi*(PosZ/(GF%GridBase - real(IZ_LO - 1, ReKi)/GF%InvDZ)) + else + ! Within tower grid + DZ = 2.0_ReKi*(real(2 - IZ_LO, ReKi) - Z_GRID) - 1.0_ReKi + end if + IZ_HI = IZ_LO + 1 + else + ! Position below grid + stat = -1 + end if + + else if (IZ_HI > GF%NZGrids) then ! Above Grid + + if (IZ_HI == GF%NZGrids + 1 .and. DZ <= GridTol) then + OnGrid = .true. + IZ_LO = GF%NZGrids - 1 + IZ_HI = GF%NZGrids + DZ = 1.0_ReKi + else + ! Position above grid + stat = 1 + end if + + end if + +end function + +function GridField_GetBoundsT(GF, Time, PosX, DT, IT_LO, IT_HI, TimeShifted) result(stat) + + type(GridFieldType), intent(in) :: GF + real(DbKi), intent(in) :: Time + real(ReKi), intent(in) :: PosX + real(ReKi), intent(out) :: DT + integer(IntKi), intent(out) :: IT_LO, IT_HI + real(ReKi), intent(out) :: TimeShifted + + real(ReKi) :: T_GRID + integer(IntKi) :: stat + + ! Perform the time shift. At time=0, a point half the grid width downstream + ! (p%YHWid) will index into the zero time slice. If we did not do this, + ! any point downstream of the tower at the beginning of the run would + ! index outside of the array. This all assumes the grid width is at least as + ! large as the rotor. If it isn't, then the interpolation will not work. + + ! in distance, X: InputInfo%PosX - p%InitXPosition - TIME*p%MeanWS + TimeShifted = real(Time, ReKi) + (GF%InitXPosition - PosX)*GF%InvMWS + + ! If field is periodic and time is after total time, remove total time + if (GF%Periodic .and. TimeShifted > GF%TotalTime) then + TimeShifted = TimeShifted - GF%TotalTime + end if + + ! Get position on T grid + T_GRID = TimeShifted*GF%Rate + 1 + + ! Calculate bounding grid indices + IT_LO = floor(T_GRID, IntKi) + IT_HI = ceiling(T_GRID, IntKi) + + ! Position location within interval [0,1] + DT = T_GRID - aint(T_GRID) + + ! Initialize stat to indicate position is within grid + stat = 0 + + ! Adjust indices and interpolant + if (IT_LO >= 1 .and. IT_HI <= GF%NSteps) then + ! Point is within grid + DT = 2.0_ReKi*DT - 1.0_ReKi + else if (IT_LO == GF%NSteps) then + if (GF%Periodic) then + ! Time wraps back to beginning + IT_HI = 1 + DT = 2.0_ReKi*DT - 1.0_ReKi + else if (DT <= GridTol) then + ! Within tolerance of last time + IT_HI = IT_LO + DT = -1.0_Reki + else + ! Extrapolate + IT_LO = GF%NSteps - 1 + IT_HI = GF%NSteps + DT = DT + 1.0_ReKi + end if + else + ! Time exceeds array bounds + stat = 1 + end if + +end function + +end module diff --git a/modules/nwtc-library/src/FlowField.txt b/modules/nwtc-library/src/FlowField.txt new file mode 100644 index 0000000000..3d4563d35b --- /dev/null +++ b/modules/nwtc-library/src/FlowField.txt @@ -0,0 +1,90 @@ +#---------------------------------------------------------------------------------------------------------------------------------- +# Data structures for representing flow fields. +#---------------------------------------------------------------------------------------------------------------------------------- +# +#---------------------------------------------------------------------------------------------------------------------------------- + +param FlowField - IntKi Undef_FieldType - 0 - "This is the code for an undefined FieldType" - +param ^ - IntKi Uniform_FieldType - 1 - "Uniform FieldType from SteadyWind or Uniform Wind" - +param ^ - IntKi Grid_FieldType - 2 - "Grid-Field FieldType from TurbSim, Bladed, HAWC" - +param ^ - IntKi User_FieldType - 3 - "User FieldType configured by the user" - +param ^ - IntKi External_FieldType - 4 - "External FieldType from OpFM or similar" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ UniformFieldType ReKi RefHeight - - - "reference height; used to center the wind" meters +typedef ^ ^ ReKi RefLength - - - "reference length used to scale the linear shear" meters +typedef ^ ^ IntKi DataSize - - - "size of data in HH file" +typedef ^ ^ ReKi Time : - - "HH time array" seconds +typedef ^ ^ ReKi VelH : - - "HH horizontal wind speed" meters/sec +typedef ^ ^ ReKi VelV : - - "HH vertical wind speed, including tower shadow" meters/sec +typedef ^ ^ ReKi VelGust : - - "HH wind gust speed" - +typedef ^ ^ ReKi AngleH : - - "HH wind direction angle" degrees +typedef ^ ^ ReKi AngleV : - - "HH upflow angle" degrees +typedef ^ ^ ReKi ShrH : - - "HH horizontal linear shear" - +typedef ^ ^ ReKi ShrV : - - "HH vertical shear exponent" - +typedef ^ ^ ReKi LinShrV : - - "HH vertical linear shear" seconds + +typedef ^ UniformField_Interp IntKi IData - - - "Data index high" +typedef ^ ^ ReKi dt - - - "interval delta time" seconds +typedef ^ ^ ReKi Time - - - "HH time" seconds +typedef ^ ^ ReKi VelH - - - "HH horizontal wind speed" meters/sec +typedef ^ ^ ReKi VelV - - - "HH vertical wind speed, including tower shadow" meters/sec +typedef ^ ^ ReKi VelGust - - - "HH wind gust speed" - +typedef ^ ^ ReKi AngleH - - - "HH wind direction angle" degrees +typedef ^ ^ ReKi AngleV - - - "HH upflow angle" degrees +typedef ^ ^ ReKi ShrH - - - "HH horizontal linear shear" - +typedef ^ ^ ReKi ShrV - - - "HH vertical shear exponent" - +typedef ^ ^ ReKi LinShrV - - - "HH vertical linear shear" seconds +typedef ^ ^ ReKi CosAngleH - - - "Horizontal angle components" - +typedef ^ ^ ReKi SinAngleH - - - "Horizontal angle components" - +typedef ^ ^ ReKi CosAngleV - - - "Vertical angle components" - +typedef ^ ^ ReKi SinAngleV - - - "Vertical angle components" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ GridFieldType IntKi WindFileFormat - - - "Binary file format description number" - +typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - +typedef ^ ^ Logical Periodic - .false. - "Flag to indicate if the wind file is periodic" - +typedef ^ ^ Logical InterpTower - .false. - "Flag to indicate if we should interpolate wind speeds below the tower" - +typedef ^ ^ Logical AddMeanAfterInterp - .false. - "Add the mean wind speed after interpolating at a given height?" - +typedef ^ ^ ReKi RefHeight - 0 - "Reference (hub) height of the grid" meters +typedef ^ ^ SiKi Vel :::: - - "Array of field velocities" - +typedef ^ ^ SiKi Acc :::: - - "Array of field accelerations" - +typedef ^ ^ SiKi VelTower ::: - - "Array of tower velocities" - +typedef ^ ^ SiKi AccTower ::: - - "Array of tower accelerations" - +typedef ^ ^ ReKi DTime - 0 - "Delta time" seconds +typedef ^ ^ ReKi Rate - 0 - "Data rate (1/FFDTime)" Hertz +typedef ^ ^ ReKi YHWid - 0 - "Half the grid width" meters +typedef ^ ^ ReKi ZHWid - 0 - "Half the grid height" meters +typedef ^ ^ ReKi GridBase - 0 - "the height of the bottom of the grid" meters +typedef ^ ^ ReKi InitXPosition - 0 - "the initial x position of grid (distance in FF is offset)" meters +typedef ^ ^ ReKi InvDY - 0 - "reciprocal of delta y" 1/meters +typedef ^ ^ ReKi InvDZ - 0 - "reciprocal of delta z" 1/meters +typedef ^ ^ ReKi MeanWS - 0 - "Mean wind speed (as defined in FF file), not necessarily of the portion used" meters/second +typedef ^ ^ ReKi InvMWS - 0 - "reciprocal of mean wind speed (MeanFFWS)" seconds/meter +typedef ^ ^ ReKi TotalTime - 0 - "The total time of the simulation" seconds +typedef ^ ^ IntKi NComp - 3 - "Number of wind components" - +typedef ^ ^ IntKi NYGrids - 0 - "Number of points in the lateral (y) direction of the grids" - +typedef ^ ^ IntKi NZGrids - 0 - "Number of points in the vertical (z) direction of the grids" - +typedef ^ ^ IntKi NTGrids - 0 - "Number of points in the vertical (z) direction on the tower (below the grids)" - +typedef ^ ^ IntKi NSteps - 0 - "Number of time steps in the FF array" - +typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - +typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ ExternalFieldType ReKi Vel :: - - "Wind velocities populated by external driver" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ UserFieldType SiKi Dummy - - - "" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ FlowFieldType IntKi FieldType - 0 - "Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External}" - +typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters +typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians +typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" radians +typedef ^ ^ logical RotateWindBox - .false. - "flag indicating if the wind will be rotated" - +typedef ^ ^ ReKi RotToWind {3}{3} - - "Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X')" - +typedef ^ ^ ReKi RotFromWind {3}{3} - - "Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind)" - +typedef ^ ^ UniformFieldType Uniform - - - "Uniform Flow Data" +typedef ^ ^ GridFieldType Grid - - - "Grid Field Wind Data" +typedef ^ ^ UserFieldType User - - - "User Field Wind Data" +typedef ^ ^ ExternalFieldType External - - - "External Flow Data" diff --git a/modules/nwtc-library/src/FlowField_Types.f90 b/modules/nwtc-library/src/FlowField_Types.f90 new file mode 100644 index 0000000000..a344ed0c78 --- /dev/null +++ b/modules/nwtc-library/src/FlowField_Types.f90 @@ -0,0 +1,2510 @@ +!STARTOFREGISTRYGENERATEDFILE 'FlowField_Types.f90' +! +! WARNING This file is generated automatically by the FAST registry. +! Do not edit. Your changes to this file will be lost. +! +! FAST Registry +!********************************************************************************************************************************* +! FlowField_Types +!................................................................................................................................. +! This file is part of FlowField. +! +! Copyright (C) 2012-2016 National Renewable Energy Laboratory +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +! +! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. +! +!********************************************************************************************************************************* +!> This module contains the user-defined types needed in FlowField. It also contains copy, destroy, pack, and +!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. +MODULE FlowField_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: Undef_FieldType = 0 ! This is the code for an undefined FieldType [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Uniform_FieldType = 1 ! Uniform FieldType from SteadyWind or Uniform Wind [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Grid_FieldType = 2 ! Grid-Field FieldType from TurbSim, Bladed, HAWC [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: User_FieldType = 3 ! User FieldType configured by the user [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: External_FieldType = 4 ! External FieldType from OpFM or similar [-] +! ========= UniformFieldType ======= + TYPE, PUBLIC :: UniformFieldType + REAL(ReKi) :: RefHeight !< reference height; used to center the wind [meters] + REAL(ReKi) :: RefLength !< reference length used to scale the linear shear [meters] + INTEGER(IntKi) :: DataSize !< size of data in HH file [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Time !< HH time array [seconds] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VelH !< HH horizontal wind speed [meters/sec] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VelV !< HH vertical wind speed, including tower shadow [meters/sec] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VelGust !< HH wind gust speed [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AngleH !< HH wind direction angle [degrees] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AngleV !< HH upflow angle [degrees] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ShrH !< HH horizontal linear shear [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ShrV !< HH vertical shear exponent [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LinShrV !< HH vertical linear shear [seconds] + END TYPE UniformFieldType +! ======================= +! ========= UniformField_Interp ======= + TYPE, PUBLIC :: UniformField_Interp + INTEGER(IntKi) :: IData !< Data index high [-] + REAL(ReKi) :: dt !< interval delta time [seconds] + REAL(ReKi) :: Time !< HH time [seconds] + REAL(ReKi) :: VelH !< HH horizontal wind speed [meters/sec] + REAL(ReKi) :: VelV !< HH vertical wind speed, including tower shadow [meters/sec] + REAL(ReKi) :: VelGust !< HH wind gust speed [-] + REAL(ReKi) :: AngleH !< HH wind direction angle [degrees] + REAL(ReKi) :: AngleV !< HH upflow angle [degrees] + REAL(ReKi) :: ShrH !< HH horizontal linear shear [-] + REAL(ReKi) :: ShrV !< HH vertical shear exponent [-] + REAL(ReKi) :: LinShrV !< HH vertical linear shear [seconds] + REAL(ReKi) :: CosAngleH !< Horizontal angle components [-] + REAL(ReKi) :: SinAngleH !< Horizontal angle components [-] + REAL(ReKi) :: CosAngleV !< Vertical angle components [-] + REAL(ReKi) :: SinAngleV !< Vertical angle components [-] + END TYPE UniformField_Interp +! ======================= +! ========= GridFieldType ======= + TYPE, PUBLIC :: GridFieldType + INTEGER(IntKi) :: WindFileFormat !< Binary file format description number [-] + INTEGER(IntKi) :: WindProfileType = -1 !< Wind profile type (0=constant;1=logarithmic;2=power law) [-] + LOGICAL :: Periodic = .false. !< Flag to indicate if the wind file is periodic [-] + LOGICAL :: InterpTower = .false. !< Flag to indicate if we should interpolate wind speeds below the tower [-] + LOGICAL :: AddMeanAfterInterp = .false. !< Add the mean wind speed after interpolating at a given height? [-] + REAL(ReKi) :: RefHeight = 0 !< Reference (hub) height of the grid [meters] + REAL(SiKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Vel !< Array of field velocities [-] + REAL(SiKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Acc !< Array of field accelerations [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: VelTower !< Array of tower velocities [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: AccTower !< Array of tower accelerations [-] + REAL(ReKi) :: DTime = 0 !< Delta time [seconds] + REAL(ReKi) :: Rate = 0 !< Data rate (1/FFDTime) [Hertz] + REAL(ReKi) :: YHWid = 0 !< Half the grid width [meters] + REAL(ReKi) :: ZHWid = 0 !< Half the grid height [meters] + REAL(ReKi) :: GridBase = 0 !< the height of the bottom of the grid [meters] + REAL(ReKi) :: InitXPosition = 0 !< the initial x position of grid (distance in FF is offset) [meters] + REAL(ReKi) :: InvDY = 0 !< reciprocal of delta y [1/meters] + REAL(ReKi) :: InvDZ = 0 !< reciprocal of delta z [1/meters] + REAL(ReKi) :: MeanWS = 0 !< Mean wind speed (as defined in FF file), not necessarily of the portion used [meters/second] + REAL(ReKi) :: InvMWS = 0 !< reciprocal of mean wind speed (MeanFFWS) [seconds/meter] + REAL(ReKi) :: TotalTime = 0 !< The total time of the simulation [seconds] + INTEGER(IntKi) :: NComp = 3 !< Number of wind components [-] + INTEGER(IntKi) :: NYGrids = 0 !< Number of points in the lateral (y) direction of the grids [-] + INTEGER(IntKi) :: NZGrids = 0 !< Number of points in the vertical (z) direction of the grids [-] + INTEGER(IntKi) :: NTGrids = 0 !< Number of points in the vertical (z) direction on the tower (below the grids) [-] + INTEGER(IntKi) :: NSteps = 0 !< Number of time steps in the FF array [-] + REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] + REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] + END TYPE GridFieldType +! ======================= +! ========= ExternalFieldType ======= + TYPE, PUBLIC :: ExternalFieldType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vel !< Wind velocities populated by external driver [-] + END TYPE ExternalFieldType +! ======================= +! ========= UserFieldType ======= + TYPE, PUBLIC :: UserFieldType + REAL(SiKi) :: Dummy !< [-] + END TYPE UserFieldType +! ======================= +! ========= FlowFieldType ======= + TYPE, PUBLIC :: FlowFieldType + INTEGER(IntKi) :: FieldType = 0 !< Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External} [-] + REAL(ReKi) , DIMENSION(1:3) :: RefPosition !< Reference position (point where box is rotated) [meters] + REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] + REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [radians] + LOGICAL :: RotateWindBox = .false. !< flag indicating if the wind will be rotated [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: RotToWind !< Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X') [-] + REAL(ReKi) , DIMENSION(1:3,1:3) :: RotFromWind !< Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind) [-] + TYPE(UniformFieldType) :: Uniform !< Uniform Flow Data [-] + TYPE(GridFieldType) :: Grid !< Grid Field Wind Data [-] + TYPE(UserFieldType) :: User !< User Field Wind Data [-] + TYPE(ExternalFieldType) :: External !< External Flow Data [-] + END TYPE FlowFieldType +! ======================= +CONTAINS + SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UniformFieldType), INTENT(IN) :: SrcUniformFieldTypeData + TYPE(UniformFieldType), INTENT(INOUT) :: DstUniformFieldTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyUniformFieldType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUniformFieldTypeData%RefHeight = SrcUniformFieldTypeData%RefHeight + DstUniformFieldTypeData%RefLength = SrcUniformFieldTypeData%RefLength + DstUniformFieldTypeData%DataSize = SrcUniformFieldTypeData%DataSize +IF (ALLOCATED(SrcUniformFieldTypeData%Time)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%Time,1) + i1_u = UBOUND(SrcUniformFieldTypeData%Time,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%Time)) THEN + ALLOCATE(DstUniformFieldTypeData%Time(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%Time.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%Time = SrcUniformFieldTypeData%Time +ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%VelH)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%VelH,1) + i1_u = UBOUND(SrcUniformFieldTypeData%VelH,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%VelH)) THEN + ALLOCATE(DstUniformFieldTypeData%VelH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%VelH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%VelH = SrcUniformFieldTypeData%VelH +ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%VelV)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%VelV,1) + i1_u = UBOUND(SrcUniformFieldTypeData%VelV,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%VelV)) THEN + ALLOCATE(DstUniformFieldTypeData%VelV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%VelV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%VelV = SrcUniformFieldTypeData%VelV +ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%VelGust)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%VelGust,1) + i1_u = UBOUND(SrcUniformFieldTypeData%VelGust,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%VelGust)) THEN + ALLOCATE(DstUniformFieldTypeData%VelGust(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%VelGust.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%VelGust = SrcUniformFieldTypeData%VelGust +ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%AngleH)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%AngleH,1) + i1_u = UBOUND(SrcUniformFieldTypeData%AngleH,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%AngleH)) THEN + ALLOCATE(DstUniformFieldTypeData%AngleH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%AngleH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%AngleH = SrcUniformFieldTypeData%AngleH +ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%AngleV)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%AngleV,1) + i1_u = UBOUND(SrcUniformFieldTypeData%AngleV,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%AngleV)) THEN + ALLOCATE(DstUniformFieldTypeData%AngleV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%AngleV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%AngleV = SrcUniformFieldTypeData%AngleV +ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%ShrH)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%ShrH,1) + i1_u = UBOUND(SrcUniformFieldTypeData%ShrH,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%ShrH)) THEN + ALLOCATE(DstUniformFieldTypeData%ShrH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%ShrH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%ShrH = SrcUniformFieldTypeData%ShrH +ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%ShrV)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%ShrV,1) + i1_u = UBOUND(SrcUniformFieldTypeData%ShrV,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%ShrV)) THEN + ALLOCATE(DstUniformFieldTypeData%ShrV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%ShrV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%ShrV = SrcUniformFieldTypeData%ShrV +ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%LinShrV)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%LinShrV,1) + i1_u = UBOUND(SrcUniformFieldTypeData%LinShrV,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%LinShrV)) THEN + ALLOCATE(DstUniformFieldTypeData%LinShrV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%LinShrV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%LinShrV = SrcUniformFieldTypeData%LinShrV +ENDIF + END SUBROUTINE FlowField_CopyUniformFieldType + + SUBROUTINE FlowField_DestroyUniformFieldType( UniformFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(UniformFieldType), INTENT(INOUT) :: UniformFieldTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyUniformFieldType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + +IF (ALLOCATED(UniformFieldTypeData%Time)) THEN + DEALLOCATE(UniformFieldTypeData%Time) +ENDIF +IF (ALLOCATED(UniformFieldTypeData%VelH)) THEN + DEALLOCATE(UniformFieldTypeData%VelH) +ENDIF +IF (ALLOCATED(UniformFieldTypeData%VelV)) THEN + DEALLOCATE(UniformFieldTypeData%VelV) +ENDIF +IF (ALLOCATED(UniformFieldTypeData%VelGust)) THEN + DEALLOCATE(UniformFieldTypeData%VelGust) +ENDIF +IF (ALLOCATED(UniformFieldTypeData%AngleH)) THEN + DEALLOCATE(UniformFieldTypeData%AngleH) +ENDIF +IF (ALLOCATED(UniformFieldTypeData%AngleV)) THEN + DEALLOCATE(UniformFieldTypeData%AngleV) +ENDIF +IF (ALLOCATED(UniformFieldTypeData%ShrH)) THEN + DEALLOCATE(UniformFieldTypeData%ShrH) +ENDIF +IF (ALLOCATED(UniformFieldTypeData%ShrV)) THEN + DEALLOCATE(UniformFieldTypeData%ShrV) +ENDIF +IF (ALLOCATED(UniformFieldTypeData%LinShrV)) THEN + DEALLOCATE(UniformFieldTypeData%LinShrV) +ENDIF + END SUBROUTINE FlowField_DestroyUniformFieldType + + SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(UniformFieldType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackUniformFieldType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! RefHeight + Re_BufSz = Re_BufSz + 1 ! RefLength + Int_BufSz = Int_BufSz + 1 ! DataSize + Int_BufSz = Int_BufSz + 1 ! Time allocated yes/no + IF ( ALLOCATED(InData%Time) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! Time upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Time) ! Time + END IF + Int_BufSz = Int_BufSz + 1 ! VelH allocated yes/no + IF ( ALLOCATED(InData%VelH) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! VelH upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VelH) ! VelH + END IF + Int_BufSz = Int_BufSz + 1 ! VelV allocated yes/no + IF ( ALLOCATED(InData%VelV) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! VelV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VelV) ! VelV + END IF + Int_BufSz = Int_BufSz + 1 ! VelGust allocated yes/no + IF ( ALLOCATED(InData%VelGust) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! VelGust upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VelGust) ! VelGust + END IF + Int_BufSz = Int_BufSz + 1 ! AngleH allocated yes/no + IF ( ALLOCATED(InData%AngleH) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AngleH upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngleH) ! AngleH + END IF + Int_BufSz = Int_BufSz + 1 ! AngleV allocated yes/no + IF ( ALLOCATED(InData%AngleV) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AngleV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngleV) ! AngleV + END IF + Int_BufSz = Int_BufSz + 1 ! ShrH allocated yes/no + IF ( ALLOCATED(InData%ShrH) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ShrH upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ShrH) ! ShrH + END IF + Int_BufSz = Int_BufSz + 1 ! ShrV allocated yes/no + IF ( ALLOCATED(InData%ShrV) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ShrV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ShrV) ! ShrV + END IF + Int_BufSz = Int_BufSz + 1 ! LinShrV allocated yes/no + IF ( ALLOCATED(InData%LinShrV) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinShrV upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LinShrV) ! LinShrV + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%RefHeight + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefLength + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%DataSize + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Time) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Time,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Time,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%Time,1), UBOUND(InData%Time,1) + ReKiBuf(Re_Xferred) = InData%Time(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%VelH) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelH,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelH,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%VelH,1), UBOUND(InData%VelH,1) + ReKiBuf(Re_Xferred) = InData%VelH(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%VelV) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelV,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%VelV,1), UBOUND(InData%VelV,1) + ReKiBuf(Re_Xferred) = InData%VelV(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%VelGust) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelGust,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelGust,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%VelGust,1), UBOUND(InData%VelGust,1) + ReKiBuf(Re_Xferred) = InData%VelGust(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AngleH) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngleH,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngleH,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AngleH,1), UBOUND(InData%AngleH,1) + ReKiBuf(Re_Xferred) = InData%AngleH(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AngleV) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngleV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngleV,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AngleV,1), UBOUND(InData%AngleV,1) + ReKiBuf(Re_Xferred) = InData%AngleV(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ShrH) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ShrH,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ShrH,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ShrH,1), UBOUND(InData%ShrH,1) + ReKiBuf(Re_Xferred) = InData%ShrH(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%ShrV) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ShrV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ShrV,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ShrV,1), UBOUND(InData%ShrV,1) + ReKiBuf(Re_Xferred) = InData%ShrV(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( .NOT. ALLOCATED(InData%LinShrV) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinShrV,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinShrV,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinShrV,1), UBOUND(InData%LinShrV,1) + ReKiBuf(Re_Xferred) = InData%LinShrV(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE FlowField_PackUniformFieldType + + SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(UniformFieldType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackUniformFieldType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%RefHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%DataSize = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Time not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Time)) DEALLOCATE(OutData%Time) + ALLOCATE(OutData%Time(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Time.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%Time,1), UBOUND(OutData%Time,1) + OutData%Time(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelH not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%VelH)) DEALLOCATE(OutData%VelH) + ALLOCATE(OutData%VelH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VelH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%VelH,1), UBOUND(OutData%VelH,1) + OutData%VelH(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelV not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%VelV)) DEALLOCATE(OutData%VelV) + ALLOCATE(OutData%VelV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VelV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%VelV,1), UBOUND(OutData%VelV,1) + OutData%VelV(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelGust not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%VelGust)) DEALLOCATE(OutData%VelGust) + ALLOCATE(OutData%VelGust(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VelGust.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%VelGust,1), UBOUND(OutData%VelGust,1) + OutData%VelGust(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngleH not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AngleH)) DEALLOCATE(OutData%AngleH) + ALLOCATE(OutData%AngleH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AngleH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AngleH,1), UBOUND(OutData%AngleH,1) + OutData%AngleH(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngleV not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AngleV)) DEALLOCATE(OutData%AngleV) + ALLOCATE(OutData%AngleV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AngleV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AngleV,1), UBOUND(OutData%AngleV,1) + OutData%AngleV(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ShrH not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ShrH)) DEALLOCATE(OutData%ShrH) + ALLOCATE(OutData%ShrH(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ShrH.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ShrH,1), UBOUND(OutData%ShrH,1) + OutData%ShrH(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ShrV not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ShrV)) DEALLOCATE(OutData%ShrV) + ALLOCATE(OutData%ShrV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ShrV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ShrV,1), UBOUND(OutData%ShrV,1) + OutData%ShrV(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinShrV not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%LinShrV)) DEALLOCATE(OutData%LinShrV) + ALLOCATE(OutData%LinShrV(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinShrV.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinShrV,1), UBOUND(OutData%LinShrV,1) + OutData%LinShrV(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF + END SUBROUTINE FlowField_UnPackUniformFieldType + + SUBROUTINE FlowField_CopyUniformField_Interp( SrcUniformField_InterpData, DstUniformField_InterpData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UniformField_Interp), INTENT(IN) :: SrcUniformField_InterpData + TYPE(UniformField_Interp), INTENT(INOUT) :: DstUniformField_InterpData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyUniformField_Interp' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUniformField_InterpData%IData = SrcUniformField_InterpData%IData + DstUniformField_InterpData%dt = SrcUniformField_InterpData%dt + DstUniformField_InterpData%Time = SrcUniformField_InterpData%Time + DstUniformField_InterpData%VelH = SrcUniformField_InterpData%VelH + DstUniformField_InterpData%VelV = SrcUniformField_InterpData%VelV + DstUniformField_InterpData%VelGust = SrcUniformField_InterpData%VelGust + DstUniformField_InterpData%AngleH = SrcUniformField_InterpData%AngleH + DstUniformField_InterpData%AngleV = SrcUniformField_InterpData%AngleV + DstUniformField_InterpData%ShrH = SrcUniformField_InterpData%ShrH + DstUniformField_InterpData%ShrV = SrcUniformField_InterpData%ShrV + DstUniformField_InterpData%LinShrV = SrcUniformField_InterpData%LinShrV + DstUniformField_InterpData%CosAngleH = SrcUniformField_InterpData%CosAngleH + DstUniformField_InterpData%SinAngleH = SrcUniformField_InterpData%SinAngleH + DstUniformField_InterpData%CosAngleV = SrcUniformField_InterpData%CosAngleV + DstUniformField_InterpData%SinAngleV = SrcUniformField_InterpData%SinAngleV + END SUBROUTINE FlowField_CopyUniformField_Interp + + SUBROUTINE FlowField_DestroyUniformField_Interp( UniformField_InterpData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(UniformField_Interp), INTENT(INOUT) :: UniformField_InterpData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyUniformField_Interp' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE FlowField_DestroyUniformField_Interp + + SUBROUTINE FlowField_PackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(UniformField_Interp), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackUniformField_Interp' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! IData + Re_BufSz = Re_BufSz + 1 ! dt + Re_BufSz = Re_BufSz + 1 ! Time + Re_BufSz = Re_BufSz + 1 ! VelH + Re_BufSz = Re_BufSz + 1 ! VelV + Re_BufSz = Re_BufSz + 1 ! VelGust + Re_BufSz = Re_BufSz + 1 ! AngleH + Re_BufSz = Re_BufSz + 1 ! AngleV + Re_BufSz = Re_BufSz + 1 ! ShrH + Re_BufSz = Re_BufSz + 1 ! ShrV + Re_BufSz = Re_BufSz + 1 ! LinShrV + Re_BufSz = Re_BufSz + 1 ! CosAngleH + Re_BufSz = Re_BufSz + 1 ! SinAngleH + Re_BufSz = Re_BufSz + 1 ! CosAngleV + Re_BufSz = Re_BufSz + 1 ! SinAngleV + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%IData + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Time + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VelH + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VelV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VelGust + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AngleH + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AngleV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShrH + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShrV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LinShrV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CosAngleH + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SinAngleH + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%CosAngleV + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%SinAngleV + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_PackUniformField_Interp + + SUBROUTINE FlowField_UnPackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(UniformField_Interp), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackUniformField_Interp' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%IData = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%dt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Time = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VelH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VelV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VelGust = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AngleH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%AngleV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShrH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ShrV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%LinShrV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CosAngleH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SinAngleH = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CosAngleV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%SinAngleV = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_UnPackUniformField_Interp + + SUBROUTINE FlowField_CopyGridFieldType( SrcGridFieldTypeData, DstGridFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(GridFieldType), INTENT(IN) :: SrcGridFieldTypeData + TYPE(GridFieldType), INTENT(INOUT) :: DstGridFieldTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyGridFieldType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstGridFieldTypeData%WindFileFormat = SrcGridFieldTypeData%WindFileFormat + DstGridFieldTypeData%WindProfileType = SrcGridFieldTypeData%WindProfileType + DstGridFieldTypeData%Periodic = SrcGridFieldTypeData%Periodic + DstGridFieldTypeData%InterpTower = SrcGridFieldTypeData%InterpTower + DstGridFieldTypeData%AddMeanAfterInterp = SrcGridFieldTypeData%AddMeanAfterInterp + DstGridFieldTypeData%RefHeight = SrcGridFieldTypeData%RefHeight +IF (ALLOCATED(SrcGridFieldTypeData%Vel)) THEN + i1_l = LBOUND(SrcGridFieldTypeData%Vel,1) + i1_u = UBOUND(SrcGridFieldTypeData%Vel,1) + i2_l = LBOUND(SrcGridFieldTypeData%Vel,2) + i2_u = UBOUND(SrcGridFieldTypeData%Vel,2) + i3_l = LBOUND(SrcGridFieldTypeData%Vel,3) + i3_u = UBOUND(SrcGridFieldTypeData%Vel,3) + i4_l = LBOUND(SrcGridFieldTypeData%Vel,4) + i4_u = UBOUND(SrcGridFieldTypeData%Vel,4) + IF (.NOT. ALLOCATED(DstGridFieldTypeData%Vel)) THEN + ALLOCATE(DstGridFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGridFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstGridFieldTypeData%Vel = SrcGridFieldTypeData%Vel +ENDIF +IF (ALLOCATED(SrcGridFieldTypeData%Acc)) THEN + i1_l = LBOUND(SrcGridFieldTypeData%Acc,1) + i1_u = UBOUND(SrcGridFieldTypeData%Acc,1) + i2_l = LBOUND(SrcGridFieldTypeData%Acc,2) + i2_u = UBOUND(SrcGridFieldTypeData%Acc,2) + i3_l = LBOUND(SrcGridFieldTypeData%Acc,3) + i3_u = UBOUND(SrcGridFieldTypeData%Acc,3) + i4_l = LBOUND(SrcGridFieldTypeData%Acc,4) + i4_u = UBOUND(SrcGridFieldTypeData%Acc,4) + IF (.NOT. ALLOCATED(DstGridFieldTypeData%Acc)) THEN + ALLOCATE(DstGridFieldTypeData%Acc(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGridFieldTypeData%Acc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstGridFieldTypeData%Acc = SrcGridFieldTypeData%Acc +ENDIF +IF (ALLOCATED(SrcGridFieldTypeData%VelTower)) THEN + i1_l = LBOUND(SrcGridFieldTypeData%VelTower,1) + i1_u = UBOUND(SrcGridFieldTypeData%VelTower,1) + i2_l = LBOUND(SrcGridFieldTypeData%VelTower,2) + i2_u = UBOUND(SrcGridFieldTypeData%VelTower,2) + i3_l = LBOUND(SrcGridFieldTypeData%VelTower,3) + i3_u = UBOUND(SrcGridFieldTypeData%VelTower,3) + IF (.NOT. ALLOCATED(DstGridFieldTypeData%VelTower)) THEN + ALLOCATE(DstGridFieldTypeData%VelTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGridFieldTypeData%VelTower.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstGridFieldTypeData%VelTower = SrcGridFieldTypeData%VelTower +ENDIF +IF (ALLOCATED(SrcGridFieldTypeData%AccTower)) THEN + i1_l = LBOUND(SrcGridFieldTypeData%AccTower,1) + i1_u = UBOUND(SrcGridFieldTypeData%AccTower,1) + i2_l = LBOUND(SrcGridFieldTypeData%AccTower,2) + i2_u = UBOUND(SrcGridFieldTypeData%AccTower,2) + i3_l = LBOUND(SrcGridFieldTypeData%AccTower,3) + i3_u = UBOUND(SrcGridFieldTypeData%AccTower,3) + IF (.NOT. ALLOCATED(DstGridFieldTypeData%AccTower)) THEN + ALLOCATE(DstGridFieldTypeData%AccTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGridFieldTypeData%AccTower.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstGridFieldTypeData%AccTower = SrcGridFieldTypeData%AccTower +ENDIF + DstGridFieldTypeData%DTime = SrcGridFieldTypeData%DTime + DstGridFieldTypeData%Rate = SrcGridFieldTypeData%Rate + DstGridFieldTypeData%YHWid = SrcGridFieldTypeData%YHWid + DstGridFieldTypeData%ZHWid = SrcGridFieldTypeData%ZHWid + DstGridFieldTypeData%GridBase = SrcGridFieldTypeData%GridBase + DstGridFieldTypeData%InitXPosition = SrcGridFieldTypeData%InitXPosition + DstGridFieldTypeData%InvDY = SrcGridFieldTypeData%InvDY + DstGridFieldTypeData%InvDZ = SrcGridFieldTypeData%InvDZ + DstGridFieldTypeData%MeanWS = SrcGridFieldTypeData%MeanWS + DstGridFieldTypeData%InvMWS = SrcGridFieldTypeData%InvMWS + DstGridFieldTypeData%TotalTime = SrcGridFieldTypeData%TotalTime + DstGridFieldTypeData%NComp = SrcGridFieldTypeData%NComp + DstGridFieldTypeData%NYGrids = SrcGridFieldTypeData%NYGrids + DstGridFieldTypeData%NZGrids = SrcGridFieldTypeData%NZGrids + DstGridFieldTypeData%NTGrids = SrcGridFieldTypeData%NTGrids + DstGridFieldTypeData%NSteps = SrcGridFieldTypeData%NSteps + DstGridFieldTypeData%PLExp = SrcGridFieldTypeData%PLExp + DstGridFieldTypeData%Z0 = SrcGridFieldTypeData%Z0 + END SUBROUTINE FlowField_CopyGridFieldType + + SUBROUTINE FlowField_DestroyGridFieldType( GridFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(GridFieldType), INTENT(INOUT) :: GridFieldTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyGridFieldType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + +IF (ALLOCATED(GridFieldTypeData%Vel)) THEN + DEALLOCATE(GridFieldTypeData%Vel) +ENDIF +IF (ALLOCATED(GridFieldTypeData%Acc)) THEN + DEALLOCATE(GridFieldTypeData%Acc) +ENDIF +IF (ALLOCATED(GridFieldTypeData%VelTower)) THEN + DEALLOCATE(GridFieldTypeData%VelTower) +ENDIF +IF (ALLOCATED(GridFieldTypeData%AccTower)) THEN + DEALLOCATE(GridFieldTypeData%AccTower) +ENDIF + END SUBROUTINE FlowField_DestroyGridFieldType + + SUBROUTINE FlowField_PackGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(GridFieldType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackGridFieldType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! WindFileFormat + Int_BufSz = Int_BufSz + 1 ! WindProfileType + Int_BufSz = Int_BufSz + 1 ! Periodic + Int_BufSz = Int_BufSz + 1 ! InterpTower + Int_BufSz = Int_BufSz + 1 ! AddMeanAfterInterp + Re_BufSz = Re_BufSz + 1 ! RefHeight + Int_BufSz = Int_BufSz + 1 ! Vel allocated yes/no + IF ( ALLOCATED(InData%Vel) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Vel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vel) ! Vel + END IF + Int_BufSz = Int_BufSz + 1 ! Acc allocated yes/no + IF ( ALLOCATED(InData%Acc) ) THEN + Int_BufSz = Int_BufSz + 2*4 ! Acc upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Acc) ! Acc + END IF + Int_BufSz = Int_BufSz + 1 ! VelTower allocated yes/no + IF ( ALLOCATED(InData%VelTower) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! VelTower upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VelTower) ! VelTower + END IF + Int_BufSz = Int_BufSz + 1 ! AccTower allocated yes/no + IF ( ALLOCATED(InData%AccTower) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AccTower upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AccTower) ! AccTower + END IF + Re_BufSz = Re_BufSz + 1 ! DTime + Re_BufSz = Re_BufSz + 1 ! Rate + Re_BufSz = Re_BufSz + 1 ! YHWid + Re_BufSz = Re_BufSz + 1 ! ZHWid + Re_BufSz = Re_BufSz + 1 ! GridBase + Re_BufSz = Re_BufSz + 1 ! InitXPosition + Re_BufSz = Re_BufSz + 1 ! InvDY + Re_BufSz = Re_BufSz + 1 ! InvDZ + Re_BufSz = Re_BufSz + 1 ! MeanWS + Re_BufSz = Re_BufSz + 1 ! InvMWS + Re_BufSz = Re_BufSz + 1 ! TotalTime + Int_BufSz = Int_BufSz + 1 ! NComp + Int_BufSz = Int_BufSz + 1 ! NYGrids + Int_BufSz = Int_BufSz + 1 ! NZGrids + Int_BufSz = Int_BufSz + 1 ! NTGrids + Int_BufSz = Int_BufSz + 1 ! NSteps + Re_BufSz = Re_BufSz + 1 ! PLExp + Re_BufSz = Re_BufSz + 1 ! Z0 + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%WindFileFormat + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WindProfileType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Periodic, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%InterpTower, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%AddMeanAfterInterp, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefHeight + Re_Xferred = Re_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%Vel) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Vel,4), UBOUND(InData%Vel,4) + DO i3 = LBOUND(InData%Vel,3), UBOUND(InData%Vel,3) + DO i2 = LBOUND(InData%Vel,2), UBOUND(InData%Vel,2) + DO i1 = LBOUND(InData%Vel,1), UBOUND(InData%Vel,1) + ReKiBuf(Re_Xferred) = InData%Vel(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%Acc) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Acc,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Acc,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Acc,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Acc,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Acc,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Acc,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Acc,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Acc,4) + Int_Xferred = Int_Xferred + 2 + + DO i4 = LBOUND(InData%Acc,4), UBOUND(InData%Acc,4) + DO i3 = LBOUND(InData%Acc,3), UBOUND(InData%Acc,3) + DO i2 = LBOUND(InData%Acc,2), UBOUND(InData%Acc,2) + DO i1 = LBOUND(InData%Acc,1), UBOUND(InData%Acc,1) + ReKiBuf(Re_Xferred) = InData%Acc(i1,i2,i3,i4) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%VelTower) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelTower,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelTower,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelTower,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelTower,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelTower,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelTower,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%VelTower,3), UBOUND(InData%VelTower,3) + DO i2 = LBOUND(InData%VelTower,2), UBOUND(InData%VelTower,2) + DO i1 = LBOUND(InData%VelTower,1), UBOUND(InData%VelTower,1) + ReKiBuf(Re_Xferred) = InData%VelTower(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AccTower) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AccTower,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AccTower,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AccTower,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AccTower,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AccTower,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AccTower,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AccTower,3), UBOUND(InData%AccTower,3) + DO i2 = LBOUND(InData%AccTower,2), UBOUND(InData%AccTower,2) + DO i1 = LBOUND(InData%AccTower,1), UBOUND(InData%AccTower,1) + ReKiBuf(Re_Xferred) = InData%AccTower(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%DTime + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Rate + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%YHWid + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ZHWid + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%GridBase + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InitXPosition + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InvDY + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InvDZ + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MeanWS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%InvMWS + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%TotalTime + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NComp + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NYGrids + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NZGrids + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NTGrids + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NSteps + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PLExp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Z0 + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_PackGridFieldType + + SUBROUTINE FlowField_UnPackGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(GridFieldType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackGridFieldType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%WindFileFormat = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%WindProfileType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%Periodic = TRANSFER(IntKiBuf(Int_Xferred), OutData%Periodic) + Int_Xferred = Int_Xferred + 1 + OutData%InterpTower = TRANSFER(IntKiBuf(Int_Xferred), OutData%InterpTower) + Int_Xferred = Int_Xferred + 1 + OutData%AddMeanAfterInterp = TRANSFER(IntKiBuf(Int_Xferred), OutData%AddMeanAfterInterp) + Int_Xferred = Int_Xferred + 1 + OutData%RefHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vel not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i4_l = IntKiBuf( Int_Xferred ) + i4_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Vel)) DEALLOCATE(OutData%Vel) + ALLOCATE(OutData%Vel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Vel,4), UBOUND(OutData%Vel,4) + DO i3 = LBOUND(OutData%Vel,3), UBOUND(OutData%Vel,3) + DO i2 = LBOUND(OutData%Vel,2), UBOUND(OutData%Vel,2) + DO i1 = LBOUND(OutData%Vel,1), UBOUND(OutData%Vel,1) + OutData%Vel(i1,i2,i3,i4) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Acc not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i4_l = IntKiBuf( Int_Xferred ) + i4_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Acc)) DEALLOCATE(OutData%Acc) + ALLOCATE(OutData%Acc(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Acc.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i4 = LBOUND(OutData%Acc,4), UBOUND(OutData%Acc,4) + DO i3 = LBOUND(OutData%Acc,3), UBOUND(OutData%Acc,3) + DO i2 = LBOUND(OutData%Acc,2), UBOUND(OutData%Acc,2) + DO i1 = LBOUND(OutData%Acc,1), UBOUND(OutData%Acc,1) + OutData%Acc(i1,i2,i3,i4) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelTower not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%VelTower)) DEALLOCATE(OutData%VelTower) + ALLOCATE(OutData%VelTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VelTower.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%VelTower,3), UBOUND(OutData%VelTower,3) + DO i2 = LBOUND(OutData%VelTower,2), UBOUND(OutData%VelTower,2) + DO i1 = LBOUND(OutData%VelTower,1), UBOUND(OutData%VelTower,1) + OutData%VelTower(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AccTower not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AccTower)) DEALLOCATE(OutData%AccTower) + ALLOCATE(OutData%AccTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AccTower.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AccTower,3), UBOUND(OutData%AccTower,3) + DO i2 = LBOUND(OutData%AccTower,2), UBOUND(OutData%AccTower,2) + DO i1 = LBOUND(OutData%AccTower,1), UBOUND(OutData%AccTower,1) + OutData%AccTower(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + OutData%DTime = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Rate = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%YHWid = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ZHWid = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%GridBase = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InitXPosition = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InvDY = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InvDZ = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%MeanWS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%InvMWS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%TotalTime = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%NComp = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NYGrids = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NZGrids = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NTGrids = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NSteps = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%PLExp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Z0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_UnPackGridFieldType + + SUBROUTINE FlowField_CopyExternalFieldType( SrcExternalFieldTypeData, DstExternalFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExternalFieldType), INTENT(IN) :: SrcExternalFieldTypeData + TYPE(ExternalFieldType), INTENT(INOUT) :: DstExternalFieldTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyExternalFieldType' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcExternalFieldTypeData%Vel)) THEN + i1_l = LBOUND(SrcExternalFieldTypeData%Vel,1) + i1_u = UBOUND(SrcExternalFieldTypeData%Vel,1) + i2_l = LBOUND(SrcExternalFieldTypeData%Vel,2) + i2_u = UBOUND(SrcExternalFieldTypeData%Vel,2) + IF (.NOT. ALLOCATED(DstExternalFieldTypeData%Vel)) THEN + ALLOCATE(DstExternalFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstExternalFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstExternalFieldTypeData%Vel = SrcExternalFieldTypeData%Vel +ENDIF + END SUBROUTINE FlowField_CopyExternalFieldType + + SUBROUTINE FlowField_DestroyExternalFieldType( ExternalFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(ExternalFieldType), INTENT(INOUT) :: ExternalFieldTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyExternalFieldType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + +IF (ALLOCATED(ExternalFieldTypeData%Vel)) THEN + DEALLOCATE(ExternalFieldTypeData%Vel) +ENDIF + END SUBROUTINE FlowField_DestroyExternalFieldType + + SUBROUTINE FlowField_PackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(ExternalFieldType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackExternalFieldType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! Vel allocated yes/no + IF ( ALLOCATED(InData%Vel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Vel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vel) ! Vel + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%Vel) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Vel,2), UBOUND(InData%Vel,2) + DO i1 = LBOUND(InData%Vel,1), UBOUND(InData%Vel,1) + ReKiBuf(Re_Xferred) = InData%Vel(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FlowField_PackExternalFieldType + + SUBROUTINE FlowField_UnPackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(ExternalFieldType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackExternalFieldType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vel not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Vel)) DEALLOCATE(OutData%Vel) + ALLOCATE(OutData%Vel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Vel,2), UBOUND(OutData%Vel,2) + DO i1 = LBOUND(OutData%Vel,1), UBOUND(OutData%Vel,1) + OutData%Vel(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FlowField_UnPackExternalFieldType + + SUBROUTINE FlowField_CopyUserFieldType( SrcUserFieldTypeData, DstUserFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UserFieldType), INTENT(IN) :: SrcUserFieldTypeData + TYPE(UserFieldType), INTENT(INOUT) :: DstUserFieldTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyUserFieldType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUserFieldTypeData%Dummy = SrcUserFieldTypeData%Dummy + END SUBROUTINE FlowField_CopyUserFieldType + + SUBROUTINE FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(UserFieldType), INTENT(INOUT) :: UserFieldTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyUserFieldType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE FlowField_DestroyUserFieldType + + SUBROUTINE FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(UserFieldType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackUserFieldType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! Dummy + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%Dummy + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_PackUserFieldType + + SUBROUTINE FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(UserFieldType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackUserFieldType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_UnPackUserFieldType + + SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FlowFieldType), INTENT(IN) :: SrcFlowFieldTypeData + TYPE(FlowFieldType), INTENT(INOUT) :: DstFlowFieldTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyFlowFieldType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstFlowFieldTypeData%FieldType = SrcFlowFieldTypeData%FieldType + DstFlowFieldTypeData%RefPosition = SrcFlowFieldTypeData%RefPosition + DstFlowFieldTypeData%PropagationDir = SrcFlowFieldTypeData%PropagationDir + DstFlowFieldTypeData%VFlowAngle = SrcFlowFieldTypeData%VFlowAngle + DstFlowFieldTypeData%RotateWindBox = SrcFlowFieldTypeData%RotateWindBox + DstFlowFieldTypeData%RotToWind = SrcFlowFieldTypeData%RotToWind + DstFlowFieldTypeData%RotFromWind = SrcFlowFieldTypeData%RotFromWind + CALL FlowField_Copyuniformfieldtype( SrcFlowFieldTypeData%Uniform, DstFlowFieldTypeData%Uniform, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FlowField_Copygridfieldtype( SrcFlowFieldTypeData%Grid, DstFlowFieldTypeData%Grid, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FlowField_Copyuserfieldtype( SrcFlowFieldTypeData%User, DstFlowFieldTypeData%User, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FlowField_Copyexternalfieldtype( SrcFlowFieldTypeData%External, DstFlowFieldTypeData%External, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE FlowField_CopyFlowFieldType + + SUBROUTINE FlowField_DestroyFlowFieldType( FlowFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(FlowFieldType), INTENT(INOUT) :: FlowFieldTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyFlowFieldType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + CALL FlowField_Destroyuniformfieldtype( FlowFieldTypeData%Uniform, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL FlowField_Destroygridfieldtype( FlowFieldTypeData%Grid, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL FlowField_Destroyuserfieldtype( FlowFieldTypeData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL FlowField_Destroyexternalfieldtype( FlowFieldTypeData%External, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END SUBROUTINE FlowField_DestroyFlowFieldType + + SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(FlowFieldType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackFlowFieldType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! FieldType + Re_BufSz = Re_BufSz + SIZE(InData%RefPosition) ! RefPosition + Re_BufSz = Re_BufSz + 1 ! PropagationDir + Re_BufSz = Re_BufSz + 1 ! VFlowAngle + Int_BufSz = Int_BufSz + 1 ! RotateWindBox + Re_BufSz = Re_BufSz + SIZE(InData%RotToWind) ! RotToWind + Re_BufSz = Re_BufSz + SIZE(InData%RotFromWind) ! RotFromWind + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Uniform: size of buffers for each call to pack subtype + CALL FlowField_Packuniformfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, .TRUE. ) ! Uniform + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Uniform + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Uniform + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Uniform + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Grid: size of buffers for each call to pack subtype + CALL FlowField_Packgridfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid, ErrStat2, ErrMsg2, .TRUE. ) ! Grid + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Grid + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Grid + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Grid + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! User: size of buffers for each call to pack subtype + CALL FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, .TRUE. ) ! User + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! User + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! User + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! User + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! External: size of buffers for each call to pack subtype + CALL FlowField_Packexternalfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%External, ErrStat2, ErrMsg2, .TRUE. ) ! External + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! External + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! External + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! External + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%FieldType + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%RefPosition,1), UBOUND(InData%RefPosition,1) + ReKiBuf(Re_Xferred) = InData%RefPosition(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%PropagationDir + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VFlowAngle + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RotateWindBox, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i2 = LBOUND(InData%RotToWind,2), UBOUND(InData%RotToWind,2) + DO i1 = LBOUND(InData%RotToWind,1), UBOUND(InData%RotToWind,1) + ReKiBuf(Re_Xferred) = InData%RotToWind(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + DO i2 = LBOUND(InData%RotFromWind,2), UBOUND(InData%RotFromWind,2) + DO i1 = LBOUND(InData%RotFromWind,1), UBOUND(InData%RotFromWind,1) + ReKiBuf(Re_Xferred) = InData%RotFromWind(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + CALL FlowField_Packuniformfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, OnlySize ) ! Uniform + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL FlowField_Packgridfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid, ErrStat2, ErrMsg2, OnlySize ) ! Grid + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, OnlySize ) ! User + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL FlowField_Packexternalfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%External, ErrStat2, ErrMsg2, OnlySize ) ! External + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END SUBROUTINE FlowField_PackFlowFieldType + + SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(FlowFieldType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackFlowFieldType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%FieldType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%RefPosition,1) + i1_u = UBOUND(OutData%RefPosition,1) + DO i1 = LBOUND(OutData%RefPosition,1), UBOUND(OutData%RefPosition,1) + OutData%RefPosition(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%PropagationDir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VFlowAngle = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RotateWindBox = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotateWindBox) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%RotToWind,1) + i1_u = UBOUND(OutData%RotToWind,1) + i2_l = LBOUND(OutData%RotToWind,2) + i2_u = UBOUND(OutData%RotToWind,2) + DO i2 = LBOUND(OutData%RotToWind,2), UBOUND(OutData%RotToWind,2) + DO i1 = LBOUND(OutData%RotToWind,1), UBOUND(OutData%RotToWind,1) + OutData%RotToWind(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + i1_l = LBOUND(OutData%RotFromWind,1) + i1_u = UBOUND(OutData%RotFromWind,1) + i2_l = LBOUND(OutData%RotFromWind,2) + i2_u = UBOUND(OutData%RotFromWind,2) + DO i2 = LBOUND(OutData%RotFromWind,2), UBOUND(OutData%RotFromWind,2) + DO i1 = LBOUND(OutData%RotFromWind,1), UBOUND(OutData%RotFromWind,1) + OutData%RotFromWind(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL FlowField_Unpackuniformfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Uniform, ErrStat2, ErrMsg2 ) ! Uniform + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL FlowField_Unpackgridfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid, ErrStat2, ErrMsg2 ) ! Grid + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL FlowField_Unpackuserfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%User, ErrStat2, ErrMsg2 ) ! User + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL FlowField_Unpackexternalfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%External, ErrStat2, ErrMsg2 ) ! External + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END SUBROUTINE FlowField_UnPackFlowFieldType + +END MODULE FlowField_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/nwtc-library/src/NWTC_Library.f90 b/modules/nwtc-library/src/NWTC_Library.f90 index 232c9c971a..77d1388f8c 100644 --- a/modules/nwtc-library/src/NWTC_Library.f90 +++ b/modules/nwtc-library/src/NWTC_Library.f90 @@ -71,6 +71,7 @@ MODULE NWTC_Library !! (without this, it is possible [depending on the Sys*.f90 file used] that the screen output will be written to a !! file called "fort.7") + USE NWTC_Library_Types USE NWTC_Num ! technically we don't need to specify this if we have ModMesh (because ModMesh USEs NWTC_Num) USE ModMesh From 64509d81a247f4d41e426e1121ad2ca752d6802a Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 22 Dec 2022 22:07:59 +0000 Subject: [PATCH 02/51] inflowwind: adding IfW_FlowField module This module allows InflowWind to read wind data files into the new FlowField module data structure in NWTC_Library. In the future, the routines within this module will replace the other InflowWind modules. --- modules/inflowwind/CMakeLists.txt | 3 + modules/inflowwind/src/IfW_FlowField.f90 | 2209 ++++++++++ modules/inflowwind/src/IfW_FlowField.txt | 95 + .../inflowwind/src/IfW_FlowField_Types.f90 | 3596 +++++++++++++++++ 4 files changed, 5903 insertions(+) create mode 100644 modules/inflowwind/src/IfW_FlowField.f90 create mode 100644 modules/inflowwind/src/IfW_FlowField.txt create mode 100644 modules/inflowwind/src/IfW_FlowField_Types.f90 diff --git a/modules/inflowwind/CMakeLists.txt b/modules/inflowwind/CMakeLists.txt index 58168790fe..d95ef84def 100644 --- a/modules/inflowwind/CMakeLists.txt +++ b/modules/inflowwind/CMakeLists.txt @@ -17,6 +17,7 @@ if (GENERATE_TYPES) generate_f90_types(src/InflowWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/InflowWind_Types.f90) generate_f90_types(src/Lidar.txt ${CMAKE_CURRENT_LIST_DIR}/src/Lidar_Types.f90) + generate_f90_types(src/IfW_FlowField.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_FlowField_Types.f90 -noextrap) generate_f90_types(src/IfW_BladedFFWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_BladedFFWind_Types.f90 -noextrap) generate_f90_types(src/IfW_4Dext.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_4Dext_Types.f90 -noextrap) generate_f90_types(src/IfW_HAWCWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_HAWCWind_Types.f90 -noextrap) @@ -27,6 +28,7 @@ if (GENERATE_TYPES) endif() set(IFW_SOURCES + src/IfW_FlowField.f90 src/IfW_BladedFFWind.f90 src/IfW_4Dext.f90 src/IfW_HAWCWind.f90 @@ -36,6 +38,7 @@ set(IFW_SOURCES src/InflowWind_Subs.f90 src/InflowWind.f90 src/Lidar.f90 + src/IfW_FlowField_Types.f90 src/IfW_FFWind_Base.f90 src/IfW_FFWind_Base_Types.f90 src/IfW_BladedFFWind_Types.f90 diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 new file mode 100644 index 0000000000..d50290c20f --- /dev/null +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -0,0 +1,2209 @@ +!> This module uses grid-field binary wind files to determine the wind inflow. +!! This module assumes that the origin, (0,0,0), is located at the tower centerline at ground level, +!! and that all units are specified in the metric system (using meters and seconds). +!! Data is shifted by half the grid width to account for turbine yaw (so that data in the X +!! direction actually starts at -1*p%FFYHWid meters). +!********************************************************************************************************************************** +! LICENSING +! Copyright (C) 2022 National Renewable Energy Laboratory +! +! This file is part of InflowWind. +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +!********************************************************************************************************************************** + +module IfW_FlowField + +use NWTC_Library +use IfW_FlowField_Types + +implicit none +private +public :: IfW_FlowField_Init + +type(ProgDesc), parameter :: IfW_FlowField_Ver = ProgDesc('IfW_FlowField', '', '') + +integer(IntKi), parameter :: WindProfileType_None = -1, & !< don't add wind profile; already included in input + WindProfileType_Constant = 0, & !< constant wind + WindProfileType_Log = 1, & !< logarithmic + WindProfileType_PL = 2 !< power law + +integer(IntKi), parameter :: ScaleMethod_None = 0, & !< no scaling + ScaleMethod_Direct = 1, & !< direct scaling factors + ScaleMethod_StdDev = 2 !< requested standard deviation + +type :: TurbSimHeaderType + integer(B2Ki) :: FileID + integer(B4Ki) :: NZGrids, NYGrids, NTGrids, NSteps + real(SiKi) :: dz, dy, dt + real(SiKi) :: mws, ref_height, grid_base_height + real(SiKi) :: VslopeX, VoffsetX + real(SiKi) :: VslopeY, VoffsetY + real(SiKi) :: VslopeZ, VoffsetZ + integer(B4Ki) :: DescLen +end type + +contains + +!---------------------------------------------------------------------------------------------------- +!> A subroutine to initialize the UserWind module. This routine will initialize the module. +!---------------------------------------------------------------------------------------------------- +subroutine IfW_FlowField_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) + + type(IfW_FlowField_InitInputType), intent(in) :: InitInp !< Input data for initialization + type(FlowFieldType), intent(out) :: FF !< Flow field + type(IfW_FlowField_InitOutputType), intent(out) :: InitOut !< Misc variables for optimization (not copied in glue code) + integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered + character(*), intent(out) :: ErrMsg !< A message about the error. See NWTC_Library info for ErrID_* levels. + + character(*), parameter :: RoutineName = 'IfW_FlowField_Init' + integer(IntKi) :: TmpErrStat ! Temp variable for the error status + character(ErrMsgLen) :: TmpErrMsg ! temporary error message + + ErrStat = ErrID_None + ErrMsg = "" + + !---------------------------------------------------------------------------- + ! Parameter initialization + !---------------------------------------------------------------------------- + + FF%PropagationDir = InitInp%PropagationDir*D2R + FF%VFlowAngle = InitInp%VFlowAngle*D2R + + ! Shift propagation direction so it is between -pi and pi + call MPi2Pi(FF%PropagationDir) + + !---------------------------------------------------------------------------- + ! Wind Type Initialization + !---------------------------------------------------------------------------- + + select case (InitInp%WindType) + case (1) ! Steady + FF%FieldType = Uniform_FieldType + call SteadyWind_Init(InitInp%Steady, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) + case (2) ! Uniform + FF%FieldType = Uniform_FieldType + call UniformWind_Init(InitInp%Uniform, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) + case (3) ! Binary TurbSim FF + FF%FieldType = Grid_FieldType + call TurbSim_Init(InitInp%TurbSim, InitInp%SumFileUnit, FF%Grid, InitOut%FileDat, TmpErrStat, TmpErrMsg) + case (4) ! Binary Bladed-Style FF + FF%FieldType = Grid_FieldType + ! call Read_Bladed_Binary(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) + case (5) ! HAWC + FF%FieldType = Grid_FieldType + call HAWC_Init(InitInp%HAWC, InitInp%SumFileUnit, FF%Grid, InitOut%FileDat, TmpErrStat, TmpErrMsg) + case (6) ! User Defined + FF%FieldType = Grid_FieldType + + case (7) ! Native Bladed FF + FF%FieldType = Grid_FieldType + ! call Read_Bladed_Native(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) + end select + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + !---------------------------------------------------------------------------- + ! Setup the coordinate transforms for rotating the wind field. + !---------------------------------------------------------------------------- + + ! Create the rotation matrices -- rotate from XYZ to X'Y'Z' (wind aligned along X) coordinates + ! Included in this rotation is the wind upflow (inclination) angle (rotation about Y axis) + FF%RotToWind(1, :) = [cos(-FF%VFlowAngle)*cos(-FF%PropagationDir), & + cos(-FF%VFlowAngle)*sin(-FF%PropagationDir), & + -sin(-FF%VFlowAngle)] + FF%RotToWind(2, :) = [-sin(-FF%PropagationDir), & + cos(-FF%PropagationDir), & + 0.0_ReKi] + FF%RotToWind(3, :) = [sin(-FF%VFlowAngle)*cos(-FF%PropagationDir), & + sin(-FF%VFlowAngle)*sin(-FF%PropagationDir), & + cos(-FF%VFlowAngle)] + + ! Create the rotation matrices -- rotate from X'Y'Z' (wind aligned along X) + ! to global XYZ coordinates: this is the same as a rotation about the + ! (positive) upflow angle multiplied by a rotation about the (positive) wind direction: + ! Global wind = R(p%PropagationDir) * R(p%VFlowAngle) * [local wind] + ! local wind = R( -p%VFlowAngle) * R (-p%PropagationDir) [global wind] + ! = R^T(p%VFlowAngle) * R^T(p%PropagationDir) [global wind] + ! = (R(p%PropagationDir) * R(p%VFlowAngle))^T [global wind] + FF%RotFromWind = transpose(FF%RotToWind) + + FF%RotateWindBox = .not. (EqualRealNos(FF%PropagationDir, 0.0_ReKi) .and. & + EqualRealNos(FF%VFlowAngle, 0.0_ReKi)) + + FF%RefPosition = [0.0_ReKi, 0.0_ReKi, InitOut%FileDat%RefHt] + + !---------------------------------------------------------------------------- + ! Initialization Output + !---------------------------------------------------------------------------- + + InitOut%Ver = IfW_FlowField_Ver + +end subroutine + +subroutine SteadyWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) + type(SteadyInitInputType), intent(in) :: InitInp + integer(IntKi), intent(in) :: SumFileUnit + type(UniformFieldType), intent(out) :: UF + type(WindFileDat), intent(out) :: FileDat + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = 'SteadyWind_Init' + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + + ErrStat = ErrID_None + ErrMsg = "" + + ! Set parameters from inititialization input + UF%DataSize = 1 + UF%RefHeight = InitInp%RefHt + UF%RefLength = 1.0_ReKi + + ! Allocate uniform wind data arrays + call Alloc_UniformWindArrays(UF, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Set data values + UF%Time = 0.0_ReKi + UF%VelH = InitInp%HWindSpeed + UF%VelV = 0.0_ReKi + UF%VelGust = 0.0_ReKi + UF%AngleH = 0.0_ReKi + UF%AngleV = 0.0_ReKi + UF%ShrH = 0.0_ReKi + UF%ShrV = InitInp%PLExp + UF%LinShrV = 0.0_ReKi + + !---------------------------------------------------------------------------- + ! Set wind file data + !---------------------------------------------------------------------------- + + FileDat%FileName = "" + FileDat%WindType = 1 + FileDat%RefHt = UF%RefHeight + FileDat%RefHt_Set = .false. + FileDat%DT = 0.0_ReKi + FileDat%NumTSteps = UF%DataSize + FileDat%ConstantDT = .false. + FileDat%TRange = 0.0_ReKi + FileDat%TRange_Limited = .false. + FileDat%YRange = 0.0_ReKi + FileDat%YRange_Limited = .false. + FileDat%ZRange = 0.0_ReKi + FileDat%ZRange_Limited = .false. + FileDat%BinaryFormat = 0_IntKi + FileDat%IsBinary = .false. + FileDat%TI = 0.0_ReKi + FileDat%TI_listed = .false. + FileDat%MWS = InitInp%HWindSpeed + + !---------------------------------------------------------------------------- + ! Write summary file if applicable + !---------------------------------------------------------------------------- + + if (SumFileUnit > 0) then + write (SumFileUnit, '(A)') + write (SumFileUnit, '(A80)') 'Steady wind -- Constant wind profile for entire simulation. No windfile read in.' + write (SumFileUnit, '(A40,G12.4)') ' Reference height: ', UF%RefHeight + write (SumFileUnit, '(A40,G12.4)') ' Horizontal velocity: ', UF%VelH(1) + write (SumFileUnit, '(A40,G12.4)') ' Vertical sheer power law exponent: ', UF%ShrV(1) + + ! Get IO status for unit + inquire (SumFileUnit, iostat=TmpErrStat) + if (TmpErrStat /= 0_IntKi) then + call SetErrStat(ErrID_Fatal, 'Error writing to summary file.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + +end subroutine + +subroutine UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) + type(UniformInitInputType), intent(in) :: InitInp + integer(IntKi), intent(in) :: SumFileUnit + type(UniformFieldType), intent(out) :: UF + type(WindFileDat), intent(out) :: FileDat + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = 'UniformWind_Init' + integer(IntKi), parameter :: MaxNumCols = 9 + integer(IntKi), parameter :: MaxTries = 100 + integer(IntKi) :: NumCols + integer(IntKi) :: LineNo, ILine + integer(IntKi) :: i + type(FileInfoType) :: WindFileInfo + logical :: WindFileConstantDT + real(DbKi) :: WindFileDT + real(ReKi) :: DirDiff + real(ReKi) :: TmpData(MaxNumCols) ! Temp variable for storing wind file data + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + + ErrStat = ErrID_None + ErrMsg = "" + + ! Set parameters from inititialization input + UF%RefHeight = InitInp%RefHt + UF%RefLength = InitInp%RefLength + + ! Read wind data from file or init input data + if (InitInp%UseInputFile) then + call ProcessComFile(InitInp%WindFileName, WindFileInfo, TmpErrStat, TmpErrMsg) + else + call NWTC_Library_CopyFileInfoType(InitInp%PassedFileData, WindFileInfo, MESH_NEWCOPY, TmpErrStat, TmpErrMsg) + end if + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Get number of data lines in file + UF%DataSize = WindFileInfo%NumLines + + ! Allocate uniform wind data arrays + call Alloc_UniformWindArrays(UF, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + !---------------------------------------------------------------------------- + ! Parse wind file data + !---------------------------------------------------------------------------- + + ! Initialize reading variables + NumCols = MaxNumCols + LineNo = 1 + + ! Attempt to read 9 columns from line; if error, upflow column is not in file + ! so set upflow=0 and reduce number of columns to read remaning data + call ParseAry(WindFileInfo, LineNo, "HH file line", TmpData(1:NumCols), NumCols, TmpErrStat, TmpErrMsg) + if (TmpErrStat /= 0) then + CALL SetErrStat(ErrID_Info,' Could not read upflow column in uniform wind files. Assuming upflow is 0.', ErrStat, ErrMsg, RoutineName) + UF%AngleV = 0 + NumCols = MaxNumCols - 1 + end if + + ! Parse the data and store it + LineNo = 1 + do i = 1, UF%DataSize + call ParseAry(WindFileInfo, LineNo, "HH file line", TmpData(1:NumCols), NumCols, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + UF%Time(i) = TmpData(1) + UF%VelH(i) = TmpData(2) + UF%AngleH(i) = TmpData(3)*D2R + UF%VelV(i) = TmpData(4) + UF%ShrH(i) = TmpData(5) + UF%ShrV(i) = TmpData(6) + UF%LinShrV(i) = TmpData(7) + UF%VelGust(i) = TmpData(8) + if (NumCols > 8) UF%AngleV(i) = TmpData(9)*D2R + end do + + !---------------------------------------------------------------------------- + ! Ensure the wind direction isn't jumping more than 180 degrees between + ! any 2 consecutive input times. + ! (Avoids interpolation errors with modular arithemetic.) + !---------------------------------------------------------------------------- + + do i = 2, UF%DataSize + ILine = 1 + do while (ILine < MaxTries) + DirDiff = (UF%AngleH(i) - UF%AngleH(i - 1)) + if (abs(DirDiff) < Pi) exit + UF%AngleH(i) = UF%AngleH(i) - SIGN(TwoPi, DirDiff) + ILine = ILine + 1 + end do + + if (ILine >= MaxTries) then + TmpErrMsg = ' Error calculating wind direction from uniform wind file. p%AngleH(' & + //TRIM(Num2LStr(i))//') = '//TRIM(Num2LStr(UF%AngleH(i)))//'; p%AngleH(' & + //TRIM(Num2LStr(i + 1))//') = '//TRIM(Num2LStr(UF%AngleH(i + 1))) + call SetErrStat(ErrID_Fatal, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + end if + end do + + !---------------------------------------------------------------------------- + ! Find out information on the timesteps and range + !---------------------------------------------------------------------------- + + ! Uniform timesteps + if (UF%DataSize > 3) then + WindFileConstantDT = .true. + WindFileDT = UF%Time(2) - UF%Time(1) + do I = 3, UF%DataSize + if (.not. EqualRealNos((UF%Time(i) - UF%Time(i - 1)), real(WindFileDT, ReKi))) then + WindFileConstantDT = .false. + exit + end if + end do + else + ! Insufficient points to check, report that the timesteps are not uniform + WindFileConstantDT = .false. + WindFileDT = 0.0_ReKi + end if + + !---------------------------------------------------------------------------- + ! Store wind file metadata + !---------------------------------------------------------------------------- + + FileDat%FileName = InitInp%WindFileName + FileDat%WindType = 2 + FileDat%RefHt = UF%RefHeight + FileDat%RefHt_Set = .false. + FileDat%DT = WindFileDT + FileDat%NumTSteps = UF%DataSize + FileDat%ConstantDT = WindFileConstantDT + FileDat%TRange = [UF%Time(1), UF%Time(UF%DataSize)] + FileDat%TRange_Limited = .false. + FileDat%YRange = (/0.0_ReKi, 0.0_ReKi/) + FileDat%YRange_Limited = .false. + FileDat%ZRange = (/0.0_ReKi, 0.0_ReKi/) + FileDat%ZRange_Limited = .false. + FileDat%BinaryFormat = 0_IntKi + FileDat%IsBinary = .false. + FileDat%TI = 0.0_ReKi + FileDat%TI_listed = .false. + + if (UF%DataSize == 1) then + FileDat%MWS = UF%VelH(1) + else + FileDat%MWS = 0.0_ReKi + do i = 2, UF%DataSize + FileDat%MWS = FileDat%MWS + 0.5_ReKi*(UF%VelH(i) + UF%VelH(i - 1))* & + (UF%Time(i) - UF%Time(i - 1)) + end do + FileDat%MWS = FileDat%MWS/(UF%Time(UF%DataSize) - UF%Time(1)) + end if + + ! Check if the fist data point from the file is not along the X-axis while applying the windfield rotation + if ((.not. EqualRealNos(UF%AngleH(1), 0.0_ReKi)) .and. & + (.not. EqualRealNos(InitInp%PropagationDir, 0.0_ReKi))) then + call SetErrStat(ErrID_Warn, ' Possible double rotation of wind field! Uniform wind file starts with a wind direction of '// & + TRIM(Num2LStr(UF%AngleH(1)*R2D))// & + ' degrees and the InflowWind input file specifies a PropagationDir of '// & + TRIM(Num2LStr(InitInp%PropagationDir*R2D))//' degrees.', & + ErrStat, ErrMsg, RoutineName) + end if + + !---------------------------------------------------------------------------- + ! Print warnings and messages + !---------------------------------------------------------------------------- + + if (UF%Time(1) > 0.0) then + TmpErrMsg = 'The uniform wind file : "'//TRIM(ADJUSTL(InitInp%WindFileName))// & + '" starts at a time '//'greater than zero. Interpolation errors may result.' + call SetErrStat(ErrID_Warn, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + end if + + if (UF%DataSize == 1) then + TmpErrMsg = ' Only 1 line in uniform wind file. Steady, horizontal wind speed at the hub height is '// & + TRIM(Num2LStr(UF%VelH(1)))//' m/s.' + call SetErrStat(ErrID_Info, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + end if + + !---------------------------------------------------------------------------- + ! Write to the summary file + !---------------------------------------------------------------------------- + + if (SumFileUnit > 0) then + write (SumFileUnit, '(A)') + write (SumFileUnit, '(A)') 'Uniform wind. Module '//TRIM(IfW_FlowField_Ver%Name)//' '//TRIM(IfW_FlowField_Ver%Ver) + write (SumFileUnit, '(A)') ' FileName: '//TRIM(InitInp%WindFileName) + write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', UF%RefHeight + write (SumFileUnit, '(A34,G12.4)') ' Reference length (m): ', UF%RefLength + write (SumFileUnit, '(A32,I8)') ' Number of data lines: ', UF%DataSize + write (SumFileUnit, '(A)') ' Time range (s): [ '// & + TRIM(Num2LStr(UF%Time(1)))//' : '//TRIM(Num2LStr(UF%Time(UF%DataSize)))//' ]' + + ! Get IO status for unit + inquire (SumFileUnit, iostat=TmpErrStat) + if (TmpErrStat /= 0_IntKi) then + call SetErrStat(ErrID_Fatal, 'Error writing to summary file.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + +end subroutine + +subroutine Alloc_UniformWindArrays(UF, ErrStat, ErrMsg) + type(UniformFieldType), intent(inout) :: UF + integer(IntKi), intent(OUT) :: ErrStat + character(*), intent(OUT) :: ErrMsg + + character(*), parameter :: RoutineName = 'Alloc_UniformWindArrays' + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + + ErrStat = ErrID_None + ErrMsg = "" + + if (.not. allocated(UF%Time)) then + call AllocAry(UF%Time, UF%DataSize, 'Uniform wind time', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + end if + + if (.not. allocated(UF%VelH)) then + call AllocAry(UF%VelH, UF%DataSize, 'Uniform wind horizontal wind speed', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + end if + + if (.not. allocated(UF%AngleH)) then + call AllocAry(UF%AngleH, UF%DataSize, 'Uniform wind direction', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + end if + + if (.not. allocated(UF%AngleV)) then + call AllocAry(UF%AngleV, UF%DataSize, 'Uniform wind upflow angle', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + end if + + if (.not. allocated(UF%VelV)) then + call AllocAry(UF%VelV, UF%DataSize, 'Uniform vertical wind speed', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + end if + + if (.not. allocated(UF%ShrH)) then + call AllocAry(UF%ShrH, UF%DataSize, 'Uniform horizontal linear shear', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + end if + + if (.not. allocated(UF%ShrV)) then + call AllocAry(UF%ShrV, UF%DataSize, 'Uniform vertical power-law shear exponent', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + end if + + if (.not. allocated(UF%LinShrV)) then + call AllocAry(UF%LinShrV, UF%DataSize, 'Uniform vertical linear shear', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + end if + + if (.not. allocated(UF%VelGust)) then + call AllocAry(UF%VelGust, UF%DataSize, 'Uniform gust velocity', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + end if + +end subroutine + +!> Read_TurbSim reads the binary TurbSim-format FF file (.bts). It fills the FFData array with +!! velocity data for the grids and fills the Tower array with velocities at points on the tower +!! (if data exists). +subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) + + type(TurbSimInitInputType), intent(in) :: InitInp + integer(IntKi), intent(in) :: SumFileUnit + type(GridFieldType), intent(out) :: GF + type(WindFileDat), intent(out) :: FileDat + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = "TurbSim_Init" + integer(IntKi) :: WindFileUnit + integer(B2Ki), allocatable :: VelRaw(:, :, :) ! raw grid-field velocity data at one time step + integer(B2Ki), allocatable :: TwrRaw(:, :) ! raw towrer velocity data at one time step + character(:), allocatable :: DescStr ! description string contained in the file + integer(IntKi) :: IC ! loop counter for wind components + integer(IntKi) :: IT ! loop counter for time + integer(IntKi) :: NChar ! number of characters in the description string + real(SiKi) :: Vslope(3) ! slope for "un-normalizing" data + real(SiKi) :: Voffset(3) ! offset for "un-normalizing" data + integer(IntKi) :: TmpErrStat ! temporary error status + character(ErrMsgLen) :: TmpErrMsg ! temporary error message + + type(TurbSimHeaderType) :: header + + !---------------------------------------------------------------------------- + ! Initialize error variables + !---------------------------------------------------------------------------- + + ErrStat = ErrID_None + ErrMsg = "" + + !---------------------------------------------------------------------------- + ! Open the binary wind file and read header + !---------------------------------------------------------------------------- + + ! 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 + + ! Open binary file + call OpenBInpFile(WindFileUnit, TRIM(InitInp%WindFileName), TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Read header from file + read (WindFileUnit, IOSTAT=TmpErrStat) header + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading header of the FF binary file "' & + //TRIM(InitInp%WindFileName)//'."', ErrStat, ErrMsg, RoutineName) + return + end if + + !---------------------------------------------------------------------------- + ! Populate parameter data from header + !---------------------------------------------------------------------------- + + GF%WindFileFormat = header%FileID ! file format identifier + GF%Periodic = header%FileID == 8 ! 7 is used for non-periodic wind files; 8 is periodic wind + GF%InterpTower = .false. ! wind should not be interpolated at tower + GF%AddMeanAfterInterp = .false. ! do not add mean wind speed after interpolation + + GF%DTime = real(header%dt, ReKi) ! grid spacing in time (dt), m/s + GF%Rate = 1.0_ReKi/GF%DTime ! Data rate (1/DTime), Hertz + + GF%NComp = 3 ! TurbSim file file contains 3 wind components + GF%NYGrids = header%NYGrids ! the number of grid points laterally + GF%NZGrids = header%NZGrids ! the number of grid points vertically + GF%NTGrids = header%NTGrids ! the number of tower points + GF%NSteps = header%NSteps ! the number of time steps + + GF%InvDY = 1.0_ReKi/real(header%dy, ReKi) ! 1/dy + GF%YHWid = 0.5_ReKi*(GF%NYGrids - 1)/GF%InvDY ! half the grid width (m) + + GF%InvDZ = 1.0_ReKi/real(header%dz, ReKi) ! 1/dz + GF%ZHWid = 0.5_ReKi*(GF%NZGrids - 1)/GF%InvDZ ! half the grid height (m) + + GF%MeanWS = real(header%mws, ReKi) ! the mean wind speed at hub height (m/s) + GF%InvMWS = 1.0_ReKi/GF%MeanWS ! inverse of mean wind speed + + GF%RefHeight = real(header%ref_height, ReKi) ! height of the hub (m) + GF%GridBase = real(header%grid_base_height, ReKi) ! height of the bottom of the grid (m) + + if (GF%Periodic) then + GF%InitXPosition = 0 ! start at the hub + GF%TotalTime = GF%NSteps*GF%DTime + else + GF%InitXPosition = GF%YHWid ! start half the grid width ahead of the turbine + GF%TotalTime = (GF%NSteps - 1)*GF%DTime + end if + + GF%WindProfileType = WindProfileType_None ! unused for turbsim + GF%PLExp = 0 ! unused for turbsim + GF%Z0 = 0 ! unused for turbsim + + !---------------------------------------------------------------------------- + ! Binary scaling factors from header + !---------------------------------------------------------------------------- + + ! Wind component slope for scaling, REAL(4) + Vslope = [header%VslopeX, header%VslopeY, header%VslopeZ] + + ! Wind component offset for scaling, REAL(4) + Voffset = [header%VoffsetX, header%VoffsetY, header%VoffsetZ] + + !---------------------------------------------------------------------------------------------- + ! Read the description string: "Generated by TurbSim (vx.xx, dd-mmm-yyyy) on dd-mmm-yyyy at hh:mm:ss." + !---------------------------------------------------------------------------------------------- + + ! The number of characters in the description string, max 200, INT(4) + NChar = header%DescLen + + ! Read description bytes, INT(1) + allocate (character(NChar)::DescStr) + read (WindFileUnit, IOSTAT=TmpErrStat) DescStr + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading description line in the FF binary file "' & + //TRIM(InitInp%WindFileName)//'."', ErrStat, ErrMsg, RoutineName) + return + end if + + !---------------------------------------------------------------------------- + ! Allocate arrays for the grid-field grid and tower if applicable + !---------------------------------------------------------------------------- + + ! Allocate storage for grid-field velocity data + call AllocAry(GF%Vel, GF%NComp, GF%NYGrids, GF%NZGrids, GF%NSteps, & + 'grid-field velocity data', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Allocate storage for raw grid-field velocity for each time step + allocate (VelRaw(GF%NComp, GF%NYGrids, GF%NZGrids), stat=TmpErrStat) + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, "error allocating grid-field time step velocity data", & + ErrStat, ErrMsg, RoutineName) + end if + if (ErrStat >= AbortErrLev) return + + ! If tower grids specified + if (GF%NTGrids > 0) then + + ! Allocate storage for tower velocity data + call AllocAry(GF%VelTower, GF%NComp, GF%NTGrids, GF%NSteps, & + 'tower wind velocity data.', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Allocate storage for raw tower data for each timestep + allocate (TwrRaw(GF%NComp, GF%NTGrids), stat=TmpErrStat) + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, "error allocating tower time step velocity data", & + ErrStat, ErrMsg, RoutineName) + end if + if (ErrStat >= AbortErrLev) return + end if + + !---------------------------------------------------------------------------- + ! Read the 16-bit raw velocity data and scale it to 32-bit real + !---------------------------------------------------------------------------- + + ! This could take a while, so we'll write a message indicating what's going on: + call WrScr(NewLine//' Reading a ' & + //TRIM(Num2LStr(GF%NYGrids))//'x' & + //TRIM(Num2LStr(GF%NZGrids))// & + ' grid ('//TRIM(Num2LStr(GF%YHWid*2))//' m wide, '// & + TRIM(Num2LStr(GF%GridBase))//' m to '// & + TRIM(Num2LStr(GF%GridBase + GF%ZHWid*2))// & + ' m above ground) with a characteristic wind speed of '// & + TRIM(Num2LStr(GF%MeanWS))//' m/s. '//TRIM(DescStr)) + + ! Loop through time steps + do IT = 1, GF%NSteps + + ! Read grid-field raw wind data (normalized) comprised of 2-byte integers, INT(2) + ! Indices are Velocity components, Y coordinates, Z coordinates + read (WindFileUnit, IOSTAT=TmpErrStat) VelRaw + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading grid wind components in the FF binary file "'// & + TRIM(InitInp%WindFileName)//'."', ErrStat, ErrMsg, RoutineName) + return + end if + + ! Loop through wind components (U, V, W), calculate de-normalized velocity (m/s) + do IC = 1, 3 + GF%Vel(IC, :, :, IT) = (real(VelRaw(IC, :, :), SiKi) - Voffset(IC))/VSlope(IC) + end do !IC + + ! Read tower raw wind data (normalized) comprised of 2-byte integers, INT(2) + ! Indices are Velocity components, Z coordinates + if (GF%NTGrids > 0) then + read (WindFileUnit, IOSTAT=TmpErrStat) TwrRaw + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading tower wind components in the FF binary file "'// & + TRIM(InitInp%WindFileName)//'."', ErrStat, ErrMsg, RoutineName) + return + end if + + ! Loop through wind components (U, V, W), calculate de-normalized velocity (m/s) + do IC = 1, 3 + GF%VelTower(IC, :, IT) = (real(TwrRaw(IC, :), SiKi) - Voffset(IC))/VSlope(IC) + end do + end if + end do + + !---------------------------------------------------------------------------- + ! Close the file + !---------------------------------------------------------------------------- + + close (WindFileUnit) + + if (GF%Periodic) then + call WrScr(NewLine//' Processed '//TRIM(Num2LStr(GF%NSteps))//' time steps of '// & + TRIM(Num2LStr(GF%Rate))//'-Hz grid-field data (period of '// & + TRIM(Num2LStr(GF%DTime*(GF%NSteps)))//' seconds).') + else + call WrScr(NewLine//' Processed '//TRIM(Num2LStr(GF%NSteps))//' time steps of '// & + TRIM(Num2LStr(GF%Rate))//'-Hz grid-field data ('// & + TRIM(Num2LStr(GF%DTime*(GF%NSteps - 1)))//' seconds).') + end if + + !---------------------------------------------------------------------------- + ! Store wind file metadata + !---------------------------------------------------------------------------- + + call PopulateWindFileDatFromGridField(GF, InitInp%WindFileName, 3, GF%NTGrids > 0, FileDat) + + !---------------------------------------------------------------------------- + ! Write the summary file + !---------------------------------------------------------------------------- + + if (SumFileUnit > 0) then + write (SumFileUnit, '(A)') + write (SumFileUnit, '(A)') 'TurbSim wind type. Read by InflowWind sub-module ' & + //TRIM(IfW_FlowField_Ver%Name)//' '//TRIM(IfW_FlowField_Ver%Ver) + write (SumFileUnit, '(A)') TRIM(TmpErrMsg) + write (SumFileUnit, '(5x,A)') 'FileName: '//TRIM(InitInp%WindFileName) + write (SumFileUnit, '(5x,A29,I3)') 'Binary file format id: ', GF%WindFileFormat + write (SumFileUnit, '(5x,A29,G12.4)') 'Reference height (m): ', GF%RefHeight + write (SumFileUnit, '(5x,A29,G12.4)') 'Timestep (s): ', GF%DTime + write (SumFileUnit, '(5x,A29,I12)') 'Number of timesteps: ', GF%NSteps + write (SumFileUnit, '(5x,A29,G12.4)') 'Mean windspeed (m/s): ', GF%MeanWS + write (SumFileUnit, '(5x,A29,L1)') 'Windfile is periodic: ', GF%Periodic + write (SumFileUnit, '(5x,A29,L1)') 'Windfile includes tower: ', GF%NTGrids > 0 + + if (GF%Periodic) then + write (SumFileUnit, '(5x,A)') 'Time range (s): [ '// & + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(GF%TotalTime))//' ]' + else ! Shift the time range to compensate for the shifting of the wind grid + write (SumFileUnit, '(5x,A)') 'Time range (s): [ '// & + TRIM(Num2LStr(-GF%InitXPosition*GF%InvMWS))//' : '// & + TRIM(Num2LStr(GF%TotalTime - GF%InitXPosition*GF%InvMWS))//' ]' + end if + + write (SumFileUnit, '(5x,A)') 'Y range (m): [ '// & + TRIM(Num2LStr(-GF%YHWid))//' : '//TRIM(Num2LStr(GF%YHWid))//' ]' + + if (GF%NTGrids > 0) then + write (SumFileUnit, '(5x,A)') 'Z range (m): [ '// & + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(GF%RefHeight + GF%ZHWid))//' ]' + else + write (SumFileUnit, '(5x,A)') 'Z range (m): [ '// & + TRIM(Num2LStr(GF%RefHeight - GF%ZHWid))//' : '//TRIM(Num2LStr(GF%RefHeight + GF%ZHWid))//' ]' + end if + + ! Get IO status for unit + inquire (SumFileUnit, iostat=TmpErrStat) + if (TmpErrStat /= 0_IntKi) then + call SetErrStat(ErrID_Fatal, 'Error writing to summary file.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + +end subroutine + +subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) + + type(HAWCInitInputType), intent(in) :: InitInp + integer(IntKi), intent(in) :: SumFileUnit + type(GridFieldType), intent(out) :: GF + type(WindFileDat), intent(out) :: FileDat + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = "Read_HAWC" + integer(IntKi) :: WindFileUnit + real(SiKi), allocatable :: VelRaw(:, :) ! grid-field data for one timestep + integer :: IC ! Loop counter for the number of wind components + integer :: IX, IY, IZ ! Loop counters for the number of grid points in the X,Y,Z directions + real(DbKi) :: vMean ! average wind speeds over time at target position + real(DbKi) :: vSum2 ! sum of wind speeds squared + real(ReKi) :: ActualSigma ! computed standard deviation + real(ReKi) :: ScaleFactors(3) ! scale factors + integer(IntKi) :: TmpErrStat ! temporary error status + character(ErrMsgLen) :: TmpErrMsg + + !---------------------------------------------------------------------------- + ! Initialize variables + !---------------------------------------------------------------------------- + + ErrStat = ErrID_None + ErrMsg = "" + + GF%WindFileFormat = 0 + GF%Periodic = .true. + GF%InterpTower = .true. + GF%AddMeanAfterInterp = .true. + + GF%DTime = InitInp%dx/InitInp%URef + GF%Rate = 1.0_ReKi/GF%DTime + + GF%NComp = 3 + GF%NYGrids = InitInp%ny + GF%NZGrids = InitInp%nz + GF%NTGrids = 0 + GF%NSteps = InitInp%nx + + GF%YHWid = 0.5_ReKi*InitInp%dy*(GF%NYGrids - 1) + GF%InvDY = 1.0/InitInp%dy + + GF%ZHWid = 0.5_ReKi*InitInp%dz*(GF%NZGrids - 1) + GF%InvDZ = 1.0_ReKi/InitInp%dz + + GF%MeanWS = InitInp%URef + GF%InvMWS = 1.0_ReKi/GF%MeanWS + + GF%RefHeight = InitInp%RefHt + GF%GridBase = GF%RefHeight - GF%ZHWid + + GF%InitXPosition = InitInp%XOffset + GF%TotalTime = GF%NSteps*InitInp%dx/GF%MeanWS + + GF%WindProfileType = InitInp%WindProfileType + GF%Z0 = InitInp%Z0 + GF%PLExp = InitInp%PLExp + + ScaleFactors = 0.0_ReKi + + !---------------------------------------------------------------------------- + ! Validate arguments + !---------------------------------------------------------------------------- + + if ((InitInp%ScaleMethod == ScaleMethod_Direct) .and. any(InitInp%SF(:GF%NComp) < 0.0_ReKi)) then + call SetErrStat(ErrID_Fatal, 'Turbulence scaling factors must not be negative.', ErrStat, ErrMsg, RoutineName) + elseif ((InitInp%ScaleMethod == ScaleMethod_StdDev) .and. any(InitInp%SigmaF(:GF%NComp) < 0.0_ReKi)) then + call SetErrStat(ErrID_Fatal, 'Turbulence standard deviations must not be negative.', ErrStat, ErrMsg, RoutineName) + else if ((InitInp%ScaleMethod /= 0) .and. (InitInp%ScaleMethod /= 1) .and. (InitInp%ScaleMethod /= 2)) then + call SetErrStat(ErrID_Fatal, 'Turbulence scaling method must be 0, 1, or 2.', ErrStat, ErrMsg, RoutineName) + else if (InitInp%RefHt < 0.0_ReKi .or. EqualRealNos(GF%RefHeight, 0.0_ReKi)) then + call SetErrStat(ErrID_Fatal, 'The grid reference height must be larger than 0.', ErrStat, ErrMsg, RoutineName) + else if (GF%MeanWS < 0.0_ReKi) then + call SetErrStat(ErrID_Fatal, 'The reference wind speed must not be negative.', ErrStat, ErrMsg, RoutineName) + else if (InitInp%nx < 1) then + call SetErrStat(ErrID_Fatal, 'Number of grid points in the X direction must be at least 1.', ErrStat, ErrMsg, RoutineName) + else if (InitInp%ny < 1) then + call SetErrStat(ErrID_Fatal, 'Number of grid points in the Y direction must be at least 1.', ErrStat, ErrMsg, RoutineName) + else if (InitInp%nz < 1) then + call SetErrStat(ErrID_Fatal, 'Number of grid points in the Z direction must be at least 1.', ErrStat, ErrMsg, RoutineName) + else if (InitInp%dx < 0.0_ReKi .or. EqualRealNos(InitInp%dx, 0.0_ReKi)) then + call SetErrStat(ErrID_Fatal, 'The grid spacing in the X direction must be larger than 0.', ErrStat, ErrMsg, RoutineName) + else if (InitInp%dy < 0.0_ReKi .or. EqualRealNos(InitInp%dy, 0.0_ReKi)) then + call SetErrStat(ErrID_Fatal, 'The grid spacing in the Y direction must be larger than 0.', ErrStat, ErrMsg, RoutineName) + else if (InitInp%dz < 0.0_ReKi .or. EqualRealNos(InitInp%dz, 0.0_ReKi)) then + call SetErrStat(ErrID_Fatal, 'The grid spacing in the Z direction must be larger than 0.', ErrStat, ErrMsg, RoutineName) + else if (GF%GridBase < 0.0_ReKi) then + call SetErrStat(ErrID_Severe, 'WARNING: The bottom of the grid is located at a height of '// & + trim(Num2LStr(GF%GridBase))//' meters, which is below the ground.'// & + ' Winds below the ground will be set to 0.', ErrStat, ErrMsg, RoutineName) + end if + if (ErrStat >= AbortErrLev) return + + !---------------------------------------------------------------------------- + ! Allocate storage for grid-field velocity data + !---------------------------------------------------------------------------- + + ! Allocate storage for grid-field velocity data + call AllocAry(GF%Vel, GF%NComp, GF%NYGrids, GF%NZGrids, GF%NSteps, & + 'grid-field velocity data', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Allocate storage for raw grid-field velocity for each time step + allocate (VelRaw(GF%NZGrids, GF%NYGrids), stat=TmpErrStat) + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, "error allocating grid-field time step velocity data", & + ErrStat, ErrMsg, RoutineName) + end if + if (ErrStat >= AbortErrLev) return + + !---------------------------------------------------------------------------- + ! Loop through files and read data + !---------------------------------------------------------------------------- + + ! Display message indicating that file is being read + call WrScr(NewLine//' Reading HAWC wind files with grids of '// & + TRIM(Num2LStr(GF%NSteps))//' x '//TRIM(Num2LStr(GF%NYGrids))//' x '//TRIM(Num2LStr(GF%NZGrids))//' points'// & + ' ('//TRIM(Num2LStr(GF%YHWid*2))//' m wide, '//TRIM(Num2LStr(GF%GridBase))//' m to '// & + TRIM(Num2LStr(GF%GridBase + GF%ZHWid*2))// & + ' m above ground) with a characteristic wind speed of '//TRIM(Num2LStr(GF%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, GF%NComp + + ! Open wind file for this component + call OpenBInpFile(WindFileUnit, InitInp%WindFileName(IC), TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Loop through time steps + do IX = 1, GF%NSteps + + ! Read file data for this timestep (Z(1:N),Y(N:1),C(1:3)) + read (WindFileUnit, IOSTAT=TmpErrStat) VelRaw + if (TmpErrStat /= 0) then + TmpErrMsg = ' Error reading binary data from "'//TRIM(InitInp%WindFileName(IC)) & + //'". I/O error '//TRIM(Num2LStr(TmpErrStat)) & + //' occurred at IX='//TRIM(Num2LStr(IX))//'.' + close (WindFileUnit) + call SetErrStat(ErrID_Fatal, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + + ! Reorganize raw data into grid-field array (reverse Y indices) + do IZ = 1, GF%NZGrids + ! Vel(NFFComp, NYGrids, NZGrids, NSteps) + ! VelRaw(NZGrids, NYGrids) + GF%Vel(IC, :, IZ, IX) = VelRaw(IZ, GF%NYGrids:1:-1) + end do + end do + + ! Close file + close (WindFileUnit) + + end do + + !---------------------------------------------------------------------------- + ! Scale turbulence + !---------------------------------------------------------------------------- + + select case (InitInp%ScaleMethod) + + case (ScaleMethod_None) ! No scaling + ScaleFactors = 1.0_ReKi + + case (ScaleMethod_Direct) ! Apply scale factors from file + ScaleFactors = InitInp%SF + + case (ScaleMethod_StdDev) ! Use scale factor to get requested sigma + + ! find the center point of the grid (if we don't have an odd number + ! of grid points, we'll pick the point closest to the center) + iz = ishft(InitInp%nz + 1, -1) ! integer divide by 2 + iy = ishft(InitInp%ny + 1, -1) ! integer divide by 2 + + ! Loop through components + do ic = 1, GF%NComp + + ! Mean of component for all time + vMean = sum(GF%Vel(ic, iy, iz, :))/InitInp%nx + + ! Sum of square of component value for all time + vSum2 = dot_product(GF%Vel(ic, iy, iz, :), GF%Vel(ic, iy, iz, :)) + + ! Standard deviation of component + ActualSigma = real(sqrt(abs(vSum2/InitInp%nx - vMean**2)), kind(ActualSigma)) + + ! If actual sigma is nearly zero, + if (EqualRealNos(ActualSigma, 0.0_ReKi)) then + ScaleFactors(ic) = 0.0_ReKi + if (.not. EqualRealNos(InitInp%SigmaF(ic), 0.0_ReKi)) then + call SetErrStat(ErrID_Fatal,"Computed standard deviation is zero; cannot scale to achieve target non-zero standard deviation.", ErrStat, ErrMsg, RoutineName ) + end if + else + ScaleFactors(ic) = InitInp%SigmaF(ic)/ActualSigma + end if + end do + end select + + ! Loop through components and apply scale factors + do ic = 1, GF%NComp + GF%Vel(ic, :, :, :) = real(ScaleFactors(ic)*GF%Vel(ic, :, :, :), SiKi) + end do + + !---------------------------------------------------------------------------- + ! Remove the U component mean wind speed + !---------------------------------------------------------------------------- + + ! If scaling method is not none, remove mean value of X component at each grid point + if (InitInp%ScaleMethod /= ScaleMethod_None) then + do iz = 1, GF%NZGrids + do iy = 1, GF%NYGrids + vMean = sum(GF%Vel(1, iy, iz, :))/GF%NSteps + GF%Vel(1, iy, iz, :) = real(GF%Vel(1, iy, iz, :) - vMean, SiKi) + end do + end do + end if + + !---------------------------------------------------------------------------- + ! Store wind file metadata + !---------------------------------------------------------------------------- + + call PopulateWindFileDatFromGridField(GF, InitInp%WindFileName(1), 5, .false., FileDat) + + !---------------------------------------------------------------------------- + ! Write the summary file + !---------------------------------------------------------------------------- + + if (SumFileUnit > 0) then + write (SumFileUnit, '(A)') + write (SumFileUnit, '(A)') 'HAWC wind type. Read by InflowWind sub-module IfW_FlowField' + + write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', GF%RefHeight + write (SumFileUnit, '(A34,G12.4)') ' Timestep (s): ', GF%DTime + write (SumFileUnit, '(A34,I12)') ' Number of timesteps: ', GF%NSteps + write (SumFileUnit, '(A34,G12.4)') ' Mean windspeed (m/s): ', GF%MeanWS + write (SumFileUnit, '(A)') ' Time range (s): [ '// & + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(GF%TotalTime))//' ]' + write (SumFileUnit, '(A)') ' X range (m): [ '// & + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(GF%TotalTime*GF%MeanWS))//' ]' + write (SumFileUnit, '(A)') ' Y range (m): [ '// & + TRIM(Num2LStr(-GF%YHWid))//' : '//TRIM(Num2LStr(GF%YHWid))//' ]' + write (SumFileUnit, '(A)') ' Z range (m): [ '// & + TRIM(Num2LStr(GF%GridBase))//' : '//TRIM(Num2LStr(GF%GridBase + GF%ZHWid*2.0))//' ]' + + write (SumFileUnit, '(A)') 'Scaling factors used:' + write (SumFileUnit, '(A)') ' u v w ' + write (SumFileUnit, '(A)') '---------- ---------- ----------' + write (SumFileUnit, '(F10.3,2x,F10.3,2x,F10.3)') ScaleFactors + end if + +end subroutine + +!> User_Init initializes a user defined wind field. +subroutine User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) + + type(UserInitInputType), intent(in) :: InitInp + integer(IntKi), intent(in) :: SumFileUnit + type(UserFieldType), intent(out) :: UF + type(WindFileDat), intent(out) :: FileDat + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + +end subroutine + +subroutine GridField_CalcAccel(GF, ErrStat, ErrMsg) + type(GridFieldType), intent(in) :: GF + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = "GridField_CalcAccel" + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + integer(IntKi) :: iy, iz, it + real(ReKi), allocatable :: time(:) + real(ReKi), allocatable :: vel(:) + + ! Allocate storage for time + call AllocAry(time, GF%NSteps, "storage for grid time", TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + + ! Allocate storage for velocity + call AllocAry(vel, GF%NSteps, "storage for grid time", TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + + ! Allocate storage for acceleration grid + call AllocAry(GF%Acc, GF%NComp, GF%NYGrids, GF%NZGrids, GF%NSteps, & + 'grid-field velocity data', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! If grid field includes tower grids, allocate storage for acceleration + if (GF%NTGrids > 0) then + call AllocAry(GF%VelTower, GF%NComp, GF%NTGrids, GF%NSteps, & + 'tower wind velocity data.', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + ! Generate time + do it = 1, GF%NSteps + ! time(i) = + end do + +end subroutine + +subroutine PopulateWindFileDatFromGridField(GridField, FileName, WindType, HasTower, FileDat) + + type(GridFieldType), intent(in) :: GridField + character(*), intent(in) :: FileName + integer(IntKi), intent(in) :: WindType + logical, intent(in) :: HasTower + type(WindFileDat), intent(out) :: FileDat + + FileDat%FileName = FileName + FileDat%WindType = WindType + FileDat%RefHt = GridField%RefHeight + FileDat%RefHt_Set = .true. + FileDat%DT = GridField%DTime + FileDat%NumTSteps = GridField%NSteps + FileDat%ConstantDT = .true. + + if (GridField%Periodic) then + FileDat%TRange = [0.0_ReKi, GridField%TotalTime] + FileDat%TRange_Limited = .false. + else ! Shift the time range to compensate for the shifting of the wind grid + FileDat%TRange = [0.0_ReKi, GridField%TotalTime] - GridField%InitXPosition*GridField%InvMWS + FileDat%TRange_Limited = .true. + end if + + FileDat%YRange = [-GridField%YHWid, GridField%YHWid] + FileDat%YRange_Limited = .true. ! Hard boundaries enforced in y-direction + + ! If has tower data + if (HasTower) then + FileDat%ZRange = [0.0_Reki, GridField%RefHeight + GridField%ZHWid] + else + FileDat%ZRange = [GridField%GridBase, GridField%GridBase + GridField%ZHWid*2.0] + end if + + FileDat%ZRange_Limited = .true. + FileDat%BinaryFormat = GridField%WindFileFormat + FileDat%IsBinary = .true. + FileDat%MWS = GridField%MeanWS + + FileDat%TI = 0.0_ReKi + FileDat%TI_listed = .false. + +end subroutine + +! subroutine Read_Bladed_Native(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) + +! ! Passed Variables: +! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters +! type(IfW_Interp_InitInputType), intent(inout) :: InitInp !< Initialization inputs +! type(IfW_Interp_InitOutputType), intent(out) :: InitOut !< Initialization outputs +! integer(IntKi), intent(in) :: WindFileUnit !< unit number for the wind file +! integer(IntKi), intent(in) :: SumFileUnit !< unit number for the summary file +! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) +! character(*), intent(out) :: ErrMsg !< message about the error encountered + +! ! Local Parameters: +! character(*), parameter :: RoutineName = "Read_Bladed_Native" + +! ! Local Variables: +! character(1024) :: WindFileName +! logical :: NativeFormat !< file is in native bladed format +! logical :: TowerFileExist !< tower file exists +! character(1024) :: BinFileName +! character(1024) :: PriPath +! character(1028) :: SumFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. +! character(1028) :: TwrFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. + +! integer(IntKi) :: ScaleMethod ! Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] +! real(ReKi) :: NatTI(3), TI ! Turbulence scaling factor for each direction [ScaleMethod=1] +! real(ReKi) :: SF(3) ! Turbulence scaling factor for each direction [ScaleMethod=1] +! real(ReKi) :: SigmaF(3) ! Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] + +! real(ReKi) :: FFXDelt, FFYDelt, FFZDelt +! real(ReKi) :: XOffset +! real(ReKi) :: UBar +! real(ReKi) :: ZCenter + +! logical :: CWise +! logical :: LHR ! Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) +! logical :: exists + +! integer(B2Ki) :: FileFormat +! integer(IntKi) :: TmpErrStat ! temporary error status +! character(ErrMsgLen) :: TmpErrMsg ! temporary error message + +! ! Wind file is specified directly in input file +! WindFileName = InitInp%WindFileNames(1) + +! ! No tower file is used +! TowerFileExist = .false. + +! ! Read the native bladed summary file +! call Read_Bladed_Native_Summary( & +! WindFileName, p%MeanFFWS, p%RefHt, InitOut%TI, InitOut%PropagationDir, & +! InitOut%VFlowAngle, BinFileName, p%PLExp, p%InitXPosition, ErrStat, ErrMsg) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) return + +! ! Binary file will be relative to the path where the primary input file is located. +! if (pathIsRelative(BinFileName)) then +! call GetPath(WindFileName, PriPath) +! BinFileName = TRIM(PriPath)//TRIM(BinFileName) +! end if + +! ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data +! if (InitInp%FixedWindFileRootName) then +! if (InitInp%TurbineID == 0) then +! ! .TRUE. for the FAST.Farm low-resolution domain +! BinFileName = TRIM(BinFileName)//TRIM(PathSep)//'Low' +! else +! ! FAST.Farm high-resolution domain(s) +! BinFileName = TRIM(BinFileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) +! end if +! end if + +! p%WindProfileType = WindProfileType_PL +! p%Periodic = .true. + +! InitInp%ScaleMethod = ScaleMethod_StdDev +! InitInp%SigmaF = InitOut%TI*p%MeanFFWS +! InitInp%SF = InitInp%SigmaF + +! InitInp%RefHt = p%RefHt +! InitInp%URef = p%MeanFFWS +! InitInp%WindProfileType = WindProfileType_PL + +! CWise = .false. +! ZCenter = p%RefHt +! TI = 100.0_ReKi +! UBar = 0.0_ReKi +! LHR = .true. + +! end subroutine + +! !> Read_Bladed reads the bladed full-field wind file. +! subroutine Read_Bladed_Binary(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) + +! ! Passed Variables: +! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters +! type(IfW_Interp_InitInputType), intent(inout) :: InitInp !< Initialization inputs +! type(IfW_Interp_InitOutputType), intent(out) :: InitOut !< Initialization outputs +! integer(IntKi), intent(in) :: WindFileUnit !< unit number for the wind file +! integer(IntKi), intent(in) :: SumFileUnit !< unit number for the summary file +! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) +! character(*), intent(out) :: ErrMsg !< message about the error encountered + +! ! Local Parameters: +! character(*), parameter :: RoutineName = "Read_Bladed_Binary" +! logical, parameter :: NativeFormat = .false. + +! ! Local Variables: +! character(1024) :: WindFileName +! logical :: TowerFileExist !< tower file exists +! character(1024) :: BinFileName +! character(1024) :: PriPath +! character(1028) :: SumFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. +! character(1028) :: TwrFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. + +! integer(IntKi) :: ScaleMethod ! Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] + +! real(ReKi) :: TI(3) ! Turbulence scaling factor for each direction [ScaleMethod=1] +! real(ReKi) :: SF(3) ! Turbulence scaling factor for each direction [ScaleMethod=1] +! real(ReKi) :: SigmaF(3) ! Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] + +! real(ReKi) :: XOffset +! real(ReKi) :: UBar +! real(ReKi) :: ZCenter + +! logical :: CWise +! logical :: LHR ! Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) +! logical :: exists + +! integer(IntKi) :: TmpErrStat ! temporary error status +! character(ErrMsgLen) :: TmpErrMsg ! temporary error message + +! !---------------------------------------------------------------------------- +! ! Initialize variables +! !---------------------------------------------------------------------------- + +! ErrStat = ErrID_None +! ErrMsg = "" + +! InitOut%PropagationDir = 0.0_ReKi +! InitOut%VFlowAngle = 0.0_ReKi +! BinFileName = InitInp%WindFileNames(1) + +! ! Create summary and tower file paths from bin file path +! call GetRoot(BinFileName, SumFile) +! TwrFile = TRIM(SumFile)//'.twr' +! SumFile = TRIM(SumFile)//'.sum' + +! ! Read the summary file to get necessary scaling information +! call Read_Bladed_TurbSim_Summary(WindFileUnit, SumFile, CWise, ZCenter, TI, UBar, & +! p%RefHt, p%Periodic, LHR, TmpErrStat, TmpErrMsg) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) return + +! ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data +! if (InitInp%FixedWindFileRootName) then +! if (InitInp%TurbineID == 0) then +! ! .TRUE. for the FAST.Farm low-resolution domain +! WindFileName = TRIM(WindFileName)//TRIM(PathSep)//'Low' +! else +! ! FAST.Farm high-resolution domain(s) +! WindFileName = TRIM(WindFileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) +! end if +! end if + +! WindFileName = TRIM(WindFileName)//'.wnd' + +! InitOut%PropagationDir = 0.0_ReKi +! InitOut%VFlowAngle = 0.0_ReKi +! BinFileName = WindFileName + +! !---------------------------------------------------------------------------- +! ! Write the summary file +! !---------------------------------------------------------------------------- + +! if (SumFileUnit > 0) then +! write (SumFileUnit, '(A)') +! write (SumFileUnit, '(A)') 'Bladed-style wind type. Read by InflowWind sub-module '// & +! TRIM(IfW_Interp_Ver%Name)//' '//TRIM(IfW_Interp_Ver%Ver) +! write (SumFileUnit, '(A)') TRIM(TmpErrMsg) +! write (SumFileUnit, '(A)') ' FileName: '//TRIM(InitInp%WindFileNames(1)) +! write (SumFileUnit, '(A34,I3)') ' Binary file format id: ', p%WindFileFormat +! write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', p%RefHt +! write (SumFileUnit, '(A34,G12.4)') ' Timestep (s): ', p%FFDTime +! write (SumFileUnit, '(A34,I12)') ' Number of timesteps: ', p%NSteps +! write (SumFileUnit, '(A34,G12.4)') ' Mean windspeed (m/s): ', p%MeanFFWS +! write (SumFileUnit, '(A)') ' Characteristic TI: [ '// & +! TRIM(Num2LStr(TI(1)))//', '//TRIM(Num2LStr(TI(2)))//', '//TRIM(Num2LStr(TI(3)))//' ] ' +! write (SumFileUnit, '(A34,L1)') ' Windfile is periodic: ', p%Periodic +! write (SumFileUnit, '(A34,L1)') ' Windfile includes tower: ', p%NTGrids > 0 + +! if (p%Periodic) then +! write (SumFileUnit, '(A)') ' Time range (s): [ '// & +! TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(p%TotalTime))//' ]' +! else ! Shift the time range to compensate for the shifting of the wind grid +! write (SumFileUnit, '(A)') ' Time range (s): [ '// & +! TRIM(Num2LStr(-p%InitXPosition*p%InvMFFWS))//' : '// & +! TRIM(Num2LStr(p%TotalTime - p%InitXPosition*p%InvMFFWS))//' ]' +! end if + +! write (SumFileUnit, '(A)') ' Y range (m): [ '// & +! TRIM(Num2LStr(-p%FFYHWid))//' : '//TRIM(Num2LStr(p%FFYHWid))//' ]' + +! if (p%NTGrids > 0) then +! write (SumFileUnit, '(A)') ' Z range (m): [ '// & +! TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(p%RefHt + p%FFZHWid))//' ]' +! else +! write (SumFileUnit, '(A)') ' Z range (m): [ '// & +! TRIM(Num2LStr(p%RefHt - p%FFZHWid))//' : '//TRIM(Num2LStr(p%RefHt + p%FFZHWid))//' ]' +! end if + +! end if + +! end subroutine + +! subroutine Read_Bladed_Wind_File(p, WindFileUnit, BinFileName, NativeFormat, UBar, ZCenter, TI, ErrStat, ErrMsg) + +! ! Passed Variables: +! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters +! integer(IntKi), intent(in) :: WindFileUnit !< unit number for the wind file +! character(*), intent(in) :: BinFileName +! logical, intent(in) :: NativeFormat +! real(ReKi), intent(in) :: UBar +! real(ReKi), intent(in) :: ZCenter +! real(ReKi), intent(inout) :: TI(3) +! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) +! character(*), intent(out) :: ErrMsg !< message about the error encountered + +! ! Local Parameters: +! character(*), parameter :: RoutineName = "Read_Bladed_Wind_File" + +! ! Local Variables: +! integer(B2Ki) :: FileFormat +! real(ReKi) :: FFXDelt, FFYDelt, FFZDelt +! real(ReKi) :: BinTI(3) ! Turbulence scaling factor for each direction [ScaleMethod=1] +! integer(IntKi) :: TmpErrStat ! temporary error status +! character(ErrMsgLen) :: TmpErrMsg ! temporary error message + +! !---------------------------------------------------------------------------- +! ! Open the binary file and read contents +! !---------------------------------------------------------------------------- + +! ! Open the wind file +! call OpenBInpFile(WindFileUnit, TRIM(BinFileName), TmpErrStat, TmpErrMsg) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) return + +! ! Read the first binary integer from the file to get info on the type. +! ! Cannot use library read routines since this is a 2-byte integer. +! read (WindFileUnit, IOSTAT=TmpErrStat) FileFormat +! if (TmpErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading first binary integer from file "' & +! //TRIM(BinFileName)//'."', ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Save file format in parameters struct +! p%WindFileFormat = FileFormat + +! ! Read file headers +! select case (p%WindFileFormat) +! case (-1, -2, -3) +! call Read_Bladed_FF_Header0(p, WindFileUnit, NativeFormat, FFXDelt, FFYDelt, FFZDelt, TmpErrStat, TmpErrMsg) +! case (-99) +! call Read_Bladed_FF_Header1(p, WindFileUnit, NativeFormat, BinTI, FFXDelt, FFYDelt, FFZDelt, TmpErrStat, TmpErrMsg) +! where (BinTI > 0) TI = BinTI +! case default +! call SetErrStat(ErrID_Fatal, ' This is not a bladed-style binary wind file (binary format identifier: '// & +! TRIM(Num2LStr(p%WindFileFormat))//'. This might be a TurbSim binary wind file.', & +! ErrStat, ErrMsg, RoutineName) +! end select +! if (ErrStat >= AbortErrLev) return + +! ! If not native format and mean wind speed is different from summary file +! if ((.not. NativeFormat) .and. (ABS(UBar - p%MeanFFWS) > 0.1)) then +! call SetErrStat(ErrID_Fatal, ' Error: Incompatible mean hub-height wind speeds in FF wind files. '// & +! '(Check that the .sum and .wnd files were generated together.)', ErrStat, ErrMsg, RoutineName) +! close (WindFileUnit) +! return +! end if + +! ! Calculate the height of the bottom of the grid (meters), error if less than zero +! p%GridBase = ZCenter - p%FFZHWid +! if (p%GridBase < 0.0_ReKi) then +! call SetErrStat(ErrID_Severe, 'WARNING: The bottom of the grid is located at a height of '// & +! TRIM(Num2LStr(p%GridBase))//' meters, which is below the ground.'// & +! ' Winds below the ground will be set to 0.', ErrStat, ErrMsg, RoutineName) +! end if + +! ! Read binary grid data +! call Read_Bladed_Grids(p, WindFileUnit, LHR, TI, CWise, NativeFormat, p, TmpErrStat, TmpErrMsg) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! close (WindFileUnit) +! if (ErrStat >= AbortErrLev) return + +! !---------------------------------------------------------------------------- +! ! Read tower data if requested +! !---------------------------------------------------------------------------- + +! ! If a tower file was specified +! if (TowerFileExist) then + +! inquire (FILE=TRIM(TwrFile), EXIST=Exists) + +! ! Double check that the tower file exists and read it. If it was requested but doesn't exist, +! ! throw fatal error and exit. +! if (Exists) then +! call Read_Bladed_Tower() +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) then +! close (WindFileUnit) +! return +! end if +! else +! call SetErrStat(ErrID_Fatal, ' Tower file '//TRIM(TwrFile)//' specified for Bladed full-field '// & +! 'wind files does not exist.', ErrStat, ErrMsg, RoutineName) +! close (WindFileUnit) +! return +! end if +! else +! p%NTGrids = 0 +! end if + +! ! Report native turbulence intensities in percent +! if (NativeFormat) TI = TI*100.0_ReKi + +! end subroutine + +! !> Read_Bladed_TurbSim_Summary reads the summary file generated by TurbSim +! !! to get the normalizing parameters needed to read the bladed binary file +! !! which was genered by TurbSim. +! subroutine Read_Bladed_TurbSim_Summary(WindFileUnit, FileName, CWise, ZCenter, TI, UBar, RefHt, Periodic, LHR, ErrStat, ErrMsg) + +! integer(IntKi), intent(IN) :: WindFileUnit !< unit number for the file to open +! character(*), intent(IN) :: FileName !< name of the summary file +! logical, intent(OUT) :: CWise !< rotation (for reading the order of the binary data) +! real(ReKi), intent(OUT) :: ZCenter !< the height at the center of the grid +! real(ReKi), intent(OUT) :: TI(3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI +! real(ReKi), intent(OUT) :: UBar !< mean (advection) wind speed +! real(ReKi), intent(OUT) :: RefHt !< Reference height +! logical, intent(OUT) :: Periodic !< rotation (for reading the order of the binary data) +! logical, intent(OUT) :: LHR !< Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) +! integer(IntKi), intent(OUT) :: ErrStat !< returns 0 if no error encountered in the subroutine +! character(*), intent(OUT) :: ErrMsg !< holds the error messages + +! character(*), parameter :: RoutineName = "Read_Bladed_TurbSim_Summary" + +! real(ReKi) :: ZGOffset ! The vertical offset of the turbine on rectangular grid (allows turbulence not centered on turbine hub) +! integer(IntKi) :: I, J ! Counters +! character(1024) :: Line ! temporary storage for reading a line from the file +! integer(IntKi) :: ContentSize ! summary file size +! character(:), allocatable :: FileContents ! summary file contents +! integer(IntKi) :: TmpErrStat ! temporary error status +! character(ErrMsgLen) :: TmpErrMsg ! temporary error message + +! !------------------------------------------------------------------------- +! ! Initialize variables +! !------------------------------------------------------------------------- + +! ErrStat = ErrID_None +! ErrMsg = '' + +! !------------------------------------------------------------------------- +! ! Read summary file contents +! !------------------------------------------------------------------------- + +! call OpenBInpFile(WindFileUnit, FileName, TmpErrStat, TmpErrMsg) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) return + +! inquire (WindFileUnit, size=ContentSize) +! allocate (character(ContentSize) :: FileContents) +! read (WindFileUnit, IOSTAT=TmpErrStat) FileContents +! close (WindFileUnit) + +! if (TmpErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading TurbSim summary file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Convert file contents to uppercase +! call Conv2UC(FileContents) + +! ! Find 'CLOCKWISE' in file +! i = index(FileContents, 'CLOCKWISE') +! if (i > 0) then + +! ! Find beginning of line where clockwise appears +! j = index(FileContents(:i), NewLine, back=.true.) + 1 + +! ! Get line with leading spaces removed +! line = adjustl(FileContents(j:i)) + +! ! Get value from beginning of line +! select case (line(1:1)) +! case ("T", "Y") +! CWise = .true. +! case ("F", "N") +! CWise = .false. +! end select +! else +! CWise = .false. +! end if + +! ! Find 'HUB HEIGHT' or 'ZHUB' in file +! i = index(FileContents, 'HUB HEIGHT') +! if (i == 0) i = index(FileContents, 'ZHUB') +! if (i == 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading hub height from FF summary file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Find beginning of line where 'HUB HEIGHT' or 'ZHUB' occur +! j = index(FileContents(:i), NewLine, back=.true.) + 1 + +! ! Read value from line +! read (FileContents(j:), *, IOSTAT=TmpErrStat) RefHt +! if (TmpErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading hub height from FF summary file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Find the mean speed +! i = index(FileContents, 'UBAR') +! if (i == 0) then +! call SetErrStat(ErrID_Fatal, ' Error find UBar in FF summary file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Get index of next equal sign +! i = index(FileContents(i:), '=') + i + 1 +! read (FileContents(i:), *, IOSTAT=TmpErrStat) UBar +! if (TmpErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading UBar from FF summary file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Read turbulence intensities on lines after mean speed +! do j = 1, 3 +! i = INDEX(FileContents(i:), '=') + i + 1 +! read (FileContents(i:), *, IOSTAT=TmpErrStat) TI(j) +! if (TmpErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading TI('//TRIM(Num2LStr(j))// & +! ') from FF summary file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if +! end do + +! ! Find the grid "HEIGHT OFFSET" (optional, default to zero) +! i = index(FileContents, "HEIGHT OFFSET") +! if (i > 0) then +! i = INDEX(FileContents(i:), '=') + i + 1 +! read (FileContents(i:), *, IOSTAT=TmpErrStat) ZGOffset +! if (TmpErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading height offset from FF summary file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if +! else +! ZGOffset = 0.0_ReKi +! end if + +! ! Calculate the height of the grid center +! ZCenter = RefHt - ZGOffset + +! ! If "PERIODIC" is in summary, then file is periodic +! Periodic = index(FileContents(i:), 'PERIODIC') > 0 + +! ! If "BLADED LEFT-HAND RULE" is in file, then file uses LHR +! LHR = index(FileContents(i:), 'BLADED LEFT-HAND RULE') > 0 + +! end subroutine Read_Bladed_TurbSim_Summary + +! !> This subroutine reads the text summary file to get normalizing parameters, the location of the +! !! grid, and the direction the grid was written to the binary file +! subroutine Read_Bladed_Native_Summary(SumFileName, UBar, RefHt, TI, PropagationDir, & +! VFlowAngle, BinFileName, PLExp, XOffset, ErrStat, ErrMsg) + +! character(*), intent(in) :: SumFileName !< Summary file name +! real(ReKi), intent(out) :: UBar +! real(ReKi), intent(out) :: RefHt +! real(ReKi), intent(out) :: TI(3) ! turbulenc +! real(ReKi), intent(out) :: PropagationDir +! real(ReKi), intent(out) :: VFlowAngle +! character(1024), intent(out) :: BinFileName +! real(ReKi), intent(out) :: PLExp +! real(ReKi), intent(out) :: XOffset +! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) +! character(*), intent(out) :: ErrMsg !< message about the error encountered + +! character(*), parameter :: RoutineName = "Read_Bladed_Native_Summary" +! integer(IntKi), parameter :: UnEc = -1 ! echo file unit number (set to something else > 0 for debugging) + +! type(FileInfoType) :: FileInfo ! The derived type for holding the file information. +! integer(IntKi) :: CurLine ! Current line to parse in FileInfo data structure +! integer(IntKi) :: TmpErrStat ! temporary error status +! character(ErrMsgLen) :: TmpErrMsg ! temporary error message + +! ! Initialize error variables +! ErrStat = ErrID_None +! ErrMsg = '' + +! !------------------------------------------------------------------------- +! ! Open and read the summary file; store data in FileInfo structure. +! !------------------------------------------------------------------------- + +! call ProcessComFile(SumFileName, FileInfo, TmpErrStat, TmpErrMsg) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) return + +! !------------------------------------------------------------------------- +! ! Process the lines stored in FileInfo +! !------------------------------------------------------------------------- + +! CurLine = 1 + +! call ParseVar(FileInfo, CurLine, 'UBAR', UBar, TmpErrStat, TmpErrMsg, UnEc) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + +! call ParseVar(FileInfo, CurLine, 'REFHT', RefHt, TmpErrStat, TmpErrMsg, UnEc) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + +! call ParseVar(FileInfo, CurLine, 'TI', TI(1), TmpErrStat, TmpErrMsg, UnEc) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + +! call ParseVar(FileInfo, CurLine, 'TI_V', TI(2), TmpErrStat, TmpErrMsg, UnEc) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + +! call ParseVar(FileInfo, CurLine, 'TI_W', TI(3), TmpErrStat, TmpErrMsg, UnEc) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + +! call ParseVar(FileInfo, CurLine, 'WDIR', PropagationDir, TmpErrStat, TmpErrMsg, UnEc) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! PropagationDir = R2D*PropagationDir + +! call ParseVar(FileInfo, CurLine, 'FLINC', VFlowAngle, TmpErrStat, TmpErrMsg, UnEc) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! VFlowAngle = R2D*VFlowAngle ! convert to degrees + +! call ParseVar(FileInfo, CurLine, 'WINDF', BinFileName, TmpErrStat, TmpErrMsg, UnEc) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + +! call ParseVar(FileInfo, CurLine, 'WSHEAR', PLExp, TmpErrStat, TmpErrMsg, UnEc) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + +! if (ErrStat >= AbortErrLev) return + +! call ParseVar(FileInfo, CurLine, 'XOffset', XOffset, TmpErrStat, TmpErrMsg, UnEc) +! if (TmpErrStat /= ErrID_None) then +! XOffset = 0.0_ReKi ! this will be the default if offset is not in the file +! end if + +! end subroutine Read_Bladed_Native_Summary + +! subroutine Read_Bladed_FF_Header0(p, WindFileUnit, NativeFormat, FFXDelt, FFYDelt, FFZDelt, ErrStat, ErrMsg) + +! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters +! integer(IntKi), intent(IN) :: WindFileUnit !< unit number for the file to open +! logical, intent(in) :: NativeFormat +! real(ReKi), intent(out) :: FFXDelt +! real(ReKi), intent(out) :: FFYDelt +! real(ReKi), intent(out) :: FFZDelt +! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) +! character(*), intent(out) :: ErrMsg !< message about the error encountered + +! character(*), parameter :: RoutineName = "Read_Bladed_FF_Header0" + +! integer(IntKi) :: TmpErrStat ! temporary error status +! character(ErrMsgLen) :: TmpErrMsg ! temporary error message + +! type :: HeaderType +! integer(B2Ki) :: DeltaZ, DeltaY, DeltaX +! integer(B2Ki) :: NumTimeStepsHalf, MFFWS10 +! integer(B2Ki) :: zLu, yLu, xLu, dummy, rnd +! integer(B2Ki) :: nz1000, ny1000 +! end type + +! type(HeaderType) :: header +! integer(B2Ki) :: dummy(6) + +! ! Read header +! read (WindFileUnit, IOSTAT=ErrStat) header +! if (ErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading header 0 from binary FF file.', ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Number of full-field velocity components +! p%NFFComp = -1*p%WindFileFormat + +! ! Grid Deltas +! FFZDelt = 0.001_ReKi*real(header%DeltaZ, ReKi) +! p%InvFFZD = 1.0_ReKi/FFZDelt +! FFYDelt = 0.001_ReKi*real(header%DeltaY, ReKi) +! p%InvFFYD = 1.0_ReKi/FFYDelt +! FFXDelt = 0.001_ReKi*real(header%DeltaX, ReKi) + +! ! Number of time steps +! p%NSteps = 2*header%NumTimeStepsHalf + +! ! Mean full field wind speed +! if (.not. NativeFormat) p%MeanFFWS = 0.1*header%MFFWS10 +! p%InvMFFWS = 1.0/p%MeanFFWS +! p%FFDTime = FFXDelt/p%MeanFFWS +! p%FFRate = 1.0/p%FFDTime + +! ! Z and Y Grid size +! p%NZGrids = header%nz1000/1000 +! p%FFZHWid = 0.5*FFZDelt*(p%NZGrids - 1) +! p%NYGrids = header%ny1000/1000 +! p%FFYHWid = 0.5*FFYDelt*(p%NYGrids - 1) + +! ! Read dummy variables (zLv, yLv, xLv, zLw, yLw, xLw) +! if (p%NFFComp == 3) then +! read (WindFileUnit, IOSTAT=TmpErrStat) dummy +! if (TmpErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading header 0 from binary FF file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if +! end if + +! end subroutine Read_Bladed_FF_Header0 + +! subroutine Read_Bladed_FF_Header1(p, WindFileUnit, NativeFormat, TI, FFXDelt, FFYDelt, FFZDelt, ErrStat, ErrMsg) + +! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters +! integer(IntKi), intent(IN) :: WindFileUnit !< unit number for the file to open +! logical, intent(in) :: NativeFormat +! real(ReKi), intent(out) :: TI(3) !< turbulence intensities +! real(ReKi), intent(out) :: FFXDelt +! real(ReKi), intent(out) :: FFYDelt +! real(ReKi), intent(out) :: FFZDelt +! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) +! character(*), intent(out) :: ErrMsg !< message about the error encountered + +! character(*), parameter :: RoutineName = "Read_Bladed_FF_Header1" + +! integer(B2Ki) :: TurbType +! integer(IntKi) :: i + +! type :: Turb4Type +! integer(B4Ki) :: NComp +! real(SiKi) :: Latitude, RoughLen, RefHeight, TurbInt(3) +! end type + +! type :: Turb78Type +! integer(B4Ki) :: HeaderSize, NComp +! end type + +! type :: Turb7Type +! real(SiKi) :: CoherenceDecay, CoherenceScale +! end type + +! type :: Turb8Type +! real(SiKi) :: dummy1(6) +! integer(B4Ki) :: dummy2(3) +! real(SiKi) :: dummy3(2) +! integer(B4Ki) :: dummy4(3) +! real(SiKi) :: dummy5(2) +! end type + +! type :: Sub1Type +! real(SiKi) :: DeltaZ, DeltaY, DeltaX +! integer(B4Ki) :: NumTimeStepsHalf +! real(SiKi) :: MFFWS, zLu, yLu, xLu +! integer(B4Ki) :: dummy, rnd, nz, ny +! end type + +! type :: Sub2Type +! real(SiKi) :: zLv, yLv, xLv, zLw, yLw, xLw +! end type + +! type(Turb4Type) :: Turb4 +! type(Turb78Type) :: Turb78 +! type(Sub1Type) :: Sub1 +! type(Sub2Type) :: Sub2 +! type(Turb7Type) :: Turb7 +! type(Turb8Type) :: Turb8 + +! ! Read turbulence type (int16) +! read (WindFileUnit, IOSTAT=ErrStat) TurbType +! if (ErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading header 0 from binary FF file.', ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Switch based on turbulence type +! select case (TurbType) + +! case (1, 2) ! 1-component Von Karman (1) or Kaimal (2) +! p%NFFComp = 1 + +! case (3, 5) ! 3-component Von Karman (3) or IEC-2 Kaimal (5) +! p%NFFComp = 3 + +! case (4) ! Improved Von Karman +! read (WindFileUnit, IOSTAT=ErrStat) Turb4 +! if (ErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading header for TurbType=4 from binary FF file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Number of components (should be 3) +! p%NFFComp = Turb4%NComp + +! ! Turbulence intensity +! where (Turb4%TurbInt > 0) TI = Turb4%TurbInt + +! case (7, 8) ! General Kaimal (7) or Mann model (8) +! read (WindFileUnit, IOSTAT=ErrStat) Turb78 +! if (ErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading header for TurbType=7,8 from binary FF file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Number of components +! p%NFFComp = Turb78%NComp + +! case default ! Unknown turbulence type +! call SetErrStat(ErrID_Warn, ' InflowWind does not recognize the full-field turbulence file type ='// & +! TRIM(Num2LStr(int(TurbType, IntKi)))//'.', ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) return +! end select + +! ! Read header sub 1 +! read (WindFileUnit, IOSTAT=ErrStat) Sub1 +! if (ErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading header for Sub1 from binary FF file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! FFZDelt = Sub1%DeltaZ +! p%InvFFZD = 1/FFZDelt +! FFYDelt = Sub1%DeltaY +! p%InvFFYD = 1/FFYDelt +! FFXDelt = Sub1%DeltaX + +! if (.not. NativeFormat) p%MeanFFWS = Sub1%MFFWS +! p%InvMFFWS = 1.0/p%MeanFFWS +! p%FFDTime = FFXDelt/p%MeanFFWS +! p%FFRate = 1.0/p%FFDTime + +! p%NZGrids = Sub1%nz +! p%FFZHWid = 0.5*FFZDelt*(p%NZGrids - 1) +! p%NYGrids = Sub1%ny +! p%FFYHWid = 0.5*FFYDelt*(p%NYGrids - 1) + +! if (p%NFFComp == 3) then +! read (WindFileUnit, IOSTAT=ErrStat) Sub2 +! if (ErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading header for Sub2 from binary FF file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if +! end if + +! ! Read additional parameters based on turbulence type +! select case (TurbType) +! case (7) +! read (WindFileUnit, IOSTAT=ErrStat) Turb7 +! if (ErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading header for Turb7 from binary FF file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if +! case (8) +! read (WindFileUnit, IOSTAT=ErrStat) Turb8 +! if (ErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading header for Turb8 from binary FF file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if +! end select + +! end subroutine + +! subroutine Read_Bladed_Grids(p, WindFileUnit, LHR, TI, NativeFormat, CWise, FFXDelt, FFYDelt, FFZDelt, ErrStat, ErrMsg) + +! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters +! integer(IntKi), intent(IN) :: WindFileUnit !< unit number for the file to open +! logical, intent(in) :: LHR +! real(ReKi), intent(out) :: TI(3) !< turbulence intensities +! logical, intent(in) :: NativeFormat +! logical, intent(in) :: Cwise +! real(ReKi), intent(out) :: FFXDelt +! real(ReKi), intent(out) :: FFYDelt +! real(ReKi), intent(out) :: FFZDelt +! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) +! character(*), intent(out) :: ErrMsg !< message about the error encountered + +! character(*), parameter :: RoutineName = "Read_Bladed_Grids" + +! real(ReKi) :: FF_Scale(3) !< used for "un-normalizing" the data +! real(ReKi) :: FF_Offset(3) !< used for "un-normalizing" the data +! integer(B2Ki), allocatable :: raw_ff(:, :, :) +! integer(IntKi) :: CFirst, CLast, CStep +! integer(IntKi) :: IC, IT +! integer(IntKi) :: TmpErrStat ! temporary error status +! character(ErrMsgLen) :: TmpErrMsg ! temporary error message + +! ! Initialize error variables +! ErrMsg = "" +! ErrStat = ErrID_None + +! ! Calculate wind scale and offset +! if (NativeFormat) then +! FF_Scale = 0.001_ReKi +! FF_Offset = 0.0_ReKi +! else +! FF_Scale = 0.001_ReKi*p%MeanFFWS*TI/100.0_ReKi +! FF_Offset = (/p%MeanFFWS, 0.0_ReKi, 0.0_ReKi/) +! end if + +! ! Bladed convention has positive V pointed along negative Y +! if (LHR) FF_Scale(2) = -FF_Scale(2) ! left-hand rule + +! ! Print message to inform user that wind file is being read (may take a while). +! call WrScr(NewLine//' Reading a '//TRIM(Num2LStr(p%NYGrids))// & +! 'x'//TRIM(Num2LStr(p%NZGrids))// & +! ' grid ('//TRIM(Num2LStr(p%FFYHWid*2))// & +! ' m wide, '//TRIM(Num2LStr(p%GridBase))// & +! ' m to '//TRIM(Num2LStr(p%GridBase + p%FFZHWid*2))// & +! ' m above ground) with a characteristic wind speed of '// & +! TRIM(Num2LStr(p%MeanFFWS))//' m/s. ') + +! !------------------------------------------------------------------------- +! ! Allocate space for the FF array +! !------------------------------------------------------------------------- + +! ! Add another step, just in case there is an odd number of steps. +! p%NSteps = p%NSteps + 1 + +! ! Allocate wind data +! call Allocate_FF_Wind_Data(p%FFData, p%NSteps, p%NFFComp, & +! p%NYGrids, p%NZGrids, TmpErrStat, TmpErrMsg) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) return + +! !------------------------------------------------------------------------- +! ! Initialize the data and set column indexing to account for +! ! direction of turbine rotation (CWise) +! !------------------------------------------------------------------------- + +! ! Initialize entire array +! p%FFData(:, :, :, :) = 0.0_SiKi ! we may have only one component + +! if (CWise) then +! CFirst = p%NYGrids +! CLast = 1 +! CStep = -1 +! else +! CFirst = 1 +! CLast = p%NYGrids +! CStep = 1 +! end if + +! !---------------------------------------------------------------------------- +! ! Loop through all the time steps, reading the data and converting to m/s +! !---------------------------------------------------------------------------- + +! ! Allocate raw full-field array to hold grid data for single time step +! allocate (raw_ff(p%NFFComp, p%NYGrids, p%NZGrids)) + +! ! Loop through time steps +! do IT = 1, p%NSteps + +! ! Read raw data (NFFComp,NYGrids,NZGrids) +! read (WindFileUnit, IOStat=TmpErrStat) raw_ff + +! ! If there was an error +! if (TmpErrStat /= 0) then + +! ! If there really were an even number of steps +! if (IT == p%NSteps) then +! p%NSteps = p%NSteps - 1 +! ErrStat = 0 +! exit +! end if + +! ! Error reading file +! call SetErrStat(ErrID_Fatal, ' Error reading binary data file. '// & +! ', it = '//TRIM(Num2LStr(it))// & +! ', nsteps = '//TRIM(Num2LStr(p%NSteps)), ErrStat, ErrMsg, RoutineName) +! return +! end if + +! ! Scale wind components and store in array +! do IC = 1, p%NFFComp +! p%FFData(IC, :, :, IT) = real(FF_Offset(IC) + FF_Scale(IC)*raw_ff(IC, CFirst:CLast:CStep, :), SiKi) +! end do + +! end do + +! if (p%Periodic) then +! call WrScr(NewLine//' Processed '//TRIM(Num2LStr(p%NSteps))//' time steps of '// & +! TRIM(Num2LStr(p%FFRate))//'-Hz full-field data (period of '// & +! TRIM(Num2LStr(p%FFDTime*p%NSteps))//' seconds).') + +! else +! call WrScr(NewLine//' Processed '//TRIM(Num2LStr(p%NSteps))//' time steps of '// & +! TRIM(Num2LStr(p%FFRate))//'-Hz full-field data ('// & +! TRIM(Num2LStr(p%FFDTime*(p%NSteps - 1)))//' seconds).') +! end if + +! end subroutine Read_Bladed_Grids + +! !> This subroutine reads the binary tower file that corresponds with the +! !! Bladed-style FF binary file. The FF grid must be read before this subroutine +! !! is called! (many checks are made to ensure the files belong together) +! subroutine Read_Bladed_Tower(p, ErrStat, ErrMsg) + +! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters +! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) +! character(*), intent(out) :: ErrMsg !< message about the error encountered + +! type :: HeaderType +! real(SiKi) :: dz, dx, Zmax +! integer(B4Ki) :: NumOutSteps, NumZ +! real(SiKi) :: UHub, TI(3) +! end type + +! real(ReKi), parameter :: TOL = 1E-4 ! tolerence for wind file comparisons +! real(ReKi), parameter :: FF_Offset(3) = (/1.0, 0.0, 0.0/) ! used for "un-normalizing" the data + +! integer(IntKi) :: IC, IT ! loop counters +! integer(B2Ki), allocatable :: raw_twr(:, :) ! holds tower velocity for one timestep + +! type(HeaderType) :: header + +! !------------------------------------------------------------------------- +! ! Initialization +! !------------------------------------------------------------------------- + +! ErrMsg = '' +! ErrStat = ErrID_None + +! p%NTGrids = 0 + +! if (p%NFFComp /= 3) then +! call SetErrStat(ErrID_Fatal, ' Error: Tower binary files require 3 wind components.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! !------------------------------------------------------------------------- +! ! Open the file +! !------------------------------------------------------------------------- + +! call OpenBInpFile(WindFileUnit, TwrFile, TmpErrStat, TmpErrMsg) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) return + +! !------------------------------------------------------------------------- +! ! Read the header information and check that it's compatible with the FF Bladed-style binary +! ! parameters already read. +! !------------------------------------------------------------------------- + +! read (WindFileUnit, IOSTAT=TmpErrStat) header +! if (TmpErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, & +! ' Error reading header of the binary tower file "' & +! //TRIM(TwrFile)//'."', ErrStat, ErrMsg, RoutineName) +! return +! end if + +! if (ABS(header%dz*p%InvFFZD - 1) > TOL) then +! call SetErrStat(ErrID_Fatal, & +! ' Resolution in the FF binary file does not match the tower file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! if (ABS(header%dx*p%InvMFFWS/p%FFDTime - 1) > TOL) then +! call SetErrStat(ErrID_Fatal, & +! ' Time resolution in the FF binary file does not match the tower file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! if (ABS(header%Zmax/p%GridBase - 1) > TOL) then +! call SetErrStat(ErrID_Fatal, & +! ' Height in the FF binary file does not match the tower file "' & +! //TRIM(TwrFile)//'."', ErrStat, ErrMsg, RoutineName) +! return +! end if + +! if (header%NumOutSteps /= p%NSteps) then +! call SetErrStat(ErrID_Fatal, & +! ' Number of time steps in the FF binary file does not match the tower file.', & +! ErrStat, ErrMsg, RoutineName) +! return +! end if + +! p%NTGrids = header%NumZ + +! if (ABS(header%UHub*p%InvMFFWS - 1) > TOL) then +! call SetErrStat(ErrID_Fatal, & +! ' Mean wind speed in the FF binary file does not match the tower file.', & +! ErrStat, ErrMsg, RoutineName) +! p%NTGrids = 0 +! return +! end if + +! ! If number of tower grids is zero, close file and return +! if (p%NTGrids == 0) then +! close (WindFileUnit) +! return +! end if + +! !------------------------------------------------------------------------- +! ! Allocate arrays for the tower points +! !------------------------------------------------------------------------- + +! call Allocate_FF_Tower_Data(p%Tower, p%NSteps, p%NFFComp, & +! p%NTGrids, TmpErrStat, TmpErrMsg) +! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) +! if (ErrStat >= AbortErrLev) return + +! !------------------------------------------------------------------------- +! ! Read the 16-bit time-series data and scale it to 32-bit reals +! !------------------------------------------------------------------------- + +! ! Loop through time. +! do IT = 1, p%NSteps + +! ! Read normalized wind-component, INT(2) for this timestep +! read (WindFileUnit, IOSTAT=TmpErrStat) raw_twr +! if (TmpErrStat /= 0) then +! call SetErrStat(ErrID_Fatal, ' Error reading binary tower data file. it = '//TRIM(Num2LStr(it))// & +! ', nsteps = '//TRIM(Num2LStr(p%NSteps)), ErrStat, ErrMsg, RoutineName) +! p%NTGrids = 0 +! return +! end if + +! ! Convert wind components to m/s +! do IC = 1, p%NFFComp +! p%Tower(IC, :, IT) = real(p%MeanFFWS*(FF_Offset(IC) + 0.00001*TI(IC)*raw_twr(IC, :)), SiKi) +! end do +! end do + +! !------------------------------------------------------------------------- +! ! Close the file +! !------------------------------------------------------------------------- + +! close (WindFileUnit) + +! TmpErrMsg = ' Processed '//TRIM(Num2LStr(p%NSteps))//' time steps of '// & +! TRIM(Num2LStr(p%NTGrids))//'x1 tower data grids.' + +! call WrScr(NewLine//TRIM(TmpErrMsg)) + +! end subroutine Read_Bladed_Tower + +end module IfW_FlowField diff --git a/modules/inflowwind/src/IfW_FlowField.txt b/modules/inflowwind/src/IfW_FlowField.txt new file mode 100644 index 0000000000..8073f4a7b5 --- /dev/null +++ b/modules/inflowwind/src/IfW_FlowField.txt @@ -0,0 +1,95 @@ +#---------------------------------------------------------------------------------------------------------------------------------- +# Registry for IfW_Interp, creates MODULE IfW_Interp_Types +# Module IfW_Interp_Types contains all of the user-defined types needed in IfW_FF. It also contains copy, destroy, pack, and +# unpack routines associated with each defined data types. +#---------------------------------------------------------------------------------------------------------------------------------- +# keyword +#---------------------------------------------------------------------------------------------------------------------------------- + +include Registry_NWTC_Library.txt +usefrom FlowField.txt + +typedef IfW_FlowField ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - +typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - +typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - +typedef ^ OtherStateType ReKi DummyOtherState - - - "Remove this variable if you have other states" - +typedef ^ MiscVarType ReKi DummyMiscVar - - - "Remove this variable if you have misc variables" - +typedef ^ InputType ReKi Position :: - - "Array holding the input positions at a given timestep" meters + +typedef ^ SteadyInitInputType ReKi HWindSpeed - - - "Horizontal wind speed" m/s +typedef ^ ^ ReKi RefHt - - - "Reference height for horizontal wind speed" meters +typedef ^ ^ ReKi PLExp - - - "Power law exponent" - + +typedef ^ UniformInitInputType character(1024) WindFileName - - - "Name of the wind file to use" - +typedef ^ ^ ReKi RefHt - - - "Reference height for horizontal wind speed" meters +typedef ^ ^ ReKi RefLength - - - "Reference length for linear horizontal and vertical sheer" - +typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians +typedef ^ ^ logical UseInputFile - .true. - "Flag for toggling file based IO in wind type 2." - +typedef ^ ^ FileInfoType PassedFileData - - - "Optional slot for wind type 2 data if file IO is not used." - + +typedef ^ TurbSimInitInputType character(1024) WindFileName - - - "Name of the wind file to use" - + +typedef ^ BladedInitInputType character(1024) WindFileName - - - "Root filename" - +typedef ^ ^ logical NativeBladedFmt - - - "Whether this is native Bladed (needs wind profile and TI scaling) or not" - +typedef ^ ^ logical TowerFileExist - - - "Tower file exists" - +typedef ^ ^ IntKi TurbineID - 0 - "Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm)" - + +typedef ^ BladedInitOutputType ReKi TI {3} - - "Turbulence intensity given in the file" - +typedef ^ ^ ReKi PropagationDir - - - "Propogation direction from native Bladed format" degrees +typedef ^ ^ ReKi VFlowAngle - - - "Vertical flow angle from native Bladed format" degrees + +typedef ^ HAWCInitInputType character(1024) WindFileName {3} - - "Name of the wind file to use" - +typedef ^ ^ IntKi nx - 0 - "Number of grids in the x direction (in the 3 files above)" - +typedef ^ ^ IntKi ny - 0 - "Number of grids in the y direction (in the 3 files above)" - +typedef ^ ^ IntKi nz - 0 - "Number of grids in the z direction (in the 3 files above)" - +typedef ^ ^ ReKi dx - 0 - "size of grids in the x direction (in the 3 files above)" - +typedef ^ ^ ReKi dy - 0 - "size of grids in the y direction (in the 3 files above)" - +typedef ^ ^ ReKi dz - 0 - "size of grids in the z direction (in the 3 files above)" - +typedef ^ ^ ReKi RefHt - 0 - "Reference (hub) height of the grid" meters +typedef ^ ^ IntKi ScaleMethod - 0 - "Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation]" - +typedef ^ ^ ReKi SF 3 0 - "Turbulence scaling factor for each direction [ScaleMethod=1]" - +typedef ^ ^ ReKi SigmaF 3 0 - "Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2]" - +typedef ^ ^ ReKi URef - 0 - "Mean u-component wind speed at the reference height" meters +typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - +typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - +typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - +typedef ^ ^ ReKi XOffset - 0 - "distance offset for FF wind files" meters + +typedef ^ UserInitInputType SiKi Dummy - - - "User field initialization input dummy value" - + +typedef ^ InitInputType IntKi WindType - 0 - "Type of the windfile" - +typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - +typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians +typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" - +typedef ^ ^ logical CalcAccel - .false. - "Flag to calculate acceleration data" - +typedef ^ ^ SteadyInitInputType Steady - - - "" - +typedef ^ ^ UniformInitInputType Uniform - - - "" - +typedef ^ ^ TurbSimInitInputType TurbSim - - - "" - +typedef ^ ^ BladedInitInputType Bladed - - - "" - +typedef ^ ^ HAWCInitInputType HAWC - - - "" - + +typedef ^ WindFileDat character(1024) FileName - - - "Name of the windfile retrieved" - +typedef ^ ^ IntKi WindType - 0 - "Type of the windfile" - +typedef ^ ^ ReKi RefHt - - - "Reference height given in file" meters +typedef ^ ^ Logical RefHt_Set - - - "Reference height was given in file" - +typedef ^ ^ DbKi DT - - - "TimeStep of the wind file -- zero value for none" seconds +typedef ^ ^ IntKi NumTSteps - - - "Number of timesteps in the time range of wind file" - +typedef ^ ^ Logical ConstantDT - - - "Timesteps are the same throughout file" - +typedef ^ ^ ReKi TRange {2} - - "Time range of the wind file" seconds +typedef ^ ^ Logical TRange_Limited - - - "TRange limits strictly enforced" - +typedef ^ ^ ReKi YRange {2} - - "Range in y direction" meters +typedef ^ ^ Logical YRange_Limited - - - "YRange limits strictly enforced" - +typedef ^ ^ ReKi ZRange {2} - - "Range in z direction" meters +typedef ^ ^ Logical ZRange_Limited - - - "ZRange limits strictly enforced" - +typedef ^ ^ IntKi BinaryFormat - - - "Binary format identifier" - +typedef ^ ^ Logical IsBinary - - - "Windfile is a binary file" - +typedef ^ ^ ReKi TI {3} - - "Turbulence intensity (U,V,W)" - +typedef ^ ^ Logical TI_listed - - - "Turbulence intesity given in file" - +typedef ^ ^ ReKi MWS - - - "Approximate mean wind speed" - + +typedef ^ InitOutputType ProgDesc Ver - - - "Version information off FFWind submodule" - +typedef ^ ^ WindFileDat FileDat - - - "" - +typedef ^ ^ BladedInitOutputType Bladed - - - "" - + + + diff --git a/modules/inflowwind/src/IfW_FlowField_Types.f90 b/modules/inflowwind/src/IfW_FlowField_Types.f90 new file mode 100644 index 0000000000..9212d16149 --- /dev/null +++ b/modules/inflowwind/src/IfW_FlowField_Types.f90 @@ -0,0 +1,3596 @@ +!STARTOFREGISTRYGENERATEDFILE 'IfW_FlowField_Types.f90' +! +! WARNING This file is generated automatically by the FAST registry. +! Do not edit. Your changes to this file will be lost. +! +! FAST Registry +!********************************************************************************************************************************* +! IfW_FlowField_Types +!................................................................................................................................. +! This file is part of IfW_FlowField. +! +! Copyright (C) 2012-2016 National Renewable Energy Laboratory +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +! +! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. +! +!********************************************************************************************************************************* +!> This module contains the user-defined types needed in IfW_FlowField. It also contains copy, destroy, pack, and +!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. +MODULE IfW_FlowField_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE FlowField_Types +USE NWTC_Library +IMPLICIT NONE +! ========= IfW_FlowField_ContinuousStateType ======= + TYPE, PUBLIC :: IfW_FlowField_ContinuousStateType + REAL(ReKi) :: DummyContState !< Remove this variable if you have continuous states [-] + END TYPE IfW_FlowField_ContinuousStateType +! ======================= +! ========= IfW_FlowField_DiscreteStateType ======= + TYPE, PUBLIC :: IfW_FlowField_DiscreteStateType + REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] + END TYPE IfW_FlowField_DiscreteStateType +! ======================= +! ========= IfW_FlowField_ConstraintStateType ======= + TYPE, PUBLIC :: IfW_FlowField_ConstraintStateType + REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] + END TYPE IfW_FlowField_ConstraintStateType +! ======================= +! ========= IfW_FlowField_OtherStateType ======= + TYPE, PUBLIC :: IfW_FlowField_OtherStateType + REAL(ReKi) :: DummyOtherState !< Remove this variable if you have other states [-] + END TYPE IfW_FlowField_OtherStateType +! ======================= +! ========= IfW_FlowField_MiscVarType ======= + TYPE, PUBLIC :: IfW_FlowField_MiscVarType + REAL(ReKi) :: DummyMiscVar !< Remove this variable if you have misc variables [-] + END TYPE IfW_FlowField_MiscVarType +! ======================= +! ========= IfW_FlowField_InputType ======= + TYPE, PUBLIC :: IfW_FlowField_InputType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Position !< Array holding the input positions at a given timestep [meters] + END TYPE IfW_FlowField_InputType +! ======================= +! ========= SteadyInitInputType ======= + TYPE, PUBLIC :: SteadyInitInputType + REAL(ReKi) :: HWindSpeed !< Horizontal wind speed [m/s] + REAL(ReKi) :: RefHt !< Reference height for horizontal wind speed [meters] + REAL(ReKi) :: PLExp !< Power law exponent [-] + END TYPE SteadyInitInputType +! ======================= +! ========= UniformInitInputType ======= + TYPE, PUBLIC :: UniformInitInputType + character(1024) :: WindFileName !< Name of the wind file to use [-] + REAL(ReKi) :: RefHt !< Reference height for horizontal wind speed [meters] + REAL(ReKi) :: RefLength !< Reference length for linear horizontal and vertical sheer [-] + REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] + LOGICAL :: UseInputFile = .true. !< Flag for toggling file based IO in wind type 2. [-] + TYPE(FileInfoType) :: PassedFileData !< Optional slot for wind type 2 data if file IO is not used. [-] + END TYPE UniformInitInputType +! ======================= +! ========= TurbSimInitInputType ======= + TYPE, PUBLIC :: TurbSimInitInputType + character(1024) :: WindFileName !< Name of the wind file to use [-] + END TYPE TurbSimInitInputType +! ======================= +! ========= BladedInitInputType ======= + TYPE, PUBLIC :: BladedInitInputType + character(1024) :: WindFileName !< Root filename [-] + LOGICAL :: NativeBladedFmt !< Whether this is native Bladed (needs wind profile and TI scaling) or not [-] + LOGICAL :: TowerFileExist !< Tower file exists [-] + INTEGER(IntKi) :: TurbineID = 0 !< Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm) [-] + END TYPE BladedInitInputType +! ======================= +! ========= BladedInitOutputType ======= + TYPE, PUBLIC :: BladedInitOutputType + REAL(ReKi) , DIMENSION(1:3) :: TI !< Turbulence intensity given in the file [-] + REAL(ReKi) :: PropagationDir !< Propogation direction from native Bladed format [degrees] + REAL(ReKi) :: VFlowAngle !< Vertical flow angle from native Bladed format [degrees] + END TYPE BladedInitOutputType +! ======================= +! ========= HAWCInitInputType ======= + TYPE, PUBLIC :: HAWCInitInputType + character(1024) , DIMENSION(1:3) :: WindFileName !< Name of the wind file to use [-] + INTEGER(IntKi) :: nx = 0 !< Number of grids in the x direction (in the 3 files above) [-] + INTEGER(IntKi) :: ny = 0 !< Number of grids in the y direction (in the 3 files above) [-] + INTEGER(IntKi) :: nz = 0 !< Number of grids in the z direction (in the 3 files above) [-] + REAL(ReKi) :: dx = 0 !< size of grids in the x direction (in the 3 files above) [-] + REAL(ReKi) :: dy = 0 !< size of grids in the y direction (in the 3 files above) [-] + REAL(ReKi) :: dz = 0 !< size of grids in the z direction (in the 3 files above) [-] + REAL(ReKi) :: RefHt = 0 !< Reference (hub) height of the grid [meters] + INTEGER(IntKi) :: ScaleMethod = 0 !< Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] [-] + REAL(ReKi) , DIMENSION(1:3) :: SF !< Turbulence scaling factor for each direction [ScaleMethod=1] [-] + REAL(ReKi) , DIMENSION(1:3) :: SigmaF !< Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] [-] + REAL(ReKi) :: URef = 0 !< Mean u-component wind speed at the reference height [meters] + INTEGER(IntKi) :: WindProfileType = -1 !< Wind profile type (0=constant;1=logarithmic;2=power law) [-] + REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] + REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] + REAL(ReKi) :: XOffset = 0 !< distance offset for FF wind files [meters] + END TYPE HAWCInitInputType +! ======================= +! ========= UserInitInputType ======= + TYPE, PUBLIC :: UserInitInputType + REAL(SiKi) :: Dummy !< User field initialization input dummy value [-] + END TYPE UserInitInputType +! ======================= +! ========= IfW_FlowField_InitInputType ======= + TYPE, PUBLIC :: IfW_FlowField_InitInputType + INTEGER(IntKi) :: WindType = 0 !< Type of the windfile [-] + INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file (-1 for none). Provided by IfW. [-] + REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] + REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [-] + LOGICAL :: CalcAccel = .false. !< Flag to calculate acceleration data [-] + TYPE(SteadyInitInputType) :: Steady !< [-] + TYPE(UniformInitInputType) :: Uniform !< [-] + TYPE(TurbSimInitInputType) :: TurbSim !< [-] + TYPE(BladedInitInputType) :: Bladed !< [-] + TYPE(HAWCInitInputType) :: HAWC !< [-] + END TYPE IfW_FlowField_InitInputType +! ======================= +! ========= WindFileDat ======= + TYPE, PUBLIC :: WindFileDat + character(1024) :: FileName !< Name of the windfile retrieved [-] + INTEGER(IntKi) :: WindType = 0 !< Type of the windfile [-] + REAL(ReKi) :: RefHt !< Reference height given in file [meters] + LOGICAL :: RefHt_Set !< Reference height was given in file [-] + REAL(DbKi) :: DT !< TimeStep of the wind file -- zero value for none [seconds] + INTEGER(IntKi) :: NumTSteps !< Number of timesteps in the time range of wind file [-] + LOGICAL :: ConstantDT !< Timesteps are the same throughout file [-] + REAL(ReKi) , DIMENSION(1:2) :: TRange !< Time range of the wind file [seconds] + LOGICAL :: TRange_Limited !< TRange limits strictly enforced [-] + REAL(ReKi) , DIMENSION(1:2) :: YRange !< Range in y direction [meters] + LOGICAL :: YRange_Limited !< YRange limits strictly enforced [-] + REAL(ReKi) , DIMENSION(1:2) :: ZRange !< Range in z direction [meters] + LOGICAL :: ZRange_Limited !< ZRange limits strictly enforced [-] + INTEGER(IntKi) :: BinaryFormat !< Binary format identifier [-] + LOGICAL :: IsBinary !< Windfile is a binary file [-] + REAL(ReKi) , DIMENSION(1:3) :: TI !< Turbulence intensity (U,V,W) [-] + LOGICAL :: TI_listed !< Turbulence intesity given in file [-] + REAL(ReKi) :: MWS !< Approximate mean wind speed [-] + END TYPE WindFileDat +! ======================= +! ========= IfW_FlowField_InitOutputType ======= + TYPE, PUBLIC :: IfW_FlowField_InitOutputType + TYPE(ProgDesc) :: Ver !< Version information off FFWind submodule [-] + TYPE(WindFileDat) :: FileDat !< [-] + TYPE(BladedInitOutputType) :: Bladed !< [-] + END TYPE IfW_FlowField_InitOutputType +! ======================= +CONTAINS + SUBROUTINE IfW_FlowField_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IfW_FlowField_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(IfW_FlowField_ContinuousStateType), INTENT(INOUT) :: DstContStateData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyContState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstContStateData%DummyContState = SrcContStateData%DummyContState + END SUBROUTINE IfW_FlowField_CopyContState + + SUBROUTINE IfW_FlowField_DestroyContState( ContStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(IfW_FlowField_ContinuousStateType), INTENT(INOUT) :: ContStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyContState' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyContState + + SUBROUTINE IfW_FlowField_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IfW_FlowField_ContinuousStateType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackContState' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! DummyContState + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%DummyContState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackContState + + SUBROUTINE IfW_FlowField_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IfW_FlowField_ContinuousStateType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackContState' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%DummyContState = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackContState + + SUBROUTINE IfW_FlowField_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IfW_FlowField_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(IfW_FlowField_DiscreteStateType), INTENT(INOUT) :: DstDiscStateData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyDiscState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState + END SUBROUTINE IfW_FlowField_CopyDiscState + + SUBROUTINE IfW_FlowField_DestroyDiscState( DiscStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(IfW_FlowField_DiscreteStateType), INTENT(INOUT) :: DiscStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyDiscState' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyDiscState + + SUBROUTINE IfW_FlowField_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IfW_FlowField_DiscreteStateType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackDiscState' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! DummyDiscState + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%DummyDiscState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackDiscState + + SUBROUTINE IfW_FlowField_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IfW_FlowField_DiscreteStateType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackDiscState' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%DummyDiscState = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackDiscState + + SUBROUTINE IfW_FlowField_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IfW_FlowField_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(IfW_FlowField_ConstraintStateType), INTENT(INOUT) :: DstConstrStateData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyConstrState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState + END SUBROUTINE IfW_FlowField_CopyConstrState + + SUBROUTINE IfW_FlowField_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(IfW_FlowField_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyConstrState' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyConstrState + + SUBROUTINE IfW_FlowField_PackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IfW_FlowField_ConstraintStateType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackConstrState' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! DummyConstrState + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%DummyConstrState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackConstrState + + SUBROUTINE IfW_FlowField_UnPackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IfW_FlowField_ConstraintStateType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackConstrState' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%DummyConstrState = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackConstrState + + SUBROUTINE IfW_FlowField_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IfW_FlowField_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(IfW_FlowField_OtherStateType), INTENT(INOUT) :: DstOtherStateData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyOtherState' +! + ErrStat = ErrID_None + ErrMsg = "" + DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState + END SUBROUTINE IfW_FlowField_CopyOtherState + + SUBROUTINE IfW_FlowField_DestroyOtherState( OtherStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(IfW_FlowField_OtherStateType), INTENT(INOUT) :: OtherStateData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyOtherState' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyOtherState + + SUBROUTINE IfW_FlowField_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IfW_FlowField_OtherStateType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackOtherState' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! DummyOtherState + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%DummyOtherState + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackOtherState + + SUBROUTINE IfW_FlowField_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IfW_FlowField_OtherStateType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackOtherState' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%DummyOtherState = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackOtherState + + SUBROUTINE IfW_FlowField_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IfW_FlowField_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(IfW_FlowField_MiscVarType), INTENT(INOUT) :: DstMiscData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar + END SUBROUTINE IfW_FlowField_CopyMisc + + SUBROUTINE IfW_FlowField_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(IfW_FlowField_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyMisc' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyMisc + + SUBROUTINE IfW_FlowField_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IfW_FlowField_MiscVarType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackMisc' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! DummyMiscVar + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%DummyMiscVar + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackMisc + + SUBROUTINE IfW_FlowField_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IfW_FlowField_MiscVarType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackMisc' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%DummyMiscVar = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackMisc + + SUBROUTINE IfW_FlowField_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IfW_FlowField_InputType), INTENT(IN) :: SrcInputData + TYPE(IfW_FlowField_InputType), INTENT(INOUT) :: DstInputData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyInput' +! + ErrStat = ErrID_None + ErrMsg = "" +IF (ALLOCATED(SrcInputData%Position)) THEN + i1_l = LBOUND(SrcInputData%Position,1) + i1_u = UBOUND(SrcInputData%Position,1) + i2_l = LBOUND(SrcInputData%Position,2) + i2_u = UBOUND(SrcInputData%Position,2) + IF (.NOT. ALLOCATED(DstInputData%Position)) THEN + ALLOCATE(DstInputData%Position(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Position.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputData%Position = SrcInputData%Position +ENDIF + END SUBROUTINE IfW_FlowField_CopyInput + + SUBROUTINE IfW_FlowField_DestroyInput( InputData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(IfW_FlowField_InputType), INTENT(INOUT) :: InputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyInput' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + +IF (ALLOCATED(InputData%Position)) THEN + DEALLOCATE(InputData%Position) +ENDIF + END SUBROUTINE IfW_FlowField_DestroyInput + + SUBROUTINE IfW_FlowField_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IfW_FlowField_InputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackInput' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! Position allocated yes/no + IF ( ALLOCATED(InData%Position) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Position upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Position) ! Position + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IF ( .NOT. ALLOCATED(InData%Position) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Position,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Position,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Position,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Position,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%Position,2), UBOUND(InData%Position,2) + DO i1 = LBOUND(InData%Position,1), UBOUND(InData%Position,1) + ReKiBuf(Re_Xferred) = InData%Position(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE IfW_FlowField_PackInput + + SUBROUTINE IfW_FlowField_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IfW_FlowField_InputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackInput' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Position not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Position)) DEALLOCATE(OutData%Position) + ALLOCATE(OutData%Position(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Position.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Position,2), UBOUND(OutData%Position,2) + DO i1 = LBOUND(OutData%Position,1), UBOUND(OutData%Position,1) + OutData%Position(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE IfW_FlowField_UnPackInput + + SUBROUTINE IfW_FlowField_CopySteadyInitInputType( SrcSteadyInitInputTypeData, DstSteadyInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SteadyInitInputType), INTENT(IN) :: SrcSteadyInitInputTypeData + TYPE(SteadyInitInputType), INTENT(INOUT) :: DstSteadyInitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopySteadyInitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstSteadyInitInputTypeData%HWindSpeed = SrcSteadyInitInputTypeData%HWindSpeed + DstSteadyInitInputTypeData%RefHt = SrcSteadyInitInputTypeData%RefHt + DstSteadyInitInputTypeData%PLExp = SrcSteadyInitInputTypeData%PLExp + END SUBROUTINE IfW_FlowField_CopySteadyInitInputType + + SUBROUTINE IfW_FlowField_DestroySteadyInitInputType( SteadyInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(SteadyInitInputType), INTENT(INOUT) :: SteadyInitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroySteadyInitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroySteadyInitInputType + + SUBROUTINE IfW_FlowField_PackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(SteadyInitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackSteadyInitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! HWindSpeed + Re_BufSz = Re_BufSz + 1 ! RefHt + Re_BufSz = Re_BufSz + 1 ! PLExp + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%HWindSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PLExp + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackSteadyInitInputType + + SUBROUTINE IfW_FlowField_UnPackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(SteadyInitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackSteadyInitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%HWindSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PLExp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackSteadyInitInputType + + SUBROUTINE IfW_FlowField_CopyUniformInitInputType( SrcUniformInitInputTypeData, DstUniformInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UniformInitInputType), INTENT(IN) :: SrcUniformInitInputTypeData + TYPE(UniformInitInputType), INTENT(INOUT) :: DstUniformInitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyUniformInitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUniformInitInputTypeData%WindFileName = SrcUniformInitInputTypeData%WindFileName + DstUniformInitInputTypeData%RefHt = SrcUniformInitInputTypeData%RefHt + DstUniformInitInputTypeData%RefLength = SrcUniformInitInputTypeData%RefLength + DstUniformInitInputTypeData%PropagationDir = SrcUniformInitInputTypeData%PropagationDir + DstUniformInitInputTypeData%UseInputFile = SrcUniformInitInputTypeData%UseInputFile + CALL NWTC_Library_Copyfileinfotype( SrcUniformInitInputTypeData%PassedFileData, DstUniformInitInputTypeData%PassedFileData, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE IfW_FlowField_CopyUniformInitInputType + + SUBROUTINE IfW_FlowField_DestroyUniformInitInputType( UniformInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(UniformInitInputType), INTENT(INOUT) :: UniformInitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyUniformInitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + CALL NWTC_Library_Destroyfileinfotype( UniformInitInputTypeData%PassedFileData, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END SUBROUTINE IfW_FlowField_DestroyUniformInitInputType + + SUBROUTINE IfW_FlowField_PackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(UniformInitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackUniformInitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName + Re_BufSz = Re_BufSz + 1 ! RefHt + Re_BufSz = Re_BufSz + 1 ! RefLength + Re_BufSz = Re_BufSz + 1 ! PropagationDir + Int_BufSz = Int_BufSz + 1 ! UseInputFile + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PassedFileData: size of buffers for each call to pack subtype + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedFileData, ErrStat2, ErrMsg2, .TRUE. ) ! PassedFileData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PassedFileData + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PassedFileData + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PassedFileData + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%WindFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%RefHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PropagationDir + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseInputFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedFileData, ErrStat2, ErrMsg2, OnlySize ) ! PassedFileData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END SUBROUTINE IfW_FlowField_PackUniformInitInputType + + SUBROUTINE IfW_FlowField_UnPackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(UniformInitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackUniformInitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%WindFileName) + OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PropagationDir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UseInputFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseInputFile) + Int_Xferred = Int_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL NWTC_Library_Unpackfileinfotype( Re_Buf, Db_Buf, Int_Buf, OutData%PassedFileData, ErrStat2, ErrMsg2 ) ! PassedFileData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END SUBROUTINE IfW_FlowField_UnPackUniformInitInputType + + SUBROUTINE IfW_FlowField_CopyTurbSimInitInputType( SrcTurbSimInitInputTypeData, DstTurbSimInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TurbSimInitInputType), INTENT(IN) :: SrcTurbSimInitInputTypeData + TYPE(TurbSimInitInputType), INTENT(INOUT) :: DstTurbSimInitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyTurbSimInitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstTurbSimInitInputTypeData%WindFileName = SrcTurbSimInitInputTypeData%WindFileName + END SUBROUTINE IfW_FlowField_CopyTurbSimInitInputType + + SUBROUTINE IfW_FlowField_DestroyTurbSimInitInputType( TurbSimInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(TurbSimInitInputType), INTENT(INOUT) :: TurbSimInitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyTurbSimInitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyTurbSimInitInputType + + SUBROUTINE IfW_FlowField_PackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(TurbSimInitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackTurbSimInitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%WindFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE IfW_FlowField_PackTurbSimInitInputType + + SUBROUTINE IfW_FlowField_UnPackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(TurbSimInitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackTurbSimInitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%WindFileName) + OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE IfW_FlowField_UnPackTurbSimInitInputType + + SUBROUTINE IfW_FlowField_CopyBladedInitInputType( SrcBladedInitInputTypeData, DstBladedInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BladedInitInputType), INTENT(IN) :: SrcBladedInitInputTypeData + TYPE(BladedInitInputType), INTENT(INOUT) :: DstBladedInitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyBladedInitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBladedInitInputTypeData%WindFileName = SrcBladedInitInputTypeData%WindFileName + DstBladedInitInputTypeData%NativeBladedFmt = SrcBladedInitInputTypeData%NativeBladedFmt + DstBladedInitInputTypeData%TowerFileExist = SrcBladedInitInputTypeData%TowerFileExist + DstBladedInitInputTypeData%TurbineID = SrcBladedInitInputTypeData%TurbineID + END SUBROUTINE IfW_FlowField_CopyBladedInitInputType + + SUBROUTINE IfW_FlowField_DestroyBladedInitInputType( BladedInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(BladedInitInputType), INTENT(INOUT) :: BladedInitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyBladedInitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyBladedInitInputType + + SUBROUTINE IfW_FlowField_PackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(BladedInitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackBladedInitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName + Int_BufSz = Int_BufSz + 1 ! NativeBladedFmt + Int_BufSz = Int_BufSz + 1 ! TowerFileExist + Int_BufSz = Int_BufSz + 1 ! TurbineID + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%WindFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = TRANSFER(InData%NativeBladedFmt, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TowerFileExist, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TurbineID + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackBladedInitInputType + + SUBROUTINE IfW_FlowField_UnPackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(BladedInitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackBladedInitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%WindFileName) + OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%NativeBladedFmt = TRANSFER(IntKiBuf(Int_Xferred), OutData%NativeBladedFmt) + Int_Xferred = Int_Xferred + 1 + OutData%TowerFileExist = TRANSFER(IntKiBuf(Int_Xferred), OutData%TowerFileExist) + Int_Xferred = Int_Xferred + 1 + OutData%TurbineID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackBladedInitInputType + + SUBROUTINE IfW_FlowField_CopyBladedInitOutputType( SrcBladedInitOutputTypeData, DstBladedInitOutputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(BladedInitOutputType), INTENT(IN) :: SrcBladedInitOutputTypeData + TYPE(BladedInitOutputType), INTENT(INOUT) :: DstBladedInitOutputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyBladedInitOutputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBladedInitOutputTypeData%TI = SrcBladedInitOutputTypeData%TI + DstBladedInitOutputTypeData%PropagationDir = SrcBladedInitOutputTypeData%PropagationDir + DstBladedInitOutputTypeData%VFlowAngle = SrcBladedInitOutputTypeData%VFlowAngle + END SUBROUTINE IfW_FlowField_CopyBladedInitOutputType + + SUBROUTINE IfW_FlowField_DestroyBladedInitOutputType( BladedInitOutputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(BladedInitOutputType), INTENT(INOUT) :: BladedInitOutputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyBladedInitOutputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyBladedInitOutputType + + SUBROUTINE IfW_FlowField_PackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(BladedInitOutputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackBladedInitOutputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI + Re_BufSz = Re_BufSz + 1 ! PropagationDir + Re_BufSz = Re_BufSz + 1 ! VFlowAngle + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO i1 = LBOUND(InData%TI,1), UBOUND(InData%TI,1) + ReKiBuf(Re_Xferred) = InData%TI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%PropagationDir + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VFlowAngle + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackBladedInitOutputType + + SUBROUTINE IfW_FlowField_UnPackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(BladedInitOutputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackBladedInitOutputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + i1_l = LBOUND(OutData%TI,1) + i1_u = UBOUND(OutData%TI,1) + DO i1 = LBOUND(OutData%TI,1), UBOUND(OutData%TI,1) + OutData%TI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%PropagationDir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VFlowAngle = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackBladedInitOutputType + + SUBROUTINE IfW_FlowField_CopyHAWCInitInputType( SrcHAWCInitInputTypeData, DstHAWCInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HAWCInitInputType), INTENT(IN) :: SrcHAWCInitInputTypeData + TYPE(HAWCInitInputType), INTENT(INOUT) :: DstHAWCInitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyHAWCInitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstHAWCInitInputTypeData%WindFileName = SrcHAWCInitInputTypeData%WindFileName + DstHAWCInitInputTypeData%nx = SrcHAWCInitInputTypeData%nx + DstHAWCInitInputTypeData%ny = SrcHAWCInitInputTypeData%ny + DstHAWCInitInputTypeData%nz = SrcHAWCInitInputTypeData%nz + DstHAWCInitInputTypeData%dx = SrcHAWCInitInputTypeData%dx + DstHAWCInitInputTypeData%dy = SrcHAWCInitInputTypeData%dy + DstHAWCInitInputTypeData%dz = SrcHAWCInitInputTypeData%dz + DstHAWCInitInputTypeData%RefHt = SrcHAWCInitInputTypeData%RefHt + DstHAWCInitInputTypeData%ScaleMethod = SrcHAWCInitInputTypeData%ScaleMethod + DstHAWCInitInputTypeData%SF = SrcHAWCInitInputTypeData%SF + DstHAWCInitInputTypeData%SigmaF = SrcHAWCInitInputTypeData%SigmaF + DstHAWCInitInputTypeData%URef = SrcHAWCInitInputTypeData%URef + DstHAWCInitInputTypeData%WindProfileType = SrcHAWCInitInputTypeData%WindProfileType + DstHAWCInitInputTypeData%PLExp = SrcHAWCInitInputTypeData%PLExp + DstHAWCInitInputTypeData%Z0 = SrcHAWCInitInputTypeData%Z0 + DstHAWCInitInputTypeData%XOffset = SrcHAWCInitInputTypeData%XOffset + END SUBROUTINE IfW_FlowField_CopyHAWCInitInputType + + SUBROUTINE IfW_FlowField_DestroyHAWCInitInputType( HAWCInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(HAWCInitInputType), INTENT(INOUT) :: HAWCInitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyHAWCInitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyHAWCInitInputType + + SUBROUTINE IfW_FlowField_PackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(HAWCInitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackHAWCInitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + SIZE(InData%WindFileName)*LEN(InData%WindFileName) ! WindFileName + Int_BufSz = Int_BufSz + 1 ! nx + Int_BufSz = Int_BufSz + 1 ! ny + Int_BufSz = Int_BufSz + 1 ! nz + Re_BufSz = Re_BufSz + 1 ! dx + Re_BufSz = Re_BufSz + 1 ! dy + Re_BufSz = Re_BufSz + 1 ! dz + Re_BufSz = Re_BufSz + 1 ! RefHt + Int_BufSz = Int_BufSz + 1 ! ScaleMethod + Re_BufSz = Re_BufSz + SIZE(InData%SF) ! SF + Re_BufSz = Re_BufSz + SIZE(InData%SigmaF) ! SigmaF + Re_BufSz = Re_BufSz + 1 ! URef + Int_BufSz = Int_BufSz + 1 ! WindProfileType + Re_BufSz = Re_BufSz + 1 ! PLExp + Re_BufSz = Re_BufSz + 1 ! Z0 + Re_BufSz = Re_BufSz + 1 ! XOffset + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO i1 = LBOUND(InData%WindFileName,1), UBOUND(InData%WindFileName,1) + DO I = 1, LEN(InData%WindFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IntKiBuf(Int_Xferred) = InData%nx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ny + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nz + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dx + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dy + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dz + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefHt + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ScaleMethod + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%SF,1), UBOUND(InData%SF,1) + ReKiBuf(Re_Xferred) = InData%SF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%SigmaF,1), UBOUND(InData%SigmaF,1) + ReKiBuf(Re_Xferred) = InData%SigmaF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + ReKiBuf(Re_Xferred) = InData%URef + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%WindProfileType + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PLExp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Z0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%XOffset + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackHAWCInitInputType + + SUBROUTINE IfW_FlowField_UnPackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(HAWCInitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackHAWCInitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + i1_l = LBOUND(OutData%WindFileName,1) + i1_u = UBOUND(OutData%WindFileName,1) + DO i1 = LBOUND(OutData%WindFileName,1), UBOUND(OutData%WindFileName,1) + DO I = 1, LEN(OutData%WindFileName) + OutData%WindFileName(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + OutData%nx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ny = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nz = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%dx = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dy = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dz = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%ScaleMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%SF,1) + i1_u = UBOUND(OutData%SF,1) + DO i1 = LBOUND(OutData%SF,1), UBOUND(OutData%SF,1) + OutData%SF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%SigmaF,1) + i1_u = UBOUND(OutData%SigmaF,1) + DO i1 = LBOUND(OutData%SigmaF,1), UBOUND(OutData%SigmaF,1) + OutData%SigmaF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%URef = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%WindProfileType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%PLExp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Z0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%XOffset = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackHAWCInitInputType + + SUBROUTINE IfW_FlowField_CopyUserInitInputType( SrcUserInitInputTypeData, DstUserInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UserInitInputType), INTENT(IN) :: SrcUserInitInputTypeData + TYPE(UserInitInputType), INTENT(INOUT) :: DstUserInitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyUserInitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUserInitInputTypeData%Dummy = SrcUserInitInputTypeData%Dummy + END SUBROUTINE IfW_FlowField_CopyUserInitInputType + + SUBROUTINE IfW_FlowField_DestroyUserInitInputType( UserInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(UserInitInputType), INTENT(INOUT) :: UserInitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyUserInitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyUserInitInputType + + SUBROUTINE IfW_FlowField_PackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(UserInitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackUserInitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! Dummy + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%Dummy + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackUserInitInputType + + SUBROUTINE IfW_FlowField_UnPackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(UserInitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackUserInitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackUserInitInputType + + SUBROUTINE IfW_FlowField_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IfW_FlowField_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(IfW_FlowField_InitInputType), INTENT(INOUT) :: DstInitInputData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyInitInput' +! + ErrStat = ErrID_None + ErrMsg = "" + DstInitInputData%WindType = SrcInitInputData%WindType + DstInitInputData%SumFileUnit = SrcInitInputData%SumFileUnit + DstInitInputData%PropagationDir = SrcInitInputData%PropagationDir + DstInitInputData%VFlowAngle = SrcInitInputData%VFlowAngle + DstInitInputData%CalcAccel = SrcInitInputData%CalcAccel + CALL IfW_FlowField_Copysteadyinitinputtype( SrcInitInputData%Steady, DstInitInputData%Steady, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copyuniforminitinputtype( SrcInitInputData%Uniform, DstInitInputData%Uniform, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copyturbsiminitinputtype( SrcInitInputData%TurbSim, DstInitInputData%TurbSim, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copybladedinitinputtype( SrcInitInputData%Bladed, DstInitInputData%Bladed, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copyhawcinitinputtype( SrcInitInputData%HAWC, DstInitInputData%HAWC, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE IfW_FlowField_CopyInitInput + + SUBROUTINE IfW_FlowField_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(IfW_FlowField_InitInputType), INTENT(INOUT) :: InitInputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyInitInput' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + CALL IfW_FlowField_Destroysteadyinitinputtype( InitInputData%Steady, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroyuniforminitinputtype( InitInputData%Uniform, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroyturbsiminitinputtype( InitInputData%TurbSim, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroybladedinitinputtype( InitInputData%Bladed, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroyhawcinitinputtype( InitInputData%HAWC, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END SUBROUTINE IfW_FlowField_DestroyInitInput + + SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IfW_FlowField_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackInitInput' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! WindType + Int_BufSz = Int_BufSz + 1 ! SumFileUnit + Re_BufSz = Re_BufSz + 1 ! PropagationDir + Re_BufSz = Re_BufSz + 1 ! VFlowAngle + Int_BufSz = Int_BufSz + 1 ! CalcAccel + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Steady: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, .TRUE. ) ! Steady + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Steady + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Steady + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Steady + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Uniform: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, .TRUE. ) ! Uniform + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Uniform + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Uniform + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Uniform + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! TurbSim: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%TurbSim, ErrStat2, ErrMsg2, .TRUE. ) ! TurbSim + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! TurbSim + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! TurbSim + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! TurbSim + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Bladed: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, .TRUE. ) ! Bladed + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Bladed + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Bladed + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Bladed + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! HAWC: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%HAWC, ErrStat2, ErrMsg2, .TRUE. ) ! HAWC + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! HAWC + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! HAWC + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! HAWC + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%WindType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%SumFileUnit + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PropagationDir + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VFlowAngle + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%CalcAccel, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL IfW_FlowField_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, OnlySize ) ! Steady + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL IfW_FlowField_Packuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, OnlySize ) ! Uniform + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL IfW_FlowField_Packturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%TurbSim, ErrStat2, ErrMsg2, OnlySize ) ! TurbSim + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL IfW_FlowField_Packbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, OnlySize ) ! Bladed + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL IfW_FlowField_Packhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%HAWC, ErrStat2, ErrMsg2, OnlySize ) ! HAWC + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END SUBROUTINE IfW_FlowField_PackInitInput + + SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IfW_FlowField_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackInitInput' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%WindType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%SumFileUnit = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%PropagationDir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VFlowAngle = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%CalcAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%CalcAccel) + Int_Xferred = Int_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpacksteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Steady, ErrStat2, ErrMsg2 ) ! Steady + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Uniform, ErrStat2, ErrMsg2 ) ! Uniform + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%TurbSim, ErrStat2, ErrMsg2 ) ! TurbSim + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Bladed, ErrStat2, ErrMsg2 ) ! Bladed + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%HAWC, ErrStat2, ErrMsg2 ) ! HAWC + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END SUBROUTINE IfW_FlowField_UnPackInitInput + + SUBROUTINE IfW_FlowField_CopyWindFileDat( SrcWindFileDatData, DstWindFileDatData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WindFileDat), INTENT(IN) :: SrcWindFileDatData + TYPE(WindFileDat), INTENT(INOUT) :: DstWindFileDatData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyWindFileDat' +! + ErrStat = ErrID_None + ErrMsg = "" + DstWindFileDatData%FileName = SrcWindFileDatData%FileName + DstWindFileDatData%WindType = SrcWindFileDatData%WindType + DstWindFileDatData%RefHt = SrcWindFileDatData%RefHt + DstWindFileDatData%RefHt_Set = SrcWindFileDatData%RefHt_Set + DstWindFileDatData%DT = SrcWindFileDatData%DT + DstWindFileDatData%NumTSteps = SrcWindFileDatData%NumTSteps + DstWindFileDatData%ConstantDT = SrcWindFileDatData%ConstantDT + DstWindFileDatData%TRange = SrcWindFileDatData%TRange + DstWindFileDatData%TRange_Limited = SrcWindFileDatData%TRange_Limited + DstWindFileDatData%YRange = SrcWindFileDatData%YRange + DstWindFileDatData%YRange_Limited = SrcWindFileDatData%YRange_Limited + DstWindFileDatData%ZRange = SrcWindFileDatData%ZRange + DstWindFileDatData%ZRange_Limited = SrcWindFileDatData%ZRange_Limited + DstWindFileDatData%BinaryFormat = SrcWindFileDatData%BinaryFormat + DstWindFileDatData%IsBinary = SrcWindFileDatData%IsBinary + DstWindFileDatData%TI = SrcWindFileDatData%TI + DstWindFileDatData%TI_listed = SrcWindFileDatData%TI_listed + DstWindFileDatData%MWS = SrcWindFileDatData%MWS + END SUBROUTINE IfW_FlowField_CopyWindFileDat + + SUBROUTINE IfW_FlowField_DestroyWindFileDat( WindFileDatData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(WindFileDat), INTENT(INOUT) :: WindFileDatData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyWindFileDat' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyWindFileDat + + SUBROUTINE IfW_FlowField_PackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(WindFileDat), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackWindFileDat' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%FileName) ! FileName + Int_BufSz = Int_BufSz + 1 ! WindType + Re_BufSz = Re_BufSz + 1 ! RefHt + Int_BufSz = Int_BufSz + 1 ! RefHt_Set + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! NumTSteps + Int_BufSz = Int_BufSz + 1 ! ConstantDT + Re_BufSz = Re_BufSz + SIZE(InData%TRange) ! TRange + Int_BufSz = Int_BufSz + 1 ! TRange_Limited + Re_BufSz = Re_BufSz + SIZE(InData%YRange) ! YRange + Int_BufSz = Int_BufSz + 1 ! YRange_Limited + Re_BufSz = Re_BufSz + SIZE(InData%ZRange) ! ZRange + Int_BufSz = Int_BufSz + 1 ! ZRange_Limited + Int_BufSz = Int_BufSz + 1 ! BinaryFormat + Int_BufSz = Int_BufSz + 1 ! IsBinary + Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI + Int_BufSz = Int_BufSz + 1 ! TI_listed + Re_BufSz = Re_BufSz + 1 ! MWS + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%FileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%FileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%WindType + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefHt + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RefHt_Set, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumTSteps + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%ConstantDT, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%TRange,1), UBOUND(InData%TRange,1) + ReKiBuf(Re_Xferred) = InData%TRange(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%TRange_Limited, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%YRange,1), UBOUND(InData%YRange,1) + ReKiBuf(Re_Xferred) = InData%YRange(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%YRange_Limited, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%ZRange,1), UBOUND(InData%ZRange,1) + ReKiBuf(Re_Xferred) = InData%ZRange(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%ZRange_Limited, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BinaryFormat + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsBinary, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%TI,1), UBOUND(InData%TI,1) + ReKiBuf(Re_Xferred) = InData%TI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%TI_listed, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MWS + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackWindFileDat + + SUBROUTINE IfW_FlowField_UnPackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(WindFileDat), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackWindFileDat' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%FileName) + OutData%FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%WindType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefHt_Set = TRANSFER(IntKiBuf(Int_Xferred), OutData%RefHt_Set) + Int_Xferred = Int_Xferred + 1 + OutData%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NumTSteps = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ConstantDT = TRANSFER(IntKiBuf(Int_Xferred), OutData%ConstantDT) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%TRange,1) + i1_u = UBOUND(OutData%TRange,1) + DO i1 = LBOUND(OutData%TRange,1), UBOUND(OutData%TRange,1) + OutData%TRange(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%TRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%TRange_Limited) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%YRange,1) + i1_u = UBOUND(OutData%YRange,1) + DO i1 = LBOUND(OutData%YRange,1), UBOUND(OutData%YRange,1) + OutData%YRange(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%YRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%YRange_Limited) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%ZRange,1) + i1_u = UBOUND(OutData%ZRange,1) + DO i1 = LBOUND(OutData%ZRange,1), UBOUND(OutData%ZRange,1) + OutData%ZRange(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%ZRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%ZRange_Limited) + Int_Xferred = Int_Xferred + 1 + OutData%BinaryFormat = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%IsBinary = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsBinary) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%TI,1) + i1_u = UBOUND(OutData%TI,1) + DO i1 = LBOUND(OutData%TI,1), UBOUND(OutData%TI,1) + OutData%TI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%TI_listed = TRANSFER(IntKiBuf(Int_Xferred), OutData%TI_listed) + Int_Xferred = Int_Xferred + 1 + OutData%MWS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackWindFileDat + + SUBROUTINE IfW_FlowField_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IfW_FlowField_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(IfW_FlowField_InitOutputType), INTENT(INOUT) :: DstInitOutputData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyInitOutput' +! + ErrStat = ErrID_None + ErrMsg = "" + CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copywindfiledat( SrcInitOutputData%FileDat, DstInitOutputData%FileDat, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copybladedinitoutputtype( SrcInitOutputData%Bladed, DstInitOutputData%Bladed, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE IfW_FlowField_CopyInitOutput + + SUBROUTINE IfW_FlowField_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(IfW_FlowField_InitOutputType), INTENT(INOUT) :: InitOutputData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyInitOutput' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroywindfiledat( InitOutputData%FileDat, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroybladedinitoutputtype( InitOutputData%Bladed, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END SUBROUTINE IfW_FlowField_DestroyInitOutput + + SUBROUTINE IfW_FlowField_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IfW_FlowField_InitOutputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackInitOutput' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Ver + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Ver + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Ver + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! FileDat: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%FileDat, ErrStat2, ErrMsg2, .TRUE. ) ! FileDat + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FileDat + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FileDat + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FileDat + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! Bladed: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, .TRUE. ) ! Bladed + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! Bladed + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! Bladed + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! Bladed + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL IfW_FlowField_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%FileDat, ErrStat2, ErrMsg2, OnlySize ) ! FileDat + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL IfW_FlowField_Packbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, OnlySize ) ! Bladed + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END SUBROUTINE IfW_FlowField_PackInitOutput + + SUBROUTINE IfW_FlowField_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IfW_FlowField_InitOutputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackInitOutput' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackwindfiledat( Re_Buf, Db_Buf, Int_Buf, OutData%FileDat, ErrStat2, ErrMsg2 ) ! FileDat + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Bladed, ErrStat2, ErrMsg2 ) ! Bladed + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END SUBROUTINE IfW_FlowField_UnPackInitOutput + +END MODULE IfW_FlowField_Types +!ENDOFREGISTRYGENERATEDFILE From 67d83e91fa9ffe6a2723b49ea92f26c167f09ec0 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 22 Dec 2022 22:14:56 +0000 Subject: [PATCH 03/51] inflowwind: add FlowField init to InflowWind_Init Minimal code changes to InflowWind_Init so it can initialize the FlowField data structure in parallel its normal init. This supports comparing output using the driver. --- modules/inflowwind/src/InflowWind.f90 | 80 +++++++++ modules/inflowwind/src/InflowWind.txt | 4 + modules/inflowwind/src/InflowWind_Types.f90 | 182 ++++++++++++++++++++ 3 files changed, 266 insertions(+) diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 3932cced26..1c902ceec9 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -44,6 +44,8 @@ MODULE InflowWind USE InflowWind_Types USE NWTC_Library USE InflowWind_Subs + USE IfW_FlowField_Types + USE IfW_FlowField USE Lidar ! module for obtaining sensor data @@ -130,6 +132,9 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, ! Local variables TYPE(InflowWind_InputFile) :: InputFileData !< Data from input file + + TYPE(IfW_FlowField_InitInputType) :: FlowField_InitData !< initialization info + TYPE(IfW_FlowField_InitOutputType) :: Interp_InitOutData !< initialization output info TYPE(IfW_UniformWind_InitInputType) :: Uniform_InitData !< initialization info TYPE(IfW_UniformWind_InitOutputType) :: Uniform_InitOutData !< initialization output info @@ -296,6 +301,81 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, InitOutData%WindFileInfo%MWS = HUGE(InitOutData%WindFileInfo%MWS) + ! General + FlowField_InitData%WindType = InputFileData%WindType + FlowField_InitData%SumFileUnit = SumFileUnit + FlowField_InitData%PropagationDir = InputFileData%PropagationDir + FlowField_InitData%VFlowAngle = InputFileData%VFlowAngle + FlowField_InitData%CalcAccel = InitInp%CalcAccel + + select case(FlowField_InitData%WindType) + + case (Steady_WindNumber) + FlowField_InitData%Steady%HWindSpeed = InputFileData%Steady_HWindSpeed + FlowField_InitData%Steady%RefHt = InputFileData%Steady_RefHt + FlowField_InitData%Steady%PLExp = InputFileData%Steady_PLexp + + case (Uniform_WindNumber) + FlowField_InitData%Uniform%WindFileName = InputFileData%Uniform_FileName + FlowField_InitData%Uniform%RefHt = InputFileData%Uniform_RefHt + FlowField_InitData%Uniform%RefLength = InputFileData%Uniform_RefLength + FlowField_InitData%Uniform%PropagationDir = InputFileData%PropagationDir + FlowField_InitData%Uniform%UseInputFile = InitInp%WindType2UseInputFile + FlowField_InitData%Uniform%PassedFileData = InitInp%WindType2Data + + case (TSFF_WindNumber) + FlowField_InitData%TurbSim%WindFileName = InputFileData%TSFF_FileName + + case (BladedFF_WindNumber, BladedFF_Shr_WindNumber) + FlowField_InitData%Bladed%TurbineID = InitInp%TurbineID + if (InputFileData%WindType /= BladedFF_Shr_WindNumber) then + IF ( InitInp%FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data + IF ( InitInp%TurbineID == 0 ) THEN ! .TRUE. for the FAST.Farm low-resolution domain + InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'Low' + ELSE ! FAST.Farm high-resolution domain(s) + InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) + ENDIF + ENDIF + FlowField_InitData%Bladed%WindFileName = TRIM(InputFileData%BladedFF_FileName)//'.wnd' + FlowField_InitData%Bladed%TowerFileExist = InputFileData%BladedFF_TowerFile + FlowField_InitData%Bladed%NativeBladedFmt = .false. + else + FlowField_InitData%Bladed%WindFileName = InputFileData%BladedFF_FileName + FlowField_InitData%Bladed%TowerFileExist = .false. + FlowField_InitData%Bladed%NativeBladedFmt = .true. + end if + + case (HAWC_WindNumber) + FlowField_InitData%HAWC%WindFileName(1) = InputFileData%HAWC_FileName_u + FlowField_InitData%HAWC%WindFileName(2) = InputFileData%HAWC_FileName_v + FlowField_InitData%HAWC%WindFileName(3) = InputFileData%HAWC_FileName_w + FlowField_InitData%HAWC%nx = InputFileData%HAWC_nx + FlowField_InitData%HAWC%ny = InputFileData%HAWC_ny + FlowField_InitData%HAWC%nz = InputFileData%HAWC_nz + FlowField_InitData%HAWC%dx = InputFileData%HAWC_dx + FlowField_InitData%HAWC%dy = InputFileData%HAWC_dy + FlowField_InitData%HAWC%dz = InputFileData%HAWC_dz + FlowField_InitData%HAWC%RefHt = InputFileData%FF%RefHt + FlowField_InitData%HAWC%ScaleMethod = InputFileData%FF%ScaleMethod + FlowField_InitData%HAWC%SF = InputFileData%FF%SF + FlowField_InitData%HAWC%SigmaF = InputFileData%FF%SigmaF + FlowField_InitData%HAWC%URef = InputFileData%FF%URef + FlowField_InitData%HAWC%WindProfileType = InputFileData%FF%WindProfileType + FlowField_InitData%HAWC%PLExp = InputFileData%FF%PLExp + FlowField_InitData%HAWC%Z0 = InputFileData%FF%Z0 + FlowField_InitData%HAWC%XOffset = InputFileData%FF%XOffset + + case (User_WindNumber) + ! Add user wind initialization data here + + case default + call SetErrStat(ErrID_Fatal, ' Undefined wind type.', ErrStat, ErrMsg, RoutineName) + return + end select + + call IfW_FlowField_Init(FlowField_InitData, p%FlowField, Interp_InitOutData, TmpErrStat, TmpErrMsg) + + SELECT CASE ( InputFileData%WindType ) diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 7223cb9c89..8d3522c317 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -7,6 +7,7 @@ # keyword ################################################################################################################################### +usefrom FlowField.txt usefrom IfW_UniformWind.txt usefrom IfW_TSFFWind.txt usefrom IfW_FFWind_Base.txt @@ -111,6 +112,7 @@ typedef ^ ^ CHARACTER(1024) RootName typedef ^ ^ FileInfoType PassedFileData - - - "If we don't use the input file, pass everything through this" - typedef ^ ^ LOGICAL WindType2UseInputFile - .TRUE. - "Flag for toggling file based IO in wind type 2." - typedef ^ ^ FileInfoType WindType2Data - - - "Optional slot for wind type 2 data if file IO is not used." - +typedef ^ ^ LOGICAL CalcAccel - .FALSE. - "Flag to calculate acceleration." - typedef ^ ^ Lidar_InitInputType lidar - - - "InitInput for lidar data" - typedef ^ ^ IfW_4Dext_InitInputType FDext - - - "InitInput for 4D external wind data" - typedef ^ ^ ReKi RadAvg - - - "Radius (from hub) used for averaging wind speed" - @@ -148,6 +150,7 @@ typedef ^ ^ ReKi ReferenceHe typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters typedef ^ ^ IntKi NWindVel - - - "Number of points in the wind velocity list" - typedef ^ ^ ReKi WindViXYZ :: - - "List of XYZ coordinates for wind velocity measurements, 3xNWindVel" meters +typedef ^ ^ FlowFieldType FlowField - - - "Parameters from Full-Field" - typedef ^ ^ IfW_UniformWind_ParameterType UniformWind - - - "Parameters from UniformWind" - typedef ^ ^ IfW_TSFFWind_ParameterType TSFFWind - - - "Parameters from TSFFWind -- TurbSim full-field format" - typedef ^ ^ IfW_BladedFFWind_ParameterType BladedFFWind - - - "Parameters from BladedFFWind -- Bladed-style full-field format" - @@ -173,6 +176,7 @@ typedef ^ ^ ReKi HubOrientat # ..... Outputs ................................................................................................................... # Define outputs that are contained on the mesh here: typedef ^ OutputType ReKi VelocityUVW :: - - "Array holding the U,V,W velocity for a given timestep" meters/sec +typedef ^ OutputType ReKi AccelUVW :: - - "Array holding the U,V,W acceleration for a given timestep" meters/sec typedef ^ OutputType ReKi WriteOutput : - - "Array with values to output to file" - typedef ^ ^ ReKi DiskVel {3} - - "Vector holding the U,V,W average velocity of the disk" meters/sec typedef ^ ^ ReKi HubVel {3} - - "Vector holding the U,V,W velocity at the hub" meters/sec diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index 1e4eb17aa1..dc91c6f9d8 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -31,6 +31,7 @@ !! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. MODULE InflowWind_Types !--------------------------------------------------------------------------------------------------------------------------------- +USE FlowField_Types USE IfW_UniformWind_Types USE IfW_TSFFWind_Types USE IfW_BladedFFWind_Types @@ -127,6 +128,7 @@ MODULE InflowWind_Types TYPE(FileInfoType) :: PassedFileData !< If we don't use the input file, pass everything through this [-] LOGICAL :: WindType2UseInputFile = .TRUE. !< Flag for toggling file based IO in wind type 2. [-] TYPE(FileInfoType) :: WindType2Data !< Optional slot for wind type 2 data if file IO is not used. [-] + LOGICAL :: CalcAccel = .FALSE. !< Flag to calculate acceleration. [-] TYPE(Lidar_InitInputType) :: lidar !< InitInput for lidar data [-] TYPE(IfW_4Dext_InitInputType) :: FDext !< InitInput for 4D external wind data [-] REAL(ReKi) :: RadAvg !< Radius (from hub) used for averaging wind speed [-] @@ -161,6 +163,7 @@ MODULE InflowWind_Types REAL(ReKi) , DIMENSION(1:3) :: RefPosition !< Reference position (point where box is rotated) [meters] INTEGER(IntKi) :: NWindVel !< Number of points in the wind velocity list [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViXYZ !< List of XYZ coordinates for wind velocity measurements, 3xNWindVel [meters] + TYPE(FlowFieldType) :: FlowField !< Parameters from Full-Field [-] TYPE(IfW_UniformWind_ParameterType) :: UniformWind !< Parameters from UniformWind [-] TYPE(IfW_TSFFWind_ParameterType) :: TSFFWind !< Parameters from TSFFWind -- TurbSim full-field format [-] TYPE(IfW_BladedFFWind_ParameterType) :: BladedFFWind !< Parameters from BladedFFWind -- Bladed-style full-field format [-] @@ -185,6 +188,7 @@ MODULE InflowWind_Types ! ========= InflowWind_OutputType ======= TYPE, PUBLIC :: InflowWind_OutputType REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: VelocityUVW !< Array holding the U,V,W velocity for a given timestep [meters/sec] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AccelUVW !< Array holding the U,V,W acceleration for a given timestep [meters/sec] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< Array with values to output to file [-] REAL(ReKi) , DIMENSION(1:3) :: DiskVel !< Vector holding the U,V,W average velocity of the disk [meters/sec] REAL(ReKi) , DIMENSION(1:3) :: HubVel !< Vector holding the U,V,W velocity at the hub [meters/sec] @@ -1199,6 +1203,7 @@ SUBROUTINE InflowWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCod CALL NWTC_Library_Copyfileinfotype( SrcInitInputData%WindType2Data, DstInitInputData%WindType2Data, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + DstInitInputData%CalcAccel = SrcInitInputData%CalcAccel CALL Lidar_CopyInitInput( SrcInitInputData%lidar, DstInitInputData%lidar, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -1318,6 +1323,7 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + Int_BufSz = Int_BufSz + 1 ! CalcAccel Int_BufSz = Int_BufSz + 3 ! lidar: size of buffers for each call to pack subtype CALL Lidar_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%lidar, ErrStat2, ErrMsg2, .TRUE. ) ! lidar CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1458,6 +1464,8 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + IntKiBuf(Int_Xferred) = TRANSFER(InData%CalcAccel, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 CALL Lidar_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%lidar, ErrStat2, ErrMsg2, OnlySize ) ! lidar CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -1646,6 +1654,8 @@ SUBROUTINE InflowWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + OutData%CalcAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%CalcAccel) + Int_Xferred = Int_Xferred + 1 Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -2487,6 +2497,9 @@ SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, END IF DstParamData%WindViXYZ = SrcParamData%WindViXYZ ENDIF + CALL FlowField_Copyflowfieldtype( SrcParamData%FlowField, DstParamData%FlowField, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN CALL IfW_UniformWind_CopyParam( SrcParamData%UniformWind, DstParamData%UniformWind, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -2582,6 +2595,8 @@ SUBROUTINE InflowWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointe IF (ALLOCATED(ParamData%WindViXYZ)) THEN DEALLOCATE(ParamData%WindViXYZ) ENDIF + CALL FlowField_Destroyflowfieldtype( ParamData%FlowField, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL IfW_UniformWind_DestroyParam( ParamData%UniformWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL IfW_TSFFWind_DestroyParam( ParamData%TSFFWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) @@ -2669,6 +2684,23 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_BufSz = Re_BufSz + SIZE(InData%WindViXYZ) ! WindViXYZ END IF ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! FlowField: size of buffers for each call to pack subtype + CALL FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, .TRUE. ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FlowField + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FlowField + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FlowField + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF Int_BufSz = Int_BufSz + 3 ! UniformWind: size of buffers for each call to pack subtype CALL IfW_UniformWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%UniformWind, ErrStat2, ErrMsg2, .TRUE. ) ! UniformWind CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2925,6 +2957,34 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END DO END DO END IF + CALL FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, OnlySize ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF CALL IfW_UniformWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%UniformWind, ErrStat2, ErrMsg2, OnlySize ) ! UniformWind CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3326,6 +3386,46 @@ SUBROUTINE InflowWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, END DO END DO END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL FlowField_Unpackflowfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%FlowField, ErrStat2, ErrMsg2 ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -4063,6 +4163,20 @@ SUBROUTINE InflowWind_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrSta END IF DstOutputData%VelocityUVW = SrcOutputData%VelocityUVW ENDIF +IF (ALLOCATED(SrcOutputData%AccelUVW)) THEN + i1_l = LBOUND(SrcOutputData%AccelUVW,1) + i1_u = UBOUND(SrcOutputData%AccelUVW,1) + i2_l = LBOUND(SrcOutputData%AccelUVW,2) + i2_u = UBOUND(SrcOutputData%AccelUVW,2) + IF (.NOT. ALLOCATED(DstOutputData%AccelUVW)) THEN + ALLOCATE(DstOutputData%AccelUVW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%AccelUVW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstOutputData%AccelUVW = SrcOutputData%AccelUVW +ENDIF IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN i1_l = LBOUND(SrcOutputData%WriteOutput,1) i1_u = UBOUND(SrcOutputData%WriteOutput,1) @@ -4106,6 +4220,9 @@ SUBROUTINE InflowWind_DestroyOutput( OutputData, ErrStat, ErrMsg, DEALLOCATEpoin IF (ALLOCATED(OutputData%VelocityUVW)) THEN DEALLOCATE(OutputData%VelocityUVW) ENDIF +IF (ALLOCATED(OutputData%AccelUVW)) THEN + DEALLOCATE(OutputData%AccelUVW) +ENDIF IF (ALLOCATED(OutputData%WriteOutput)) THEN DEALLOCATE(OutputData%WriteOutput) ENDIF @@ -4153,6 +4270,11 @@ SUBROUTINE InflowWind_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Int_BufSz = Int_BufSz + 2*2 ! VelocityUVW upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%VelocityUVW) ! VelocityUVW END IF + Int_BufSz = Int_BufSz + 1 ! AccelUVW allocated yes/no + IF ( ALLOCATED(InData%AccelUVW) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! AccelUVW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AccelUVW) ! AccelUVW + END IF Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no IF ( ALLOCATED(InData%WriteOutput) ) THEN Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension @@ -4225,6 +4347,26 @@ SUBROUTINE InflowWind_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E END DO END DO END IF + IF ( .NOT. ALLOCATED(InData%AccelUVW) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AccelUVW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AccelUVW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AccelUVW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AccelUVW,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%AccelUVW,2), UBOUND(InData%AccelUVW,2) + DO i1 = LBOUND(InData%AccelUVW,1), UBOUND(InData%AccelUVW,1) + ReKiBuf(Re_Xferred) = InData%AccelUVW(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -4329,6 +4471,29 @@ SUBROUTINE InflowWind_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat END DO END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AccelUVW not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AccelUVW)) DEALLOCATE(OutData%AccelUVW) + ALLOCATE(OutData%AccelUVW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AccelUVW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%AccelUVW,2), UBOUND(OutData%AccelUVW,2) + DO i1 = LBOUND(OutData%AccelUVW,1), UBOUND(OutData%AccelUVW,1) + OutData%AccelUVW(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -6415,6 +6580,14 @@ SUBROUTINE InflowWind_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, END DO END DO END IF ! check if allocated +IF (ALLOCATED(y_out%AccelUVW) .AND. ALLOCATED(y1%AccelUVW)) THEN + DO i2 = LBOUND(y_out%AccelUVW,2),UBOUND(y_out%AccelUVW,2) + DO i1 = LBOUND(y_out%AccelUVW,1),UBOUND(y_out%AccelUVW,1) + b = -(y1%AccelUVW(i1,i2) - y2%AccelUVW(i1,i2)) + y_out%AccelUVW(i1,i2) = y1%AccelUVW(i1,i2) + b * ScaleFactor + END DO + END DO +END IF ! check if allocated IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) b = -(y1%WriteOutput(i1) - y2%WriteOutput(i1)) @@ -6499,6 +6672,15 @@ SUBROUTINE InflowWind_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrS END DO END DO END IF ! check if allocated +IF (ALLOCATED(y_out%AccelUVW) .AND. ALLOCATED(y1%AccelUVW)) THEN + DO i2 = LBOUND(y_out%AccelUVW,2),UBOUND(y_out%AccelUVW,2) + DO i1 = LBOUND(y_out%AccelUVW,1),UBOUND(y_out%AccelUVW,1) + b = (t(3)**2*(y1%AccelUVW(i1,i2) - y2%AccelUVW(i1,i2)) + t(2)**2*(-y1%AccelUVW(i1,i2) + y3%AccelUVW(i1,i2)))* scaleFactor + c = ( (t(2)-t(3))*y1%AccelUVW(i1,i2) + t(3)*y2%AccelUVW(i1,i2) - t(2)*y3%AccelUVW(i1,i2) ) * scaleFactor + y_out%AccelUVW(i1,i2) = y1%AccelUVW(i1,i2) + b + c * t_out + END DO + END DO +END IF ! check if allocated IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1) b = (t(3)**2*(y1%WriteOutput(i1) - y2%WriteOutput(i1)) + t(2)**2*(-y1%WriteOutput(i1) + y3%WriteOutput(i1)))* scaleFactor From 8d3bf704520543fcdde7494d4b215ea99653cc62 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 28 Dec 2022 15:17:36 +0000 Subject: [PATCH 04/51] nwtc-library: add acceleration calc for FlowField This commit adds routines to calculate flow field derivatives for UniformField and GridField. It also adds a method to calculate smooth velocity and acceleration (in time) for the UniformField. This is a significant improvement over the constant acceleration previously implemented. --- modules/nwtc-library/src/FlowField.f90 | 456 ++++++++++++++--- modules/nwtc-library/src/FlowField.txt | 21 +- modules/nwtc-library/src/FlowField_Types.f90 | 509 ++++++++++++++++++- 3 files changed, 881 insertions(+), 105 deletions(-) diff --git a/modules/nwtc-library/src/FlowField.f90 b/modules/nwtc-library/src/FlowField.f90 index d295f5a99e..49e28a5ba8 100644 --- a/modules/nwtc-library/src/FlowField.f90 +++ b/modules/nwtc-library/src/FlowField.f90 @@ -25,16 +25,13 @@ module FlowField implicit none public FlowField_GetVelAcc +public UniformField_CalcAccel, GridField_CalcAccel integer(IntKi), parameter :: WindProfileType_None = -1 !< don't add wind profile; already included in input integer(IntKi), parameter :: WindProfileType_Constant = 0 !< constant wind integer(IntKi), parameter :: WindProfileType_Log = 1 !< logarithmic integer(IntKi), parameter :: WindProfileType_PL = 2 !< power law -integer(IntKi), parameter :: ScaleMethod_None = 0 !< no scaling -integer(IntKi), parameter :: ScaleMethod_Direct = 1 !< direct scaling factors -integer(IntKi), parameter :: ScaleMethod_StdDev = 2 !< requested standard deviation - real(ReKi), parameter :: GridTol = 1.0E-3 ! Tolerance for determining if position is within grid contains @@ -56,7 +53,6 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel integer(IntKi) :: NumPoints real(ReKi), dimension(3) :: PositionPrime type(UniformField_Interp) :: UFop - type(UniformField_Interp) :: UFopdt real(ReKi) :: DY, DZ, DT real(ReKi), dimension(3, 8) :: P logical :: Interp3D @@ -71,7 +67,6 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel !TODO: Check that position, velocity, and acceleration are all the same shape - !---------------------------------------------------------------------------- ! Wind speed coordinate transforms from Wind file coordinates to global !---------------------------------------------------------------------------- @@ -95,19 +90,11 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel ! Uniform Flow Field !------------------------------------------------------------------------- - ! Get uniform flow operating point values at current time - UFop = UniformField_GetOP(FF%Uniform, Time) - - ! If getting accel, get change in operating point values wrt time + ! If accel allocated if (allocated(AccelUVW)) then - UFopdt%VelH = (FF%Uniform%VelH(Ufop%IData) - FF%Uniform%VelH(Ufop%IData - 1))/Ufop%dt - UFopdt%AngleH = (FF%Uniform%AngleH(Ufop%IData) - FF%Uniform%AngleH(Ufop%IData - 1))/Ufop%dt - UFopdt%AngleV = (FF%Uniform%AngleV(Ufop%IData) - FF%Uniform%AngleV(Ufop%IData - 1))/Ufop%dt - UFopdt%VelV = (FF%Uniform%VelV(Ufop%IData) - FF%Uniform%VelV(Ufop%IData - 1))/Ufop%dt - UFopdt%ShrH = (FF%Uniform%ShrH(Ufop%IData) - FF%Uniform%ShrH(Ufop%IData - 1))/Ufop%dt - UFopdt%ShrV = (FF%Uniform%ShrV(Ufop%IData) - FF%Uniform%ShrV(Ufop%IData - 1))/Ufop%dt - UFopdt%LinShrV = (FF%Uniform%LinShrV(Ufop%IData) - FF%Uniform%LinShrV(Ufop%IData - 1))/Ufop%dt - UFopdt%VelGust = (FF%Uniform%VelGust(Ufop%IData) - FF%Uniform%VelGust(Ufop%IData - 1))/Ufop%dt + UFop = UniformField_GetSmoothOP(FF%Uniform, Time) + else + UFop = UniformField_GetOP(FF%Uniform, Time) end if if (.not. FF%RotateWindBox) then @@ -120,7 +107,7 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel ! Velocity and acceleration do i = 1, NumPoints VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionXYZ(:, i)) - AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, UFopdt, PositionXYZ(:, i)) + AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, PositionXYZ(:, i)) end do end if @@ -137,7 +124,7 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel do i = 1, NumPoints PositionPrime = GetPrimePosition(PositionXYZ(:, i)) VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionPrime) - AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, UFopdt, PositionPrime) + AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, PositionPrime) end do end if @@ -284,9 +271,7 @@ pure function UniformField_GetVel(UF, op, Position) result(Velocity) VZ_rotate = op%SinAngleV*V1 + op%CosAngleV*op%VelV ! Apply wind direction - Velocity(1) = V1_rotate*op%CosAngleH - Velocity(2) = -V1_rotate*op%SinAngleH - Velocity(3) = VZ_rotate + Velocity = [V1_rotate*op%CosAngleH, -V1_rotate*op%SinAngleH, VZ_rotate] else @@ -298,56 +283,43 @@ pure function UniformField_GetVel(UF, op, Position) result(Velocity) end function -function UniformField_GetAcc(UF, op, opdt, Position) result(Accel) +function UniformField_GetAcc(UF, op, Position) result(Accel) type(UniformFieldType), intent(in) :: UF type(UniformField_Interp), intent(in) :: op - type(UniformField_Interp), intent(in) :: opdt real(ReKi), dimension(3), intent(in) :: Position real(ReKi), dimension(3) :: Accel character(*), parameter :: RoutineName = "UniformField_GetAcc" real(ReKi) :: C1, C2, C3, C4, C5 - ! If only one data point or time is outside data range, acceleration is zero - if (op%IData == 1 .or. op%IData > UF%DataSize .or. Position(3) <= 0.0_Reki) then - Accel = 0.0_ReKi - else - - ! If change in time is negative or near zero, acceleration is zero - if (op%dt < 0.0_ReKi .or. EqualRealNos(op%dt, 0.0_ReKi)) then - Accel = 0.0_ReKi - return - end if - - C1 = (Position(3)/UF%RefHeight)**op%ShrV + & - (op%LinShrV*(Position(3) - UF%RefHeight) + & - op%ShrH*(Position(1)*op%SinAngleH + & - Position(2)*op%CosAngleH))/UF%RefLength + C1 = (Position(3)/UF%RefHeight)**op%ShrV + & + (op%LinShrV*(Position(3) - UF%RefHeight) + & + op%ShrH*(Position(1)*op%SinAngleH + & + Position(2)*op%CosAngleH))/UF%RefLength - C2 = op%CosAngleV*(op%VelGust + op%VelH*(C1)) + C2 = op%CosAngleV*(op%VelGust + op%VelH*(C1)) - C3 = opdt%AngleV*op%SinAngleV*(op%VelGust + op%VelH*(C1)) + C3 = op%AngleVDot*op%SinAngleV*(op%VelGust + op%VelH*(C1)) - C4 = opdt%LinShrV*(Position(3) - UF%RefHeight) + & - opdt%ShrH*(Position(1)*op%SinAngleH + Position(2)*op%CosAngleH) + & - op%ShrH*(Position(1)*opdt%AngleH*op%CosAngleH - & - Position(2)*opdt%AngleH*op%SinAngleH) + C4 = op%LinShrVDot*(Position(3) - UF%RefHeight) + & + op%ShrHDot*(Position(1)*op%SinAngleH + Position(2)*op%CosAngleH) + & + op%ShrH*(Position(1)*op%AngleHDot*op%CosAngleH - & + Position(2)*op%AngleHDot*op%SinAngleH) - C5 = opdt%VelGust + opdt%VelH*C1 + & - op%VelH*(opdt%ShrV*(Position(3)/UF%RefHeight)**op%ShrV* & - log(Position(3)/UF%RefHeight) + C4/UF%RefLength) + C5 = op%VelGustDot + op%VelHDot*C1 + & + op%VelH*(op%ShrVDot*(Position(3)/UF%RefHeight)**op%ShrV* & + log(Position(3)/UF%RefHeight) + C4/UF%RefLength) - Accel(1) = -opdt%AngleH*op%SinAngleH*(C2 - op%SinAngleV*op%VelV) + & - op%CosAngleH*(-opdt%AngleV*op%CosAngleV*op%VelV - C3 - & - opdt%VelV*op%SinAngleV + op%CosAngleV*C5) + Accel(1) = -op%AngleHDot*op%SinAngleH*(C2 - op%SinAngleV*op%VelV) + & + op%CosAngleH*(-op%AngleVDot*op%CosAngleV*op%VelV - C3 - & + op%VelVDot*op%SinAngleV + op%CosAngleV*C5) - Accel(2) = opdt%AngleH*op%CosAngleH*(-C2 + op%SinAngleV*op%VelV) + & - op%SinAngleH*(opdt%AngleV*op%CosAngleV*op%VelV + C3 + & - opdt%VelV*op%SinAngleV - op%CosAngleV*C5) + Accel(2) = op%AngleHDot*op%CosAngleH*(-C2 + op%SinAngleV*op%VelV) + & + op%SinAngleH*(op%AngleVDot*op%CosAngleV*op%VelV + C3 + & + op%VelVDot*op%SinAngleV - op%CosAngleV*C5) - Accel(3) = opdt%AngleV*C2 - opdt%AngleV*op%SinAngleV*op%VelV + & - opdt%VelV*op%CosAngleV + op%SinAngleV*C5 - end if + Accel(3) = op%AngleVDot*C2 - op%AngleVDot*op%SinAngleV*op%VelV + & + op%VelVDot*op%CosAngleV + op%SinAngleV*C5 end function @@ -357,16 +329,11 @@ pure function UniformField_GetOP(UF, Time) result(op) real(DbKi), intent(in) :: Time type(UniformField_Interp) :: op integer(IntKi) :: i - real(ReKi) :: alpha, OMalpha - - ! Save the time in operating point - op%Time = real(Time, ReKi) + real(ReKi) :: dt, alpha, OMalpha ! If only one data point or time is at or below first time, use first sample if (UF%DataSize == 1 .or. Time < UF%Time(1)) then - op%IData = 1 - op%dt = 0.0_ReKi op%VelH = UF%VelH(1) op%AngleH = UF%AngleH(1) op%AngleV = UF%AngleV(1) @@ -379,8 +346,6 @@ pure function UniformField_GetOP(UF, Time) result(op) ! If time is after end time, use last data point else if (Time >= UF%Time(UF%DataSize)) then - op%IData = UF%DataSize + 1 - op%dt = 0.0_ReKi op%VelH = UF%VelH(UF%DataSize) op%AngleH = UF%AngleH(UF%DataSize) op%AngleV = UF%AngleV(UF%DataSize) @@ -397,13 +362,11 @@ pure function UniformField_GetOP(UF, Time) result(op) if (Time < UF%Time(i)) exit end do - op%IData = i - ! Calculate interval delta time - op%dt = UF%Time(i) - UF%Time(i - 1) + dt = UF%Time(i) - UF%Time(i - 1) ! Calculate interpolation coefficient [0,1] - alpha = real((Time - UF%Time(i - 1))/op%dt, ReKi) + alpha = real((Time - UF%Time(i - 1))/dt, ReKi) OMalpha = 1.0_ReKi - alpha ! Blend states before and after time based on alpha @@ -425,21 +388,236 @@ pure function UniformField_GetOP(UF, Time) result(op) end function -pure function UniformField_AD_DiskVel(op) result(DiskVel) - type(UniformField_Interp), intent(in) :: op - real(ReKi), dimension(3) :: DiskVel +pure function UniformField_GetSmoothOP(UF, Time) result(op) - real(ReKi) :: V1_rotate, Vz_rotate + type(UniformFieldType), intent(in) :: UF + real(DbKi), intent(in) :: Time + type(UniformField_Interp) :: op + + integer(IntKi) :: i + real(ReKi) :: C1, C2, C3, C4, h, t + + ! Initialize data index + i = 0 - V1_rotate = op%CosAngleV*op%VelH - op%SinAngleV*op%VelV - Vz_rotate = op%SinAngleV*op%VelH + op%CosAngleV*op%VelV + ! If time is outside of array + if (UF%DataSize == 1 .or. Time < UF%Time(1)) then + ! One data point or time is at or below first time, use first sample + i = 1 + else if (Time >= UF%Time(UF%DataSize)) then + ! Time is after end time, use last data point + i = UF%DataSize + end if + + ! If time was inside data array + if (i == 0) then + + ! Find first index where current time is less than Time(i) + do i = 2, UF%DataSize + if (Time < UF%Time(i)) exit + end do - DiskVel(1) = V1_rotate*op%CosAngleH - DiskVel(2) = -V1_rotate*op%SinAngleH - DiskVel(3) = Vz_rotate + h = UF%Time(i) - UF%Time(i - 1) + t = real((Time - UF%Time(i - 1))/h, ReKi) + + C1 = 2.0_ReKi*t*t*t - 3.0_ReKi*t*t + 1.0_ReKi + C2 = (t*t*t - 2.0_ReKi*t*t + t)*h + C3 = -2.0_ReKi*t*t*t + 3.0_ReKi*t*t + C4 = (t*t*t - t*t)*h + + op%VelH = C1*UF%VelH(i - 1) + C2*UF%VelHDot(i - 1) + C3*UF%VelH(i) + C4*UF%VelHDot(i) + op%AngleH = C1*UF%AngleH(i - 1) + C2*UF%AngleHDot(i - 1) + C3*UF%AngleH(i) + C4*UF%AngleHDot(i) + op%AngleV = C1*UF%AngleV(i - 1) + C2*UF%AngleVDot(i - 1) + C3*UF%AngleV(i) + C4*UF%AngleVDot(i) + op%VelV = C1*UF%VelV(i - 1) + C2*UF%VelVDot(i - 1) + C3*UF%VelV(i) + C4*UF%VelVDot(i) + op%ShrH = C1*UF%ShrH(i - 1) + C2*UF%ShrHDot(i - 1) + C3*UF%ShrH(i) + C4*UF%ShrHDot(i) + op%ShrV = C1*UF%ShrV(i - 1) + C2*UF%ShrVDot(i - 1) + C3*UF%ShrV(i) + C4*UF%ShrVDot(i) + op%LinShrV = C1*UF%LinShrV(i - 1) + C2*UF%LinShrVDot(i - 1) + C3*UF%LinShrV(i) + C4*UF%LinShrVDot(i) + op%VelGust = C1*UF%VelGust(i - 1) + C2*UF%VelGustDot(i - 1) + C3*UF%VelGust(i) + C4*UF%VelGustDot(i) + + C1 = (6.0_ReKi*t*t - 6.0_ReKi*t)/h + C2 = (3.0_ReKi*t*t - 4.0_ReKi*t + 1.0_ReKi) + C3 = -C1 + C4 = (3.0_ReKi*t*t - 2.0_ReKi*t) + + op%VelHDot = C1*UF%VelH(i - 1) + C2*UF%VelHDot(i - 1) + C3*UF%VelH(i) + C4*UF%VelHDot(i) + op%AngleHDot = C1*UF%AngleH(i - 1) + C2*UF%AngleHDot(i - 1) + C3*UF%AngleH(i) + C4*UF%AngleHDot(i) + op%AngleVDot = C1*UF%AngleV(i - 1) + C2*UF%AngleVDot(i - 1) + C3*UF%AngleV(i) + C4*UF%AngleVDot(i) + op%VelVDot = C1*UF%VelV(i - 1) + C2*UF%VelVDot(i - 1) + C3*UF%VelV(i) + C4*UF%VelVDot(i) + op%ShrHDot = C1*UF%ShrH(i - 1) + C2*UF%ShrHDot(i - 1) + C3*UF%ShrH(i) + C4*UF%ShrHDot(i) + op%ShrVDot = C1*UF%ShrV(i - 1) + C2*UF%ShrVDot(i - 1) + C3*UF%ShrV(i) + C4*UF%ShrVDot(i) + op%LinShrVDot = C1*UF%LinShrV(i - 1) + C2*UF%LinShrVDot(i - 1) + C3*UF%LinShrV(i) + C4*UF%LinShrVDot(i) + op%VelGustDot = C1*UF%VelGust(i - 1) + C2*UF%VelGustDot(i - 1) + C3*UF%VelGust(i) + C4*UF%VelGustDot(i) + + else + + ! Set values based on first/last index + op%VelH = UF%VelH(i) + op%AngleH = UF%AngleH(i) + op%AngleV = UF%AngleV(i) + op%VelV = UF%VelV(i) + op%ShrH = UF%ShrH(i) + op%ShrV = UF%ShrV(i) + op%LinShrV = UF%LinShrV(i) + op%VelGust = UF%VelGust(i) + + op%VelHDot = 0.0_ReKi + op%AngleHDot = 0.0_ReKi + op%AngleVDot = 0.0_ReKi + op%VelVDot = 0.0_ReKi + op%ShrHDot = 0.0_ReKi + op%ShrVDot = 0.0_ReKi + op%LinShrVDot = 0.0_ReKi + op%VelGustDot = 0.0_ReKi + + end if + + op%CosAngleH = cos(op%AngleH) + op%SinAngleH = sin(op%AngleH) + op%CosAngleV = cos(op%AngleV) + op%SinAngleV = sin(op%AngleV) end function +subroutine UniformField_CalcAccel(UF, ErrStat, ErrMsg) + type(UniformFieldType), intent(inout) :: UF + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = "UniformField_CalcAccel" + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + real(ReKi), allocatable :: b(:), u(:), dy2(:) + + ErrStat = ErrID_None + ErrMsg = "" + + !---------------------------------------------------------------------------- + ! Storage for spline fit arrays + !---------------------------------------------------------------------------- + + call AllocAry(B, UF%DataSize, "storage for B", TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + call AllocAry(U, UF%DataSize, "storage for U", TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + call AllocAry(dy2, UF%DataSize, "storage for dy2", TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + !---------------------------------------------------------------------------- + ! Storage for derivative arrays + !---------------------------------------------------------------------------- + + call AllocAry(UF%VelHDot, UF%DataSize, 'Uniform wind horizontal wind speed derivative', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + + call AllocAry(UF%AngleHDot, UF%DataSize, 'Uniform wind direction derivative', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + + call AllocAry(UF%AngleVDot, UF%DataSize, 'Uniform wind upflow angle derivative', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + + call AllocAry(UF%VelVDot, UF%DataSize, 'Uniform vertical wind speed derivative', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + + call AllocAry(UF%ShrHDot, UF%DataSize, 'Uniform horizontal linear shear derivative', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + + call AllocAry(UF%ShrVDot, UF%DataSize, 'Uniform vertical power-law shear exponent derivative', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + + call AllocAry(UF%LinShrVDot, UF%DataSize, 'Uniform vertical linear shear derivative', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + + call AllocAry(UF%VelGustDot, UF%DataSize, 'Uniform gust velocity derivative', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat > AbortErrLev) return + + !---------------------------------------------------------------------------- + ! Calculate derivatives + !---------------------------------------------------------------------------- + + call CalcCubicSplineDeriv(UF%Time, UF%VelH, UF%VelHDot) + call CalcCubicSplineDeriv(UF%Time, UF%AngleH, UF%AngleHDot) + call CalcCubicSplineDeriv(UF%Time, UF%AngleV, UF%AngleVDot) + call CalcCubicSplineDeriv(UF%Time, UF%VelV, UF%VelVDot) + call CalcCubicSplineDeriv(UF%Time, UF%ShrH, UF%ShrHDot) + call CalcCubicSplineDeriv(UF%Time, UF%ShrV, UF%ShrVDot) + call CalcCubicSplineDeriv(UF%Time, UF%LinShrV, UF%LinShrVDot) + call CalcCubicSplineDeriv(UF%Time, UF%VelGust, UF%VelGustDot) + +contains + + !> CalcCubicSplineDeriv fits a cubic spline through the y array with points + !! at x locations. It then calculates the corresponding derivative of y + !! with respect to x at the same x values and returns it in the dy array. + subroutine CalcCubicSplineDeriv(x, y, dy) + real(ReKi), intent(in) :: x(:) + real(ReKi), intent(in) :: y(:) + real(ReKi), intent(out) :: dy(:) + + integer(IntKi) :: i, n + real(ReKi) :: p, sig, un + + ! Get size of arrays + n = size(x) + + ! If 1 or 2 points, set derivatives to zero and return + if (n < 3) then + do i = 1, n + dy(i) = 0.0_ReKi + end do + return + end if + + ! Natural lower and upper boundaries (second derivative = 0) + ! u(1) = 0.0_ReKi + ! dy2(1) = 0.0_ReKi + ! dy2(n) = 0.0_ReKi + + ! First derivative is zero at lower boundary condition + dy2(1) = -0.5_ReKi + u(1) = 3.0_ReKi*(y(2) - y(1))/(x(2) - x(1))**2 + + ! Calculate slopes + do i = 1, n - 1 + b(i) = (y(i + 1) - y(i))/(x(i + 1) - x(i)) + end do + + ! Decomposition + do i = 2, n - 1 + sig = (x(i) - x(i - 1))/(x(i + 1) - x(i - 1)) + p = sig*dy2(i - 1) + 2.0_ReKi + dy2(i) = (sig - 1.0_ReKi)/p + u(i) = (6.*((y(i + 1) - y(i))/(x(i + 1) - x(i)) - (y(i) - y(i - 1))/(x(i) - x(i - 1)))/ & + (x(i + 1) - x(i - 1)) - sig*u(i - 1))/p + end do + + ! First derviative is zero at upper boundary condition + un = -3.0_ReKi*(y(n) - y(n - 1))/(x(n) - x(n - 1))**2 + dy2(n) = (un - 0.5_ReKi*u(n - 1))/(0.5_ReKi*dy2(n - 1) + 1.0_ReKi) + + ! Back substitution and derivative calculation + do i = n - 1, 1, -1 + dy2(i) = dy2(i)*dy2(i + 1) + u(i) + dy(i) = real(b(i) - (x(i + 1) - x(i))*(dy2(i)/3.0_ReKi + dy2(i + 1)/6.0_ReKi), SiKi) + end do + dy(n) = real(b(n - 1) + (x(n) - x(n - 1))*(dy2(n - 1)/6.0_ReKi + dy2(n)/3.0_ReKi), SiKi) + + end subroutine + +end subroutine + function GridField_GetVel(GF, Position, DY, DZ, DT, P, Interp3D) result(Velocity) type(GridFieldType), intent(in) :: GF !< Grid-Field data @@ -726,7 +904,6 @@ function GridField_GetBoundsZ(GF, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) integer(IntKi) :: stat real(ReKi) :: Z_GRID - real(ReKi) :: Z_twr(3) ! Calculate position on Z grid Z_GRID = (PosZ - GF%GridBase)*GF%InvDZ + 1 @@ -860,4 +1037,123 @@ function GridField_GetBoundsT(GF, Time, PosX, DT, IT_LO, IT_HI, TimeShifted) res end function +subroutine GridField_CalcAccel(GF, ErrStat, ErrMsg) + type(GridFieldType), intent(inout) :: GF + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = "GridField_CalcAccel" + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + integer(IntKi) :: ic, iy, iz + real(ReKi), allocatable :: b(:), u(:), dy2(:) + + ErrStat = ErrID_None + ErrMsg = "" + + ! Allocate storage for acceleration grid + call AllocAry(GF%Acc, size(GF%Vel, dim=1), size(GF%Vel, dim=2), & + size(GF%Vel, dim=3), size(GF%Vel, dim=4), & + 'grid-field velocity data', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Allocate storage for B used in cubic spline derivative calc + call AllocAry(B, GF%NSteps, "storage for B", TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Allocate storage for U used in cubic spline derivative calc + call AllocAry(U, GF%NSteps, "storage for U", TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Allocate storage for V used in cubic spline derivative calc + call AllocAry(dy2, GF%NSteps, "storage for V", TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Calculate acceleration at each grid point + do iz = 1, GF%NZGrids + do iy = 1, GF%NYGrids + do ic = 1, GF%NComp + call CalcCubicSplineDeriv(GF%DTime, GF%Vel(ic, iy, iz, :), GF%Acc(ic, iy, iz, :)) + end do + end do + end do + + ! If grid field includes tower grids + if (GF%NTGrids > 0) then + + ! Allocate storage for tower acceleration + call AllocAry(GF%AccTower, size(GF%VelTower, dim=1), & + size(GF%VelTower, dim=2), size(GF%VelTower, dim=3), & + 'tower wind acceleration data.', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Loop through tower grid and calculate acceleration + do iz = 1, GF%NTGrids + do ic = 1, GF%NComp + call CalcCubicSplineDeriv(GF%DTime, GF%VelTower(ic, iz, :), GF%AccTower(ic, iz, :)) + end do + end do + end if + +contains + + !> CalcCubicSplineDeriv fits a cubic spline through the y array with points + !! spaced a constant 'h' apart. It then calculates the corresponding + !! derivative of y with respect to x at the same x values and returns it + !! in the dy array. + subroutine CalcCubicSplineDeriv(h, y, dy) + real(ReKi), intent(in) :: h + real(SiKi), intent(in) :: y(:) + real(SiKi), intent(out) :: dy(:) + + integer(IntKi) :: i, n + real(ReKi) :: p, un + + ! Get size of arrays + n = size(y) + + ! If 1 or 2 points, set derivatives to zero and return + if (n < 3) then + do i = 1, n + dy(i) = 0.0_ReKi + end do + return + end if + + ! First derivative is zero at lower boundary condition + dy2(1) = -0.5_ReKi + u(1) = 3.0_ReKi*(y(2) - y(1))/h**2 + + ! Calculate slopes + do i = 1, n - 1 + b(i) = (y(i + 1) - y(i))/h + end do + + ! Decomposition + do i = 2, n - 1 + p = 0.5_ReKi*dy2(i - 1) + 2.0_ReKi + dy2(i) = -0.5_ReKi/p + u(i) = (6.*((y(i + 1) - y(i))/h - (y(i) - y(i - 1))/h)/(2.0_ReKi*h) - 0.5_ReKi*u(i - 1))/p + end do + + ! First derviative is zero at upper boundary condition + un = -3.0_ReKi*(y(n) - y(n - 1))/h**2 + dy2(n) = (un - 0.5_ReKi*u(n - 1))/(0.5_ReKi*dy2(n - 1) + 1.0_ReKi) + + ! Back substitution and derivative calculation + do i = n - 1, 1, -1 + dy2(i) = dy2(i)*dy2(i + 1) + u(i) + dy(i) = real(b(i) - h*(dy2(i)/3.0_ReKi + dy2(i + 1)/6.0_ReKi), SiKi) + end do + dy(n) = real(b(n - 1) + h*(dy2(n - 1)/6.0_ReKi + dy2(n)/3.0_ReKi), SiKi) + + end subroutine + +end subroutine + end module diff --git a/modules/nwtc-library/src/FlowField.txt b/modules/nwtc-library/src/FlowField.txt index 3d4563d35b..e1ab2aca44 100644 --- a/modules/nwtc-library/src/FlowField.txt +++ b/modules/nwtc-library/src/FlowField.txt @@ -16,25 +16,38 @@ typedef ^ ^ ReKi RefLength typedef ^ ^ IntKi DataSize - - - "size of data in HH file" typedef ^ ^ ReKi Time : - - "HH time array" seconds typedef ^ ^ ReKi VelH : - - "HH horizontal wind speed" meters/sec +typedef ^ ^ ReKi VelHDot : - - "Derivative of HH horizontal wind speed wrt time" meters/sec typedef ^ ^ ReKi VelV : - - "HH vertical wind speed, including tower shadow" meters/sec +typedef ^ ^ ReKi VelVDot : - - "Derivative of HH vertical wind speed wrt time" meters/sec typedef ^ ^ ReKi VelGust : - - "HH wind gust speed" - +typedef ^ ^ ReKi VelGustDot : - - "Derivative of HH wind gust speed wrt time" - typedef ^ ^ ReKi AngleH : - - "HH wind direction angle" degrees +typedef ^ ^ ReKi AngleHDot : - - "Derivative of HH wind direction angle wrt time" degrees typedef ^ ^ ReKi AngleV : - - "HH upflow angle" degrees +typedef ^ ^ ReKi AngleVDot : - - "Derivative of HH upflow angle wrt time" degrees typedef ^ ^ ReKi ShrH : - - "HH horizontal linear shear" - +typedef ^ ^ ReKi ShrHDot : - - "Derivative of HH horizontal linear shear wrt time" - typedef ^ ^ ReKi ShrV : - - "HH vertical shear exponent" - +typedef ^ ^ ReKi ShrVDot : - - "Derivative of HH vertical shear exponent wrt time" - typedef ^ ^ ReKi LinShrV : - - "HH vertical linear shear" seconds +typedef ^ ^ ReKi LinShrVDot : - - "Derivative of HH vertical linear shear wrt time" seconds -typedef ^ UniformField_Interp IntKi IData - - - "Data index high" -typedef ^ ^ ReKi dt - - - "interval delta time" seconds -typedef ^ ^ ReKi Time - - - "HH time" seconds -typedef ^ ^ ReKi VelH - - - "HH horizontal wind speed" meters/sec +typedef ^ UniformField_Interp ReKi VelH - - - "HH horizontal wind speed" meters/sec +typedef ^ ^ ReKi VelHDot - - - "derivative of HH horizontal wind speed wrt Time" meters/sec typedef ^ ^ ReKi VelV - - - "HH vertical wind speed, including tower shadow" meters/sec +typedef ^ ^ ReKi VelVDot - - - "derivative of HH vertical wind speed wrt Time" meters/sec typedef ^ ^ ReKi VelGust - - - "HH wind gust speed" - +typedef ^ ^ ReKi VelGustDot - - - "derivative of HH wind gust speed wrt Time" - typedef ^ ^ ReKi AngleH - - - "HH wind direction angle" degrees +typedef ^ ^ ReKi AngleHDot - - - "derivative of HH wind direction angle wrt Time" degrees typedef ^ ^ ReKi AngleV - - - "HH upflow angle" degrees +typedef ^ ^ ReKi AngleVDot - - - "derivative of HH upflow angle wrt Time" degrees typedef ^ ^ ReKi ShrH - - - "HH horizontal linear shear" - +typedef ^ ^ ReKi ShrHDot - - - "derivative of HH horizontal linear shear wrt Time" - typedef ^ ^ ReKi ShrV - - - "HH vertical shear exponent" - +typedef ^ ^ ReKi ShrVDot - - - "derivative of HH vertical shear exponent wrt Time" - typedef ^ ^ ReKi LinShrV - - - "HH vertical linear shear" seconds +typedef ^ ^ ReKi LinShrVDot - - - "derivative of HH vertical linear shear wrt Time" seconds typedef ^ ^ ReKi CosAngleH - - - "Horizontal angle components" - typedef ^ ^ ReKi SinAngleH - - - "Horizontal angle components" - typedef ^ ^ ReKi CosAngleV - - - "Vertical angle components" - diff --git a/modules/nwtc-library/src/FlowField_Types.f90 b/modules/nwtc-library/src/FlowField_Types.f90 index a344ed0c78..551d6a430d 100644 --- a/modules/nwtc-library/src/FlowField_Types.f90 +++ b/modules/nwtc-library/src/FlowField_Types.f90 @@ -45,28 +45,41 @@ MODULE FlowField_Types INTEGER(IntKi) :: DataSize !< size of data in HH file [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Time !< HH time array [seconds] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VelH !< HH horizontal wind speed [meters/sec] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VelHDot !< Derivative of HH horizontal wind speed wrt time [meters/sec] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VelV !< HH vertical wind speed, including tower shadow [meters/sec] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VelVDot !< Derivative of HH vertical wind speed wrt time [meters/sec] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VelGust !< HH wind gust speed [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VelGustDot !< Derivative of HH wind gust speed wrt time [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AngleH !< HH wind direction angle [degrees] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AngleHDot !< Derivative of HH wind direction angle wrt time [degrees] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AngleV !< HH upflow angle [degrees] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AngleVDot !< Derivative of HH upflow angle wrt time [degrees] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ShrH !< HH horizontal linear shear [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ShrHDot !< Derivative of HH horizontal linear shear wrt time [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ShrV !< HH vertical shear exponent [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ShrVDot !< Derivative of HH vertical shear exponent wrt time [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LinShrV !< HH vertical linear shear [seconds] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: LinShrVDot !< Derivative of HH vertical linear shear wrt time [seconds] END TYPE UniformFieldType ! ======================= ! ========= UniformField_Interp ======= TYPE, PUBLIC :: UniformField_Interp - INTEGER(IntKi) :: IData !< Data index high [-] - REAL(ReKi) :: dt !< interval delta time [seconds] - REAL(ReKi) :: Time !< HH time [seconds] REAL(ReKi) :: VelH !< HH horizontal wind speed [meters/sec] + REAL(ReKi) :: VelHDot !< derivative of HH horizontal wind speed wrt Time [meters/sec] REAL(ReKi) :: VelV !< HH vertical wind speed, including tower shadow [meters/sec] + REAL(ReKi) :: VelVDot !< derivative of HH vertical wind speed wrt Time [meters/sec] REAL(ReKi) :: VelGust !< HH wind gust speed [-] + REAL(ReKi) :: VelGustDot !< derivative of HH wind gust speed wrt Time [-] REAL(ReKi) :: AngleH !< HH wind direction angle [degrees] + REAL(ReKi) :: AngleHDot !< derivative of HH wind direction angle wrt Time [degrees] REAL(ReKi) :: AngleV !< HH upflow angle [degrees] + REAL(ReKi) :: AngleVDot !< derivative of HH upflow angle wrt Time [degrees] REAL(ReKi) :: ShrH !< HH horizontal linear shear [-] + REAL(ReKi) :: ShrHDot !< derivative of HH horizontal linear shear wrt Time [-] REAL(ReKi) :: ShrV !< HH vertical shear exponent [-] + REAL(ReKi) :: ShrVDot !< derivative of HH vertical shear exponent wrt Time [-] REAL(ReKi) :: LinShrV !< HH vertical linear shear [seconds] + REAL(ReKi) :: LinShrVDot !< derivative of HH vertical linear shear wrt Time [seconds] REAL(ReKi) :: CosAngleH !< Horizontal angle components [-] REAL(ReKi) :: SinAngleH !< Horizontal angle components [-] REAL(ReKi) :: CosAngleV !< Vertical angle components [-] @@ -176,6 +189,18 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi END IF DstUniformFieldTypeData%VelH = SrcUniformFieldTypeData%VelH ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%VelHDot)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%VelHDot,1) + i1_u = UBOUND(SrcUniformFieldTypeData%VelHDot,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%VelHDot)) THEN + ALLOCATE(DstUniformFieldTypeData%VelHDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%VelHDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%VelHDot = SrcUniformFieldTypeData%VelHDot +ENDIF IF (ALLOCATED(SrcUniformFieldTypeData%VelV)) THEN i1_l = LBOUND(SrcUniformFieldTypeData%VelV,1) i1_u = UBOUND(SrcUniformFieldTypeData%VelV,1) @@ -188,6 +213,18 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi END IF DstUniformFieldTypeData%VelV = SrcUniformFieldTypeData%VelV ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%VelVDot)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%VelVDot,1) + i1_u = UBOUND(SrcUniformFieldTypeData%VelVDot,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%VelVDot)) THEN + ALLOCATE(DstUniformFieldTypeData%VelVDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%VelVDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%VelVDot = SrcUniformFieldTypeData%VelVDot +ENDIF IF (ALLOCATED(SrcUniformFieldTypeData%VelGust)) THEN i1_l = LBOUND(SrcUniformFieldTypeData%VelGust,1) i1_u = UBOUND(SrcUniformFieldTypeData%VelGust,1) @@ -200,6 +237,18 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi END IF DstUniformFieldTypeData%VelGust = SrcUniformFieldTypeData%VelGust ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%VelGustDot)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%VelGustDot,1) + i1_u = UBOUND(SrcUniformFieldTypeData%VelGustDot,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%VelGustDot)) THEN + ALLOCATE(DstUniformFieldTypeData%VelGustDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%VelGustDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%VelGustDot = SrcUniformFieldTypeData%VelGustDot +ENDIF IF (ALLOCATED(SrcUniformFieldTypeData%AngleH)) THEN i1_l = LBOUND(SrcUniformFieldTypeData%AngleH,1) i1_u = UBOUND(SrcUniformFieldTypeData%AngleH,1) @@ -212,6 +261,18 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi END IF DstUniformFieldTypeData%AngleH = SrcUniformFieldTypeData%AngleH ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%AngleHDot)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%AngleHDot,1) + i1_u = UBOUND(SrcUniformFieldTypeData%AngleHDot,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%AngleHDot)) THEN + ALLOCATE(DstUniformFieldTypeData%AngleHDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%AngleHDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%AngleHDot = SrcUniformFieldTypeData%AngleHDot +ENDIF IF (ALLOCATED(SrcUniformFieldTypeData%AngleV)) THEN i1_l = LBOUND(SrcUniformFieldTypeData%AngleV,1) i1_u = UBOUND(SrcUniformFieldTypeData%AngleV,1) @@ -224,6 +285,18 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi END IF DstUniformFieldTypeData%AngleV = SrcUniformFieldTypeData%AngleV ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%AngleVDot)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%AngleVDot,1) + i1_u = UBOUND(SrcUniformFieldTypeData%AngleVDot,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%AngleVDot)) THEN + ALLOCATE(DstUniformFieldTypeData%AngleVDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%AngleVDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%AngleVDot = SrcUniformFieldTypeData%AngleVDot +ENDIF IF (ALLOCATED(SrcUniformFieldTypeData%ShrH)) THEN i1_l = LBOUND(SrcUniformFieldTypeData%ShrH,1) i1_u = UBOUND(SrcUniformFieldTypeData%ShrH,1) @@ -236,6 +309,18 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi END IF DstUniformFieldTypeData%ShrH = SrcUniformFieldTypeData%ShrH ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%ShrHDot)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%ShrHDot,1) + i1_u = UBOUND(SrcUniformFieldTypeData%ShrHDot,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%ShrHDot)) THEN + ALLOCATE(DstUniformFieldTypeData%ShrHDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%ShrHDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%ShrHDot = SrcUniformFieldTypeData%ShrHDot +ENDIF IF (ALLOCATED(SrcUniformFieldTypeData%ShrV)) THEN i1_l = LBOUND(SrcUniformFieldTypeData%ShrV,1) i1_u = UBOUND(SrcUniformFieldTypeData%ShrV,1) @@ -248,6 +333,18 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi END IF DstUniformFieldTypeData%ShrV = SrcUniformFieldTypeData%ShrV ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%ShrVDot)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%ShrVDot,1) + i1_u = UBOUND(SrcUniformFieldTypeData%ShrVDot,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%ShrVDot)) THEN + ALLOCATE(DstUniformFieldTypeData%ShrVDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%ShrVDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%ShrVDot = SrcUniformFieldTypeData%ShrVDot +ENDIF IF (ALLOCATED(SrcUniformFieldTypeData%LinShrV)) THEN i1_l = LBOUND(SrcUniformFieldTypeData%LinShrV,1) i1_u = UBOUND(SrcUniformFieldTypeData%LinShrV,1) @@ -259,6 +356,18 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi END IF END IF DstUniformFieldTypeData%LinShrV = SrcUniformFieldTypeData%LinShrV +ENDIF +IF (ALLOCATED(SrcUniformFieldTypeData%LinShrVDot)) THEN + i1_l = LBOUND(SrcUniformFieldTypeData%LinShrVDot,1) + i1_u = UBOUND(SrcUniformFieldTypeData%LinShrVDot,1) + IF (.NOT. ALLOCATED(DstUniformFieldTypeData%LinShrVDot)) THEN + ALLOCATE(DstUniformFieldTypeData%LinShrVDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstUniformFieldTypeData%LinShrVDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstUniformFieldTypeData%LinShrVDot = SrcUniformFieldTypeData%LinShrVDot ENDIF END SUBROUTINE FlowField_CopyUniformFieldType @@ -289,26 +398,50 @@ SUBROUTINE FlowField_DestroyUniformFieldType( UniformFieldTypeData, ErrStat, Err IF (ALLOCATED(UniformFieldTypeData%VelH)) THEN DEALLOCATE(UniformFieldTypeData%VelH) ENDIF +IF (ALLOCATED(UniformFieldTypeData%VelHDot)) THEN + DEALLOCATE(UniformFieldTypeData%VelHDot) +ENDIF IF (ALLOCATED(UniformFieldTypeData%VelV)) THEN DEALLOCATE(UniformFieldTypeData%VelV) ENDIF +IF (ALLOCATED(UniformFieldTypeData%VelVDot)) THEN + DEALLOCATE(UniformFieldTypeData%VelVDot) +ENDIF IF (ALLOCATED(UniformFieldTypeData%VelGust)) THEN DEALLOCATE(UniformFieldTypeData%VelGust) ENDIF +IF (ALLOCATED(UniformFieldTypeData%VelGustDot)) THEN + DEALLOCATE(UniformFieldTypeData%VelGustDot) +ENDIF IF (ALLOCATED(UniformFieldTypeData%AngleH)) THEN DEALLOCATE(UniformFieldTypeData%AngleH) ENDIF +IF (ALLOCATED(UniformFieldTypeData%AngleHDot)) THEN + DEALLOCATE(UniformFieldTypeData%AngleHDot) +ENDIF IF (ALLOCATED(UniformFieldTypeData%AngleV)) THEN DEALLOCATE(UniformFieldTypeData%AngleV) ENDIF +IF (ALLOCATED(UniformFieldTypeData%AngleVDot)) THEN + DEALLOCATE(UniformFieldTypeData%AngleVDot) +ENDIF IF (ALLOCATED(UniformFieldTypeData%ShrH)) THEN DEALLOCATE(UniformFieldTypeData%ShrH) ENDIF +IF (ALLOCATED(UniformFieldTypeData%ShrHDot)) THEN + DEALLOCATE(UniformFieldTypeData%ShrHDot) +ENDIF IF (ALLOCATED(UniformFieldTypeData%ShrV)) THEN DEALLOCATE(UniformFieldTypeData%ShrV) ENDIF +IF (ALLOCATED(UniformFieldTypeData%ShrVDot)) THEN + DEALLOCATE(UniformFieldTypeData%ShrVDot) +ENDIF IF (ALLOCATED(UniformFieldTypeData%LinShrV)) THEN DEALLOCATE(UniformFieldTypeData%LinShrV) +ENDIF +IF (ALLOCATED(UniformFieldTypeData%LinShrVDot)) THEN + DEALLOCATE(UniformFieldTypeData%LinShrVDot) ENDIF END SUBROUTINE FlowField_DestroyUniformFieldType @@ -360,41 +493,81 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Int_BufSz = Int_BufSz + 2*1 ! VelH upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%VelH) ! VelH END IF + Int_BufSz = Int_BufSz + 1 ! VelHDot allocated yes/no + IF ( ALLOCATED(InData%VelHDot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! VelHDot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VelHDot) ! VelHDot + END IF Int_BufSz = Int_BufSz + 1 ! VelV allocated yes/no IF ( ALLOCATED(InData%VelV) ) THEN Int_BufSz = Int_BufSz + 2*1 ! VelV upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%VelV) ! VelV END IF + Int_BufSz = Int_BufSz + 1 ! VelVDot allocated yes/no + IF ( ALLOCATED(InData%VelVDot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! VelVDot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VelVDot) ! VelVDot + END IF Int_BufSz = Int_BufSz + 1 ! VelGust allocated yes/no IF ( ALLOCATED(InData%VelGust) ) THEN Int_BufSz = Int_BufSz + 2*1 ! VelGust upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%VelGust) ! VelGust END IF + Int_BufSz = Int_BufSz + 1 ! VelGustDot allocated yes/no + IF ( ALLOCATED(InData%VelGustDot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! VelGustDot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VelGustDot) ! VelGustDot + END IF Int_BufSz = Int_BufSz + 1 ! AngleH allocated yes/no IF ( ALLOCATED(InData%AngleH) ) THEN Int_BufSz = Int_BufSz + 2*1 ! AngleH upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%AngleH) ! AngleH END IF + Int_BufSz = Int_BufSz + 1 ! AngleHDot allocated yes/no + IF ( ALLOCATED(InData%AngleHDot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AngleHDot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngleHDot) ! AngleHDot + END IF Int_BufSz = Int_BufSz + 1 ! AngleV allocated yes/no IF ( ALLOCATED(InData%AngleV) ) THEN Int_BufSz = Int_BufSz + 2*1 ! AngleV upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%AngleV) ! AngleV END IF + Int_BufSz = Int_BufSz + 1 ! AngleVDot allocated yes/no + IF ( ALLOCATED(InData%AngleVDot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! AngleVDot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AngleVDot) ! AngleVDot + END IF Int_BufSz = Int_BufSz + 1 ! ShrH allocated yes/no IF ( ALLOCATED(InData%ShrH) ) THEN Int_BufSz = Int_BufSz + 2*1 ! ShrH upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%ShrH) ! ShrH END IF + Int_BufSz = Int_BufSz + 1 ! ShrHDot allocated yes/no + IF ( ALLOCATED(InData%ShrHDot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ShrHDot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ShrHDot) ! ShrHDot + END IF Int_BufSz = Int_BufSz + 1 ! ShrV allocated yes/no IF ( ALLOCATED(InData%ShrV) ) THEN Int_BufSz = Int_BufSz + 2*1 ! ShrV upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%ShrV) ! ShrV END IF + Int_BufSz = Int_BufSz + 1 ! ShrVDot allocated yes/no + IF ( ALLOCATED(InData%ShrVDot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ShrVDot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%ShrVDot) ! ShrVDot + END IF Int_BufSz = Int_BufSz + 1 ! LinShrV allocated yes/no IF ( ALLOCATED(InData%LinShrV) ) THEN Int_BufSz = Int_BufSz + 2*1 ! LinShrV upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%LinShrV) ! LinShrV END IF + Int_BufSz = Int_BufSz + 1 ! LinShrVDot allocated yes/no + IF ( ALLOCATED(InData%LinShrVDot) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! LinShrVDot upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%LinShrVDot) ! LinShrVDot + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -458,6 +631,21 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%VelHDot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelHDot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelHDot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%VelHDot,1), UBOUND(InData%VelHDot,1) + ReKiBuf(Re_Xferred) = InData%VelHDot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%VelV) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -473,6 +661,21 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%VelVDot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelVDot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelVDot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%VelVDot,1), UBOUND(InData%VelVDot,1) + ReKiBuf(Re_Xferred) = InData%VelVDot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%VelGust) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -488,6 +691,21 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%VelGustDot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelGustDot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelGustDot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%VelGustDot,1), UBOUND(InData%VelGustDot,1) + ReKiBuf(Re_Xferred) = InData%VelGustDot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%AngleH) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -503,6 +721,21 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%AngleHDot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngleHDot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngleHDot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AngleHDot,1), UBOUND(InData%AngleHDot,1) + ReKiBuf(Re_Xferred) = InData%AngleHDot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%AngleV) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -518,6 +751,21 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%AngleVDot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AngleVDot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AngleVDot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%AngleVDot,1), UBOUND(InData%AngleVDot,1) + ReKiBuf(Re_Xferred) = InData%AngleVDot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%ShrH) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -533,6 +781,21 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%ShrHDot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ShrHDot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ShrHDot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ShrHDot,1), UBOUND(InData%ShrHDot,1) + ReKiBuf(Re_Xferred) = InData%ShrHDot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%ShrV) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -548,6 +811,21 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%ShrVDot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ShrVDot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ShrVDot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ShrVDot,1), UBOUND(InData%ShrVDot,1) + ReKiBuf(Re_Xferred) = InData%ShrVDot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( .NOT. ALLOCATED(InData%LinShrV) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -563,6 +841,21 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( .NOT. ALLOCATED(InData%LinShrVDot) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%LinShrVDot,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%LinShrVDot,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%LinShrVDot,1), UBOUND(InData%LinShrVDot,1) + ReKiBuf(Re_Xferred) = InData%LinShrVDot(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE FlowField_PackUniformFieldType SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -637,6 +930,24 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelHDot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%VelHDot)) DEALLOCATE(OutData%VelHDot) + ALLOCATE(OutData%VelHDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VelHDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%VelHDot,1), UBOUND(OutData%VelHDot,1) + OutData%VelHDot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelV not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -655,6 +966,24 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelVDot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%VelVDot)) DEALLOCATE(OutData%VelVDot) + ALLOCATE(OutData%VelVDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VelVDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%VelVDot,1), UBOUND(OutData%VelVDot,1) + OutData%VelVDot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelGust not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -673,6 +1002,24 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelGustDot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%VelGustDot)) DEALLOCATE(OutData%VelGustDot) + ALLOCATE(OutData%VelGustDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VelGustDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%VelGustDot,1), UBOUND(OutData%VelGustDot,1) + OutData%VelGustDot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngleH not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -691,6 +1038,24 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngleHDot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AngleHDot)) DEALLOCATE(OutData%AngleHDot) + ALLOCATE(OutData%AngleHDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AngleHDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AngleHDot,1), UBOUND(OutData%AngleHDot,1) + OutData%AngleHDot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngleV not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -709,6 +1074,24 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AngleVDot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AngleVDot)) DEALLOCATE(OutData%AngleVDot) + ALLOCATE(OutData%AngleVDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AngleVDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%AngleVDot,1), UBOUND(OutData%AngleVDot,1) + OutData%AngleVDot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ShrH not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -727,6 +1110,24 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ShrHDot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ShrHDot)) DEALLOCATE(OutData%ShrHDot) + ALLOCATE(OutData%ShrHDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ShrHDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ShrHDot,1), UBOUND(OutData%ShrHDot,1) + OutData%ShrHDot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ShrV not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -745,6 +1146,24 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ShrVDot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ShrVDot)) DEALLOCATE(OutData%ShrVDot) + ALLOCATE(OutData%ShrVDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ShrVDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ShrVDot,1), UBOUND(OutData%ShrVDot,1) + OutData%ShrVDot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinShrV not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -763,6 +1182,24 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Re_Xferred = Re_Xferred + 1 END DO END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! LinShrVDot not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%LinShrVDot)) DEALLOCATE(OutData%LinShrVDot) + ALLOCATE(OutData%LinShrVDot(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%LinShrVDot.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%LinShrVDot,1), UBOUND(OutData%LinShrVDot,1) + OutData%LinShrVDot(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END IF END SUBROUTINE FlowField_UnPackUniformFieldType SUBROUTINE FlowField_CopyUniformField_Interp( SrcUniformField_InterpData, DstUniformField_InterpData, CtrlCode, ErrStat, ErrMsg ) @@ -779,17 +1216,22 @@ SUBROUTINE FlowField_CopyUniformField_Interp( SrcUniformField_InterpData, DstUni ! ErrStat = ErrID_None ErrMsg = "" - DstUniformField_InterpData%IData = SrcUniformField_InterpData%IData - DstUniformField_InterpData%dt = SrcUniformField_InterpData%dt - DstUniformField_InterpData%Time = SrcUniformField_InterpData%Time DstUniformField_InterpData%VelH = SrcUniformField_InterpData%VelH + DstUniformField_InterpData%VelHDot = SrcUniformField_InterpData%VelHDot DstUniformField_InterpData%VelV = SrcUniformField_InterpData%VelV + DstUniformField_InterpData%VelVDot = SrcUniformField_InterpData%VelVDot DstUniformField_InterpData%VelGust = SrcUniformField_InterpData%VelGust + DstUniformField_InterpData%VelGustDot = SrcUniformField_InterpData%VelGustDot DstUniformField_InterpData%AngleH = SrcUniformField_InterpData%AngleH + DstUniformField_InterpData%AngleHDot = SrcUniformField_InterpData%AngleHDot DstUniformField_InterpData%AngleV = SrcUniformField_InterpData%AngleV + DstUniformField_InterpData%AngleVDot = SrcUniformField_InterpData%AngleVDot DstUniformField_InterpData%ShrH = SrcUniformField_InterpData%ShrH + DstUniformField_InterpData%ShrHDot = SrcUniformField_InterpData%ShrHDot DstUniformField_InterpData%ShrV = SrcUniformField_InterpData%ShrV + DstUniformField_InterpData%ShrVDot = SrcUniformField_InterpData%ShrVDot DstUniformField_InterpData%LinShrV = SrcUniformField_InterpData%LinShrV + DstUniformField_InterpData%LinShrVDot = SrcUniformField_InterpData%LinShrVDot DstUniformField_InterpData%CosAngleH = SrcUniformField_InterpData%CosAngleH DstUniformField_InterpData%SinAngleH = SrcUniformField_InterpData%SinAngleH DstUniformField_InterpData%CosAngleV = SrcUniformField_InterpData%CosAngleV @@ -854,17 +1296,22 @@ SUBROUTINE FlowField_PackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Indata Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! IData - Re_BufSz = Re_BufSz + 1 ! dt - Re_BufSz = Re_BufSz + 1 ! Time Re_BufSz = Re_BufSz + 1 ! VelH + Re_BufSz = Re_BufSz + 1 ! VelHDot Re_BufSz = Re_BufSz + 1 ! VelV + Re_BufSz = Re_BufSz + 1 ! VelVDot Re_BufSz = Re_BufSz + 1 ! VelGust + Re_BufSz = Re_BufSz + 1 ! VelGustDot Re_BufSz = Re_BufSz + 1 ! AngleH + Re_BufSz = Re_BufSz + 1 ! AngleHDot Re_BufSz = Re_BufSz + 1 ! AngleV + Re_BufSz = Re_BufSz + 1 ! AngleVDot Re_BufSz = Re_BufSz + 1 ! ShrH + Re_BufSz = Re_BufSz + 1 ! ShrHDot Re_BufSz = Re_BufSz + 1 ! ShrV + Re_BufSz = Re_BufSz + 1 ! ShrVDot Re_BufSz = Re_BufSz + 1 ! LinShrV + Re_BufSz = Re_BufSz + 1 ! LinShrVDot Re_BufSz = Re_BufSz + 1 ! CosAngleH Re_BufSz = Re_BufSz + 1 ! SinAngleH Re_BufSz = Re_BufSz + 1 ! CosAngleV @@ -896,28 +1343,38 @@ SUBROUTINE FlowField_PackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Indata Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf(Int_Xferred) = InData%IData - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%dt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Time - Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VelH Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VelHDot + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VelV Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VelVDot + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VelGust Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VelGustDot + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%AngleH Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AngleHDot + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%AngleV Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%AngleVDot + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%ShrH Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShrHDot + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%ShrV Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%ShrVDot + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%LinShrV Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%LinShrVDot + Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%CosAngleH Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%SinAngleH @@ -954,28 +1411,38 @@ SUBROUTINE FlowField_UnPackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Outd Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%IData = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%dt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Time = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 OutData%VelH = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%VelHDot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%VelV = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%VelVDot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%VelGust = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%VelGustDot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%AngleH = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%AngleHDot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%AngleV = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%AngleVDot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%ShrH = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%ShrHDot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%ShrV = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%ShrVDot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%LinShrV = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%LinShrVDot = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 OutData%CosAngleH = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%SinAngleH = ReKiBuf(Re_Xferred) From d58ffc395fb90962d1c9bd9e12f1968c7ce2b710 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 28 Dec 2022 15:18:51 +0000 Subject: [PATCH 05/51] inflowwind: add acceleration calc to IfW_FlowField This commit adds a flow field type specific initialization section. Currently only used for calculating acceleration when requested. --- modules/inflowwind/src/IfW_FlowField.f90 | 80 +++++++++++------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index d50290c20f..dec9d179b7 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -27,6 +27,7 @@ module IfW_FlowField use NWTC_Library use IfW_FlowField_Types +use FlowField implicit none private @@ -34,11 +35,6 @@ module IfW_FlowField type(ProgDesc), parameter :: IfW_FlowField_Ver = ProgDesc('IfW_FlowField', '', '') -integer(IntKi), parameter :: WindProfileType_None = -1, & !< don't add wind profile; already included in input - WindProfileType_Constant = 0, & !< constant wind - WindProfileType_Log = 1, & !< logarithmic - WindProfileType_PL = 2 !< power law - integer(IntKi), parameter :: ScaleMethod_None = 0, & !< no scaling ScaleMethod_Direct = 1, & !< direct scaling factors ScaleMethod_StdDev = 2 !< requested standard deviation @@ -101,25 +97,51 @@ subroutine IfW_FlowField_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) case (4) ! Binary Bladed-Style FF FF%FieldType = Grid_FieldType ! call Read_Bladed_Binary(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) + TmpErrStat = ErrID_Fatal + TmpErrMsg = "Binary Bladed Wind is not implemented" case (5) ! HAWC FF%FieldType = Grid_FieldType call HAWC_Init(InitInp%HAWC, InitInp%SumFileUnit, FF%Grid, InitOut%FileDat, TmpErrStat, TmpErrMsg) case (6) ! User Defined FF%FieldType = Grid_FieldType - + TmpErrStat = ErrID_Fatal + TmpErrMsg = "User Wind is not implemented" case (7) ! Native Bladed FF FF%FieldType = Grid_FieldType ! call Read_Bladed_Native(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) + TmpErrStat = ErrID_Fatal + TmpErrMsg = "Native Bladed Wind is not implemented" end select call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return + !---------------------------------------------------------------------------- + ! Field Type Initialization + !---------------------------------------------------------------------------- + + select case (FF%FieldType) + case (Uniform_FieldType) + if (InitInp%CalcAccel) then + call UniformField_CalcAccel(FF%Uniform, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + case (Grid_FieldType) + if (InitInp%CalcAccel) then + call GridField_CalcAccel(FF%Grid, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + end select + !---------------------------------------------------------------------------- ! Setup the coordinate transforms for rotating the wind field. !---------------------------------------------------------------------------- - ! Create the rotation matrices -- rotate from XYZ to X'Y'Z' (wind aligned along X) coordinates - ! Included in this rotation is the wind upflow (inclination) angle (rotation about Y axis) + ! Create the rotation matrices + ! rotate from XYZ to X'Y'Z' (wind aligned along X) coordinates + ! Includes the wind upflow (inclination) angle (rotation about Y axis) FF%RotToWind(1, :) = [cos(-FF%VFlowAngle)*cos(-FF%PropagationDir), & cos(-FF%VFlowAngle)*sin(-FF%PropagationDir), & -sin(-FF%VFlowAngle)] @@ -1057,47 +1079,17 @@ subroutine User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg -end subroutine - -subroutine GridField_CalcAccel(GF, ErrStat, ErrMsg) - type(GridFieldType), intent(in) :: GF - integer(IntKi), intent(out) :: ErrStat - character(*), intent(out) :: ErrMsg - - character(*), parameter :: RoutineName = "GridField_CalcAccel" - integer(IntKi) :: TmpErrStat - character(ErrMsgLen) :: TmpErrMsg - integer(IntKi) :: iy, iz, it - real(ReKi), allocatable :: time(:) - real(ReKi), allocatable :: vel(:) - - ! Allocate storage for time - call AllocAry(time, GF%NSteps, "storage for grid time", TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + character(*), parameter :: RoutineName = "User_Init" - ! Allocate storage for velocity - call AllocAry(vel, GF%NSteps, "storage for grid time", TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + ErrStat = ErrID_None + ErrMsg = "" - ! Allocate storage for acceleration grid - call AllocAry(GF%Acc, GF%NComp, GF%NYGrids, GF%NZGrids, GF%NSteps, & - 'grid-field velocity data', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return + UF%Dummy = 1 - ! If grid field includes tower grids, allocate storage for acceleration - if (GF%NTGrids > 0) then - call AllocAry(GF%VelTower, GF%NComp, GF%NTGrids, GF%NSteps, & - 'tower wind velocity data.', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return + if (SumFileUnit > 0) then + write (SumFileUnit, '(A)') InitInp%Dummy end if - ! Generate time - do it = 1, GF%NSteps - ! time(i) = - end do - end subroutine subroutine PopulateWindFileDatFromGridField(GridField, FileName, WindType, HasTower, FileDat) From fee05ac3e422cb69c2a1911ffd2ad0a1d2df3308 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 28 Dec 2022 21:35:30 +0000 Subject: [PATCH 06/51] nwtc-library: FlowField smooth Grid and ExtGrid This commit adds a smooth interpolation function for the FlowField GridField type which gives velocity and acceleration based on cubic hermite spline interpolation. An external grid field type was added to satisfy the 4Dext type from InflowWind. --- modules/nwtc-library/src/FlowField.f90 | 856 +++++++++++++------ modules/nwtc-library/src/FlowField.txt | 25 +- modules/nwtc-library/src/FlowField_Types.f90 | 543 ++++++++++-- 3 files changed, 1060 insertions(+), 364 deletions(-) diff --git a/modules/nwtc-library/src/FlowField.f90 b/modules/nwtc-library/src/FlowField.f90 index 49e28a5ba8..627ce34d20 100644 --- a/modules/nwtc-library/src/FlowField.f90 +++ b/modules/nwtc-library/src/FlowField.f90 @@ -51,11 +51,8 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel character(*), parameter :: RoutineName = "FlowField_GetVelAcc" integer(IntKi) :: i integer(IntKi) :: NumPoints - real(ReKi), dimension(3) :: PositionPrime + real(ReKi), dimension(:, :), allocatable :: Position type(UniformField_Interp) :: UFop - real(ReKi) :: DY, DZ, DT - real(ReKi), dimension(3, 8) :: P - logical :: Interp3D integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg @@ -65,6 +62,22 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel ! Get number of points to evaluate NumPoints = size(PositionXYZ, dim=2) + ! Allocate position array + call AllocAry(Position, 3, NumPoints, "Rotated position data", TmpErrStat, TmpErrMsg) + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + + ! Copy positions or transform based on wind box rotation + if (.not. FF%RotateWindBox) then + Position = PositionXYZ + else + do i = 1, NumPoints + Position(:, i) = GetPrimePosition(PositionXYZ(:, i)) + end do + end if + !TODO: Check that position, velocity, and acceleration are all the same shape !---------------------------------------------------------------------------- @@ -97,37 +110,25 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel UFop = UniformField_GetOP(FF%Uniform, Time) end if - if (.not. FF%RotateWindBox) then - if (.not. allocated(AccelUVW)) then - ! Velocity - do i = 1, NumPoints - VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionXYZ(:, i)) - end do - else - ! Velocity and acceleration - do i = 1, NumPoints - VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionXYZ(:, i)) - AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, PositionXYZ(:, i)) - end do - end if - - else ! Rotated wind box - - if (.not. allocated(AccelUVW)) then - ! Rotation, velocity - do i = 1, NumPoints - PositionPrime = GetPrimePosition(PositionXYZ(:, i)) - VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionPrime) - end do - else - ! Rotation, velocity, and acceleration - do i = 1, NumPoints - PositionPrime = GetPrimePosition(PositionXYZ(:, i)) - VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, PositionPrime) - AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, PositionPrime) - end do - end if - + ! Get velocity or velocity and acceleration + if (.not. allocated(AccelUVW)) then + do i = 1, NumPoints + if (Position(3, i) > 0.0_ReKi) then + VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, Position(:, i)) + else + VelocityUVW(:, i) = 0.0_ReKi + end if + end do + else + do i = 1, NumPoints + if (Position(3, i) > 0.0_ReKi) then + VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, Position(:, i)) + AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, Position(:, i)) + else + VelocityUVW(:, i) = 0.0_ReKi + AccelUVW(:, i) = 0.0_ReKi + end if + end do end if case (Grid_FieldType) @@ -136,112 +137,138 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel ! Grid Flow Field !------------------------------------------------------------------------- - if (.not. FF%RotateWindBox) then + ! Loop through points + do i = 1, NumPoints - if (.not. allocated(AccelUVW)) then - ! Velocity - do i = 1, NumPoints - if (PositionXYZ(3, i) <= 0.0_ReKi) then - VelocityUVW(:, i) = 0.0_ReKi - cycle - end if - call GridField_GetInterp(FF%Grid, Time, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D, TmpErrStat, TmpErrMsg) - if (TmpErrStat >= AbortErrLev) then - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - return - end if - VelocityUVW(:, i) = GridField_GetVel(FF%Grid, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D) - end do - else - ! Velocity and acceleration - do i = 1, NumPoints - if (PositionXYZ(3, i) <= 0.0_ReKi) then - VelocityUVW(:, i) = 0.0_ReKi - AccelUVW(:, i) = 0.0_Reki - cycle - end if - call GridField_GetInterp(FF%Grid, Time, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D, TmpErrStat, TmpErrMsg) - if (TmpErrStat >= AbortErrLev) then - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - return - end if - VelocityUVW(:, i) = GridField_GetVel(FF%Grid, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D) - AccelUVW(:, i) = GridField_GetAcc(FF%Grid, PositionXYZ(:, i), DY, DZ, DT, P, Interp3D) - end do + ! If height is less than zero, set velocity to zero + if (Position(3, i) <= 0.0_ReKi) then + VelocityUVW(:, i) = 0.0_ReKi + if (allocated(AccelUVW)) AccelUVW(:, i) = 0.0_ReKi + cycle end if - else ! Rotated wind box - + ! Get velocity or velocity and acceleration if (.not. allocated(AccelUVW)) then - ! Velocity (rotated) - do i = 1, NumPoints - PositionPrime = GetPrimePosition(PositionXYZ(:, i)) - if (PositionPrime(3) <= ReKi) then - VelocityUVW(:, i) = 0.0_ReKi - cycle - end if - call GridField_GetInterp(FF%Grid, Time, PositionPrime, DY, DZ, DT, P, Interp3D, TmpErrStat, TmpErrMsg) - if (TmpErrStat >= AbortErrLev) then - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - return - end if - VelocityUVW(:, i) = matmul(FF%RotFromWind, GridField_GetVel(FF%Grid, PositionPrime, DY, DZ, DT, P, Interp3D)) - end do + call GridField_GetVel(FF%Grid, Time, Position(:, i), VelocityUVW(:, i), TmpErrStat, TmpErrMsg) else - ! Velocity and acceleration (rotated) - do i = 1, NumPoints - ! Get rotated coordinates - PositionPrime = GetPrimePosition(PositionXYZ(:, i)) - if (PositionPrime(3) <= ReKi) then - VelocityUVW(:, i) = 0.0_ReKi - AccelUVW(:, i) = 0.0_ReKi - cycle - end if - call GridField_GetInterp(FF%Grid, Time, PositionPrime, DY, DZ, DT, P, Interp3D, TmpErrStat, TmpErrMsg) - if (TmpErrStat >= AbortErrLev) then - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - return - end if - VelocityUVW(:, i) = matmul(FF%RotFromWind, GridField_GetVel(FF%Grid, PositionPrime, DY, DZ, DT, P, Interp3D)) - AccelUVW(:, i) = matmul(FF%RotFromWind, GridField_GetAcc(FF%Grid, PositionPrime, DY, DZ, DT, P, Interp3D)) - end do + call GridField_GetVelAcc(FF%Grid, Time, Position(:, i), VelocityUVW(:, i), AccelUVW(:, i), TmpErrStat, TmpErrMsg) + end if + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return end if + + end do + + ! Add mean wind speed after interpolation if flag is set + if (FF%Grid%AddMeanAfterInterp) then + do i = 1, NumPoints + VelocityUVW(1, i) = VelocityUVW(1, i) + GetMeanVelocity(FF%Grid, Position(3, i)) + end do end if - case (User_FieldType) + case (ExtGrid_FieldType) !------------------------------------------------------------------------- - ! User Flow Field + ! External Grid Flow Field !------------------------------------------------------------------------- - call SetErrStat(ErrID_Fatal, "User Field not implemented", ErrStat, ErrMsg, RoutineName) - return + ! If external field is not allocated, return error + if (.not. allocated(FF%ExtGrid%Vel)) then + call SetErrStat(ErrID_Fatal, "External Grid Field not allocated", ErrStat, ErrMsg, RoutineName) + return + end if + + ! Loop through points + do i = 1, NumPoints - case (External_FieldType) + ! If height less than or equal to zero, set velocity to zero + if (Position(3, i) <= 0.0_ReKi) then + VelocityUVW(:, i) = 0.0_ReKi + cycle + end if + + call ExtGridField_GetVel(FF%ExtGrid, Time, Position(:, i), VelocityUVW(:, i), TmpErrStat, TmpErrMsg) + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + end do + + case (ExtPoint_FieldType) !------------------------------------------------------------------------- - ! External Flow Field + ! External Grid Flow Field !------------------------------------------------------------------------- ! If external field is not allocated, return error - if (.not. allocated(FF%external%Vel)) then - call SetErrStat(ErrID_Fatal, "External Field not allocated", ErrStat, ErrMsg, RoutineName) + if (.not. allocated(FF%ExtPoint%Vel)) then + call SetErrStat(ErrID_Fatal, "External Point Field not allocated", ErrStat, ErrMsg, RoutineName) return end if - VelocityUVW = FF%external%Vel(:, IStart:IStart + NumPoints - 1) + ! Set velocities directly from velocity array + VelocityUVW = FF%ExtPoint%Vel(:, IStart:IStart + NumPoints - 1) + + case (User_FieldType) + + !------------------------------------------------------------------------- + ! User Flow Field + !------------------------------------------------------------------------- + + call SetErrStat(ErrID_Fatal, "User Field not to be implemented", ErrStat, ErrMsg, RoutineName) + return case default call SetErrStat(ErrID_Fatal, "Invalid FieldType "//trim(num2lstr(FF%FieldType)), ErrStat, ErrMsg, RoutineName) return end select + !---------------------------------------------------------------------------- + ! If wind box was rotated, apply rotation to velocity/acceleration + !---------------------------------------------------------------------------- + + if (FF%RotateWindBox) then + if (.not. allocated(AccelUVW)) then + do i = 1, NumPoints + VelocityUVW(:, i) = matmul(FF%RotFromWind, VelocityUVW(:, i)) + end do + else + do i = 1, NumPoints + VelocityUVW(:, i) = matmul(FF%RotFromWind, VelocityUVW(:, i)) + AccelUVW(:, i) = matmul(FF%RotFromWind, AccelUVW(:, i)) + end do + end if + end if + contains - pure function GetPrimePosition(Position) result(PrimePosition) - real(ReKi), dimension(3), intent(in) :: Position - real(ReKi), dimension(3) :: PrimePosition - PrimePosition = matmul(FF%RotToWind, (Position - FF%RefPosition)) + FF%RefPosition + pure function GetPrimePosition(Pos) result(PrimePos) + real(ReKi), dimension(3), intent(in) :: Pos + real(ReKi), dimension(3) :: PrimePos + PrimePos = matmul(FF%RotToWind, (Pos - FF%RefPosition)) + FF%RefPosition + end function + + function GetMeanVelocity(GF, PosZ) result(U) + type(GridFieldType), intent(in) :: GF + real(ReKi), intent(in) :: PosZ + real(ReKi) :: U + select case (GF%WindProfileType) + case (WindProfileType_None) + U = 0.0_ReKi + case (WindProfileType_PL) + U = GF%MeanWS*(PosZ/GF%RefHeight)**GF%PLExp ! [IEC 61400-1 6.3.1.2 (10)] + case (WindProfileType_Log) + if (.not. EqualRealNos(GF%RefHeight, GF%Z0) .and. PosZ > 0.0_ReKi) then + U = GF%MeanWS*log(PosZ/GF%Z0)/log(GF%RefHeight/GF%Z0) + else + U = 0.0_ReKi + end if + case (WindProfileType_Constant) + U = GF%MeanWS + case default + U = 0.0_ReKi + end select end function end subroutine @@ -258,28 +285,18 @@ pure function UniformField_GetVel(UF, op, Position) result(Velocity) real(ReKi) :: V1 real(ReKi) :: V1_rotate, VZ_rotate - if (Position(3) > 0.0_ReKi) then - - ! Calculate horizontal velocity if position is above ground - V1 = op%VelH*((Position(3)/UF%RefHeight)**op%ShrV & ! power-law wind shear - + (op%ShrH*(Position(2)*op%CosAngleH + Position(1)*op%SinAngleH) & ! horizontal linear shear - + op%LinShrV*(Position(3) - UF%RefHeight))/UF%RefLength) & ! vertical linear shear - + op%VelGust ! gust speed + ! Calculate horizontal velocity if position is above ground + V1 = op%VelH*((Position(3)/UF%RefHeight)**op%ShrV & ! power-law wind shear + + (op%ShrH*(Position(2)*op%CosAngleH + Position(1)*op%SinAngleH) & ! horizontal linear shear + + op%LinShrV*(Position(3) - UF%RefHeight))/UF%RefLength) & ! vertical linear shear + + op%VelGust ! gust speed - ! Apply upflow angle - V1_rotate = op%CosAngleV*V1 - op%SinAngleV*op%VelV - VZ_rotate = op%SinAngleV*V1 + op%CosAngleV*op%VelV + ! Apply upflow angle + V1_rotate = op%CosAngleV*V1 - op%SinAngleV*op%VelV + VZ_rotate = op%SinAngleV*V1 + op%CosAngleV*op%VelV - ! Apply wind direction - Velocity = [V1_rotate*op%CosAngleH, -V1_rotate*op%SinAngleH, VZ_rotate] - - else - - ! Height is below ground, set velocity to zero. - ! Removed error check to be consistent with full field method - Velocity = 0.0_ReKi - - end if + ! Apply wind direction + Velocity = [V1_rotate*op%CosAngleH, -V1_rotate*op%SinAngleH, VZ_rotate] end function @@ -618,143 +635,229 @@ subroutine CalcCubicSplineDeriv(x, y, dy) end subroutine -function GridField_GetVel(GF, Position, DY, DZ, DT, P, Interp3D) result(Velocity) - - type(GridFieldType), intent(in) :: GF !< Grid-Field data - real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value - real(ReKi), intent(in) :: DY, DZ, DT !< Weights [-1,1] - real(ReKi), dimension(3, 8), intent(in) :: P !< Interp points - logical, intent(in) :: Interp3D !< flag for 3D vs 2D interp - real(ReKi) :: Velocity(3) !< The U, V, W velocities +subroutine GridField_GetVel(GF, Time, Position, Velocity, ErrStat, ErrMsg) + type(GridFieldType), intent(in) :: GF !< Grid-Field data + real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value + real(DbKi), intent(in) :: Time !< Weights [-1,1] + real(ReKi), intent(out) :: Velocity(3) !< The U, V, W velocities + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = "GridField_GetVel" + character(*), parameter :: RoutineName = "GridField_GetVel" + real(ReKi) :: DY, DZ, DT ! Weights [-1,1] + real(ReKi), dimension(8, 3) :: P ! Interp points + real(ReKi), dimension(8) :: N ! Shape function values - real(ReKi) :: N(8, 1) ! Shape function values + integer(IntKi) :: IT_LO, IT_HI + integer(IntKi) :: IY_LO, IY_HI + integer(IntKi) :: IZ_LO, IZ_HI + integer(IntKi) :: ic - if (Interp3D) then - - ! Get 3D interpolation weights - N(1, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) - N(2, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) - N(3, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) - N(4, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) - N(5, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) - N(6, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) - N(7, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) - N(8, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) - N(1:4, 1) = N(1:4, 1)*(1.0_ReKi - DT)/8.0_ReKi - N(5:8, 1) = N(5:8, 1)*(1.0_ReKi + DT)/8.0_ReKi - - ! Calculate velocity via matrix multiplication - Velocity = pack(matmul(P, N), .true.) + logical :: OnGrid + real(ReKi) :: TimeShifted + integer(IntKi) :: boundStat - else - - ! Get 2D interpolation weights - N(1, 1) = (1.0_ReKi - DZ)*(1.0_ReKi - DT)/4.0_ReKi - N(2, 1) = (1.0_ReKi + DZ)*(1.0_ReKi - DT)/4.0_ReKi - N(3, 1) = (1.0_ReKi - DZ)*(1.0_ReKi + DT)/4.0_ReKi - N(4, 1) = (1.0_ReKi + DZ)*(1.0_ReKi + DT)/4.0_ReKi + ErrStat = ErrID_None + ErrMsg = "" - ! Calculate velocity via matrix multiplication - Velocity = pack(matmul(P(:, 1:4), N(1:4, 1)), .true.) + !---------------------------------------------------------------------------- + ! Find grid bounds in Time and Z + !---------------------------------------------------------------------------- + ! Get grid time bounds + boundStat = GridField_GetBoundsT(GF, Time, Position(1), DT, IT_LO, IT_HI, TimeShifted) + if (boundStat > 0) then + ErrMsg = ' Error: GF wind array was exhausted at '//TRIM(Num2LStr(TIME))// & + ' seconds (trying to access data at '//TRIM(Num2LStr(TimeShifted))//' seconds).' + ErrStat = ErrID_Fatal + return end if - ! Add mean wind speed after interpolation if flag is set - if (GF%AddMeanAfterInterp) then - Velocity(1) = Velocity(1) + GetMeanVelocity(Position(3)) + ! Get grid Z bounds + boundStat = GridField_GetBoundsZ(GF, Position(3), DZ, IZ_LO, IZ_HI, OnGrid) + if (boundStat < 0) then + ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction '// & + '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' + ErrStat = ErrID_Fatal + return + else if (boundStat > 0) then + ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction (Z='// & + TRIM(Num2LStr(Position(3)))//' m is above the grid).' + ErrStat = ErrID_Fatal + return end if -contains + !---------------------------------------------------------------------------- + ! Interpolate + !---------------------------------------------------------------------------- - function GetMeanVelocity(PosZ) result(U) - real(ReKi), intent(in) :: PosZ - real(ReKi) :: U - select case (GF%WindProfileType) - case (WindProfileType_None) - U = 0.0_ReKi - case (WindProfileType_PL) - U = GF%MeanWS*(PosZ/GF%RefHeight)**GF%PLExp ! [IEC 61400-1 6.3.1.2 (10)] - case (WindProfileType_Log) - if (.not. EqualRealNos(GF%RefHeight, GF%Z0) .and. PosZ > 0.0_ReKi) then - U = GF%MeanWS*log(PosZ/GF%Z0)/log(GF%RefHeight/GF%Z0) - else - U = 0.0_ReKi - end if - case (WindProfileType_Constant) - U = GF%MeanWS - case default - U = 0.0_ReKi - end select - end function + if (OnGrid .or. GF%InterpTower) then -end function + ! Get grid Y bounds + boundStat = GridField_GetBoundsY(GF, Position(2), DY, IY_LO, IY_HI) + if (boundStat /= 0) then + ErrMsg = ' GF wind array boundaries violated: Grid too small in Y direction. Y='// & + TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*GF%YHWid))// & + ', '//TRIM(Num2LStr(GF%YHWid))//']' + ErrStat = ErrID_Fatal + return + end if -function GridField_GetAcc(GF, Position, DY, DZ, DT, P, Interp3D) result(Accel) + if (OnGrid) then - type(GridFieldType), intent(in) :: GF - real(ReKi), dimension(3), intent(in) :: Position - real(ReKi), intent(in) :: DY, DZ, DT !< Weights [-1,1] - real(ReKi), dimension(3, 8), intent(in) :: P !< Interp points - logical, intent(in) :: Interp3D !< flag for 3D vs 2D interp - real(ReKi), dimension(3) :: Accel + ! Get points from the grid + P(1, :) = GF%Vel(:, IY_LO, IZ_LO, IT_LO) + P(2, :) = GF%Vel(:, IY_HI, IZ_LO, IT_LO) + P(3, :) = GF%Vel(:, IY_LO, IZ_HI, IT_LO) + P(4, :) = GF%Vel(:, IY_HI, IZ_HI, IT_LO) + P(5, :) = GF%Vel(:, IY_LO, IZ_LO, IT_HI) + P(6, :) = GF%Vel(:, IY_HI, IZ_LO, IT_HI) + P(7, :) = GF%Vel(:, IY_LO, IZ_HI, IT_HI) + P(8, :) = GF%Vel(:, IY_HI, IZ_HI, IT_HI) - character(*), parameter :: RoutineName = "GridField_GetAcc" - real(ReKi) :: N(8, 1) + else if (GF%InterpTower) then - if (Interp3D) then + ! Get points from grid bottom and ground + P(1, :) = 0.0_ReKi !GF%Vel(:, IY_LO, IZ_LO, IT_LO) + P(2, :) = 0.0_ReKi !GF%Vel(:, IY_HI, IZ_LO, IT_LO) + P(3, :) = GF%Vel(:, IY_LO, IZ_HI, IT_LO) + P(4, :) = GF%Vel(:, IY_HI, IZ_HI, IT_LO) + P(5, :) = 0.0_ReKi !GF%Vel(:, IY_HI, IZ_LO, IT_HI) + P(6, :) = 0.0_ReKi !GF%Vel(:, IY_LO, IZ_LO, IT_HI) + P(7, :) = GF%Vel(:, IY_LO, IZ_HI, IT_HI) + P(8, :) = GF%Vel(:, IY_HI, IZ_HI, IT_HI) + + end if ! Get 3D interpolation weights - N(1, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) - N(2, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) - N(3, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) - N(4, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) - N(5, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) - N(6, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) - N(7, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) - N(8, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) - N(1:4, 1) = N(1:4, 1)/(-4.0_ReKi*GF%DTime) - N(5:8, 1) = N(5:8, 1)/(4.0_ReKi*GF%DTime) - - ! Calculate Accel via matrix multiplication - Accel = pack(matmul(P, N), .true.) + N(1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) + N(2) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) + N(3) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) + N(4) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) + N(5) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) + N(6) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) + N(7) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) + N(8) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) + N(1:4) = N(1:4)*(1.0_ReKi - DT)/8.0_ReKi + N(5:8) = N(5:8)*(1.0_ReKi + DT)/8.0_ReKi + + ! Calculate velocity + do ic = 1, 3 + Velocity(ic) = dot_product(P(:, ic), N) + end do else - ! Get 2D interpolation weights - N(1, 1) = (1.0_ReKi - DZ)/(-2.0_ReKi*GF%DTime) - N(2, 1) = (1.0_ReKi + DZ)/(-2.0_ReKi*GF%DTime) - N(3, 1) = (1.0_ReKi - DZ)/(2.0_ReKi*GF%DTime) - N(4, 1) = (1.0_ReKi + DZ)/(2.0_ReKi*GF%DTime) + if (IZ_HI <= GF%NTGrids) then + ! In tower grid + P(1, :) = GF%VelTower(:, IZ_LO, IT_LO) + P(2, :) = GF%VelTower(:, IZ_HI, IT_LO) + P(3, :) = GF%VelTower(:, IZ_LO, IT_HI) + P(4, :) = GF%VelTower(:, IZ_HI, IT_HI) + else + ! Between tower grid and ground + P(1, :) = GF%VelTower(:, IZ_LO, IT_LO) + P(2, :) = 0.0_ReKi + P(3, :) = GF%VelTower(:, IZ_LO, IT_HI) + P(4, :) = 0.0_ReKi + end if - ! Calculate Accel via matrix multiplication - Accel = pack(matmul(P(:, 1:4), N(1:4, 1)), .true.) + ! Get 2D interpolation weights + N(1) = (1.0_ReKi - DZ)*(1.0_ReKi - DT)/4.0_ReKi + N(2) = (1.0_ReKi + DZ)*(1.0_ReKi - DT)/4.0_ReKi + N(3) = (1.0_ReKi - DZ)*(1.0_ReKi + DT)/4.0_ReKi + N(4) = (1.0_ReKi + DZ)*(1.0_ReKi + DT)/4.0_ReKi + + ! Calculate velocity + do ic = 1, 3 + Velocity(ic) = dot_product(P(1:4, ic), N(1:4)) + end do end if -end function - -subroutine GridField_GetInterp(GF, Time, Position, DY, DZ, DT, P, Interp3D, ErrStat, ErrMsg) - - type(GridFieldType), intent(in) :: GF !< Grid-Field data - real(DbKi), intent(in) :: Time !< time (s) - real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value - real(ReKi), intent(out) :: DY, DZ, DT !< - real(ReKi), intent(out) :: P(3, 8) - logical, intent(out) :: Interp3D - integer(IntKi), intent(out) :: ErrStat !< error status - character(*), intent(out) :: ErrMsg !< error message - - character(*), parameter :: RoutineName = "GridField_GetInterp" - - integer(IntKi) :: IT_LO, IT_HI - integer(IntKi) :: IY_LO, IY_HI - integer(IntKi) :: IZ_LO, IZ_HI +end subroutine - logical :: OnGrid - real(ReKi) :: TimeShifted - integer(IntKi) :: boundStat +! function GridField_GetAcc(GF, Position, DY, DZ, DT, P, Interp3D) result(Accel) + +! type(GridFieldType), intent(in) :: GF +! real(ReKi), dimension(3), intent(in) :: Position +! real(ReKi), intent(in) :: DY, DZ, DT !< Weights [-1,1] +! real(ReKi), dimension(3, 8), intent(in) :: P !< Interp points +! logical, intent(in) :: Interp3D !< flag for 3D vs 2D interp +! real(ReKi), dimension(3) :: Accel + +! character(*), parameter :: RoutineName = "GridField_GetAcc" +! real(ReKi) :: N(8, 1) + +! if (Interp3D) then + +! ! Get 3D interpolation weights +! N(1, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) +! N(2, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) +! N(3, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) +! N(4, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) +! N(5, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) +! N(6, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) +! N(7, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) +! N(8, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) +! N(1:4, 1) = N(1:4, 1)/(-4.0_ReKi*GF%DTime) +! N(5:8, 1) = N(5:8, 1)/(4.0_ReKi*GF%DTime) + +! ! Calculate Accel via matrix multiplication +! Accel = pack(matmul(P, N), .true.) + +! else + +! ! Get 2D interpolation weights +! N(1, 1) = (1.0_ReKi - DZ)/(-2.0_ReKi*GF%DTime) +! N(2, 1) = (1.0_ReKi + DZ)/(-2.0_ReKi*GF%DTime) +! N(3, 1) = (1.0_ReKi - DZ)/(2.0_ReKi*GF%DTime) +! N(4, 1) = (1.0_ReKi + DZ)/(2.0_ReKi*GF%DTime) + +! ! Calculate Accel via matrix multiplication +! Accel = pack(matmul(P(:, 1:4), N(1:4, 1)), .true.) + +! end if + +! end function + +! subroutine GridField_GetInterp(GF, Time, Position, DY, DZ, DT, P, Interp3D, ErrStat, ErrMsg) + +! type(GridFieldType), intent(in) :: GF !< Grid-Field data +! real(DbKi), intent(in) :: Time !< time (s) +! real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value +! real(ReKi), intent(out) :: DY, DZ, DT !< +! real(ReKi), intent(out) :: P(3, 8) +! logical, intent(out) :: Interp3D +! integer(IntKi), intent(out) :: ErrStat !< error status +! character(*), intent(out) :: ErrMsg !< error message + +! character(*), parameter :: RoutineName = "GridField_GetInterp" + +! end subroutine + +subroutine GridField_GetVelAcc(GF, Time, Position, Velocity, Accel, ErrStat, ErrMsg) + + type(GridFieldType), intent(in) :: GF !< Grid-Field data + real(DbKi), intent(in) :: Time !< time (s) + real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value + real(ReKi), intent(out) :: Velocity(3) !< + real(ReKi), intent(out) :: Accel(3) !< + integer(IntKi), intent(out) :: ErrStat !< error status + character(*), intent(out) :: ErrMsg !< error message + + character(*), parameter :: RoutineName = "GridField_GetSmoothInterp" + real(ReKi) :: Xi_Y, Xi_Z, Xi_T ! isoparametric coordinates (Y,Z,T) + integer(IntKi) :: IY_Lo, IY_Hi + integer(IntKi) :: IZ_Lo, IZ_Hi + integer(IntKi) :: IT_Lo, IT_Hi + integer(IntKi) :: IT, IC + real(ReKi) :: V(4, 3, 2), A(4, 3, 2), N(4) + real(ReKi) :: P(3, 2), PP(3, 2) + real(ReKi) :: h, t, C1, C2, C3, C4 + logical :: OnGrid + real(ReKi) :: TimeShifted + integer(IntKi) :: boundStat ErrStat = ErrID_None ErrMsg = "" @@ -764,7 +867,7 @@ subroutine GridField_GetInterp(GF, Time, Position, DY, DZ, DT, P, Interp3D, ErrS !---------------------------------------------------------------------------- ! Get grid time bounds - boundStat = GridField_GetBoundsT(GF, Time, Position(1), DT, IT_LO, IT_HI, TimeShifted) + boundStat = GridField_GetBoundsT(GF, Time, Position(1), Xi_T, IT_Lo, IT_Hi, TimeShifted) if (boundStat > 0) then ErrMsg = ' Error: GF wind array was exhausted at '//TRIM(Num2LStr(TIME))// & ' seconds (trying to access data at '//TRIM(Num2LStr(TimeShifted))//' seconds).' @@ -773,7 +876,7 @@ subroutine GridField_GetInterp(GF, Time, Position, DY, DZ, DT, P, Interp3D, ErrS end if ! Get grid Z bounds - boundStat = GridField_GetBoundsZ(GF, Position(3), DZ, IZ_LO, IZ_HI, OnGrid) + boundStat = GridField_GetBoundsZ(GF, Position(3), Xi_Z, IZ_Lo, IZ_Hi, OnGrid) if (boundStat < 0) then ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction '// & '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' @@ -792,11 +895,8 @@ subroutine GridField_GetInterp(GF, Time, Position, DY, DZ, DT, P, Interp3D, ErrS if (OnGrid .or. GF%InterpTower) then - ! Set flag for 3D interpolation to true - Interp3D = .true. - ! Get grid Y bounds - boundStat = GridField_GetBoundsY(GF, Position(2), DY, IY_LO, IY_HI) + boundStat = GridField_GetBoundsY(GF, Position(2), Xi_Y, IY_Lo, IY_Hi) if (boundStat /= 0) then ErrMsg = ' GF wind array boundaries violated: Grid too small in Y direction. Y='// & TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*GF%YHWid))// & @@ -807,51 +907,130 @@ subroutine GridField_GetInterp(GF, Time, Position, DY, DZ, DT, P, Interp3D, ErrS if (OnGrid) then - ! Get points from the grid - P(:, 1) = GF%Vel(:, IY_LO, IZ_LO, IT_LO) - P(:, 2) = GF%Vel(:, IY_HI, IZ_LO, IT_LO) - P(:, 3) = GF%Vel(:, IY_LO, IZ_HI, IT_LO) - P(:, 4) = GF%Vel(:, IY_HI, IZ_HI, IT_LO) - P(:, 5) = GF%Vel(:, IY_LO, IZ_LO, IT_HI) - P(:, 6) = GF%Vel(:, IY_HI, IZ_LO, IT_HI) - P(:, 7) = GF%Vel(:, IY_LO, IZ_HI, IT_HI) - P(:, 8) = GF%Vel(:, IY_HI, IZ_HI, IT_HI) + ! Get velocities from the grid + V(1, :, 1) = GF%Vel(:, IY_Lo, IZ_Lo, IT_Lo) + V(2, :, 1) = GF%Vel(:, IY_Hi, IZ_Lo, IT_Lo) + V(3, :, 1) = GF%Vel(:, IY_Lo, IZ_Hi, IT_Lo) + V(4, :, 1) = GF%Vel(:, IY_Hi, IZ_Hi, IT_Lo) + V(1, :, 2) = GF%Vel(:, IY_Lo, IZ_Lo, IT_Hi) + V(2, :, 2) = GF%Vel(:, IY_Hi, IZ_Lo, IT_Hi) + V(3, :, 2) = GF%Vel(:, IY_Lo, IZ_Hi, IT_Hi) + V(4, :, 2) = GF%Vel(:, IY_Hi, IZ_Hi, IT_Hi) + + ! Get accelerations from the grid + A(1, :, 1) = GF%Acc(:, IY_Lo, IZ_Lo, IT_Lo) + A(2, :, 1) = GF%Acc(:, IY_Hi, IZ_Lo, IT_Lo) + A(3, :, 1) = GF%Acc(:, IY_Lo, IZ_Hi, IT_Lo) + A(4, :, 1) = GF%Acc(:, IY_Hi, IZ_Hi, IT_Lo) + A(1, :, 2) = GF%Acc(:, IY_Lo, IZ_Lo, IT_Hi) + A(2, :, 2) = GF%Acc(:, IY_Hi, IZ_Lo, IT_Hi) + A(3, :, 2) = GF%Acc(:, IY_Lo, IZ_Hi, IT_Hi) + A(4, :, 2) = GF%Acc(:, IY_Hi, IZ_Hi, IT_Hi) else if (GF%InterpTower) then - ! Get points from grid bottom and ground - P(:, 1) = 0.0_ReKi !GF%Vel(:, IY_LO, IZ_LO, IT_LO) - P(:, 2) = 0.0_ReKi !GF%Vel(:, IY_HI, IZ_LO, IT_LO) - P(:, 3) = GF%Vel(:, IY_LO, IZ_HI, IT_LO) - P(:, 4) = GF%Vel(:, IY_HI, IZ_HI, IT_LO) - P(:, 5) = 0.0_ReKi !GF%Vel(:, IY_HI, IZ_LO, IT_HI) - P(:, 6) = 0.0_ReKi !GF%Vel(:, IY_LO, IZ_LO, IT_HI) - P(:, 7) = GF%Vel(:, IY_LO, IZ_HI, IT_HI) - P(:, 8) = GF%Vel(:, IY_HI, IZ_HI, IT_HI) + ! Get velocities from the grid + V(1, :, 1) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Lo) + V(2, :, 1) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Lo) + V(3, :, 1) = GF%Vel(:, IY_Lo, IZ_Hi, IT_Lo) + V(4, :, 1) = GF%Vel(:, IY_Hi, IZ_Hi, IT_Lo) + V(1, :, 2) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Hi) + V(2, :, 2) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Hi) + V(3, :, 2) = GF%Vel(:, IY_Lo, IZ_Hi, IT_Hi) + V(4, :, 2) = GF%Vel(:, IY_Hi, IZ_Hi, IT_Hi) + + ! Get accelerations from the grid + A(1, :, 1) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Lo) + A(2, :, 1) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Lo) + A(3, :, 1) = GF%Acc(:, IY_Lo, IZ_Hi, IT_Lo) + A(4, :, 1) = GF%Acc(:, IY_Hi, IZ_Hi, IT_Lo) + A(1, :, 2) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Hi) + A(2, :, 2) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Hi) + A(3, :, 2) = GF%Acc(:, IY_Lo, IZ_Hi, IT_Hi) + A(4, :, 2) = GF%Acc(:, IY_Hi, IZ_Hi, IT_Hi) end if - else + ! Get interpolation weights + N(1) = (1.0_ReKi - Xi_Y)*(1.0_ReKi - Xi_Z)/4.0_ReKi + N(2) = (1.0_ReKi + Xi_Y)*(1.0_ReKi - Xi_Z)/4.0_ReKi + N(3) = (1.0_ReKi - Xi_Y)*(1.0_ReKi + Xi_Z)/4.0_ReKi + N(4) = (1.0_ReKi + Xi_Y)*(1.0_ReKi + Xi_Z)/4.0_ReKi + + ! Calculate velocity and acceleration at lo and hi time + do IT = 1, 2 + do IC = 1, 3 + P(IC, IT) = dot_product(V(:, IC, IT), N) + PP(IC, IT) = dot_product(A(:, IC, IT), N) + end do + end do - ! Set flag for 3D interpolation to false for 2D - Interp3D = .false. + else if (IZ_HI <= GF%NTGrids) then + ! In tower grid - P(:, 1) = GF%VelTower(:, IZ_LO, IT_LO) - P(:, 2) = GF%VelTower(:, IZ_HI, IT_LO) - P(:, 3) = GF%VelTower(:, IZ_LO, IT_HI) - P(:, 4) = GF%VelTower(:, IZ_HI, IT_HI) + V(1, :, 1) = GF%VelTower(:, IZ_LO, IT_LO) + V(2, :, 1) = GF%VelTower(:, IZ_HI, IT_LO) + V(1, :, 2) = GF%VelTower(:, IZ_LO, IT_HI) + V(2, :, 2) = GF%VelTower(:, IZ_HI, IT_HI) + + A(1, :, 1) = GF%AccTower(:, IZ_LO, IT_LO) + A(2, :, 1) = GF%AccTower(:, IZ_HI, IT_LO) + A(1, :, 2) = GF%AccTower(:, IZ_LO, IT_HI) + A(2, :, 2) = GF%AccTower(:, IZ_HI, IT_HI) + else + ! Between tower grid and ground - P(:, 1) = GF%VelTower(:, IZ_LO, IT_LO) - P(:, 2) = 0.0_ReKi - P(:, 3) = GF%VelTower(:, IZ_LO, IT_HI) - P(:, 4) = 0.0_ReKi + V(1, :, 1) = GF%VelTower(:, IZ_LO, IT_LO) + V(2, :, 1) = 0.0_ReKi + V(1, :, 2) = GF%VelTower(:, IZ_LO, IT_HI) + V(2, :, 2) = 0.0_ReKi + + ! Between tower grid and ground + A(1, :, 1) = GF%AccTower(:, IZ_LO, IT_LO) + A(2, :, 1) = 0.0_ReKi + A(1, :, 2) = GF%AccTower(:, IZ_LO, IT_HI) + A(2, :, 2) = 0.0_ReKi + end if + ! Get interpolation weights + N(1) = (1.0_ReKi - Xi_Z)/2.0_ReKi + N(2) = (1.0_ReKi + Xi_Z)/2.0_ReKi + + ! Calculate velocity and acceleration at lo and hi time + do IT = 1, 2 + do IC = 1, 3 + P(IC, IT) = dot_product(V(1:2, IC, IT), N(1:2)) + PP(IC, IT) = dot_product(A(1:2, IC, IT), N(1:2)) + end do + end do + end if + !---------------------------------------------------------------------------- + ! Smooth velocity and acceleration using cubic hermite spline + !---------------------------------------------------------------------------- + + h = GF%DTime + t = (Xi_T + 1)/2.0_ReKi + + C1 = 2.0_ReKi*t*t*t - 3.0_ReKi*t*t + 1.0_ReKi + C2 = (t*t*t - 2.0_ReKi*t*t + t)*h + C3 = -2.0_ReKi*t*t*t + 3.0_ReKi*t*t + C4 = (t*t*t - t*t)*h + + Velocity = C1*P(:, 1) + C2*PP(:, 1) + C3*P(:, 2) + C4*PP(:, 2) + + C1 = (6.0_ReKi*t*t - 6.0_ReKi*t)/h + C2 = 3.0_ReKi*t*t - 4.0_ReKi*t + 1.0_ReKi + C3 = -C1 + C4 = 3.0_ReKi*t*t - 2.0_ReKi*t + + Accel = C1*P(:, 1) + C2*PP(:, 1) + C3*P(:, 2) + C4*PP(:, 2) + end subroutine function GridField_GetBoundsY(GF, PosY, DY, IY_LO, IY_HI) result(stat) @@ -1156,4 +1335,125 @@ subroutine CalcCubicSplineDeriv(h, y, dy) end subroutine +subroutine ExtGridField_GetVel(EGF, Time, Position, Velocity, ErrStat, ErrMsg) + + type(ExtGridFieldType), intent(in) :: EGF !< External grid-field data + real(DbKi), intent(in) :: Time !< time to get value + real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value + real(ReKi), intent(out) :: Velocity(3) !< The U, V, W velocities + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = "ExtGridField_GetVel" + + integer(IntKi) :: Indx_Lo(4) ! index associated with lower bound of dimension 1-4 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + integer(IntKi) :: Indx_Hi(4) ! index associated with upper bound of dimension 1-4 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) + real(ReKi) :: xi(4) ! isoparametric coordinates + real(ReKi) :: N(16, 1) ! Shape function + real(ReKi) :: P(3, 16) ! Point values + real(ReKi) :: tmp + integer(IntKi) :: i + + ErrStat = ErrID_None + ErrMsg = "" + + !---------------------------------------------------------------------------- + ! Find the bounding indices for XYZ position + !---------------------------------------------------------------------------- + + do i = 1, 3 + tmp = (Position(i) - EGF%pZero(i))/EGF%delta(i) + Indx_Lo(i) = INT(tmp) + 1 ! convert REAL to INTEGER, then add one since our grid indices start at 1, not 0 + xi(i) = 2.0_ReKi*(tmp - aint(tmp)) - 1.0_ReKi ! convert to value between -1 and 1 + end do + + !---------------------------------------------------------------------------- + ! Find the bounding indices for time + !---------------------------------------------------------------------------- + + i = 4 + tmp = real((Time - EGF%TimeStart)/EGF%delta(i), ReKi) + Indx_Lo(i) = INT(tmp) + 1 ! convert REAL to INTEGER, then add one since our grid indices start at 1, not 0 + xi(i) = 2.0_ReKi*(tmp - aint(tmp)) - 1.0_ReKi ! convert to value between -1 and 1 + if ((Indx_Lo(i) == EGF%n(i))) then + if (abs(xi(i) + 1.0_SiKi) < 0.001_SiKi) then ! Allow for the special case where Time = TgridStart + deltat*( n_high_low - 1 ) + Indx_Lo(i) = Indx_Lo(i) - 1 + xi(i) = 1.0_SiKi + end if + end if + + !---------------------------------------------------------------------------- + ! Return error if outside bounds + !---------------------------------------------------------------------------- + + 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) + return + elseif (Indx_Lo(i) >= EGF%n(i)) then + Indx_Lo(i) = max(EGF%n(i) - 1, 1) ! make sure it's a valid index + call SetErrStat(ErrID_Fatal, 'Outside the grid bounds.', ErrStat, ErrMsg, RoutineName) + return + end if + Indx_Hi(i) = min(Indx_Lo(i) + 1, EGF%n(i)) ! make sure it's a valid index + end do + + !---------------------------------------------------------------------------- + ! Clamp isopc to [-1, 1] so we don't extrapolate (effectively nearest neighbor) + !---------------------------------------------------------------------------- + + xi = min(+1.0_ReKi, max(-1.0_ReKi, xi)) + + !---------------------------------------------------------------------------- + ! compute weighting factors + !---------------------------------------------------------------------------- + + N(1, 1) = (1.0_ReKi - xi(1))*(1.0_ReKi - xi(2))*(1.0_ReKi - xi(3))*(1.0_ReKi - xi(4)) + N(2, 1) = (1.0_ReKi + xi(1))*(1.0_ReKi - xi(2))*(1.0_ReKi - xi(3))*(1.0_ReKi - xi(4)) + N(3, 1) = (1.0_ReKi - xi(1))*(1.0_ReKi + xi(2))*(1.0_ReKi - xi(3))*(1.0_ReKi - xi(4)) + N(4, 1) = (1.0_ReKi + xi(1))*(1.0_ReKi + xi(2))*(1.0_ReKi - xi(3))*(1.0_ReKi - xi(4)) + N(5, 1) = (1.0_ReKi - xi(1))*(1.0_ReKi - xi(2))*(1.0_ReKi + xi(3))*(1.0_ReKi - xi(4)) + N(6, 1) = (1.0_ReKi + xi(1))*(1.0_ReKi - xi(2))*(1.0_ReKi + xi(3))*(1.0_ReKi - xi(4)) + N(7, 1) = (1.0_ReKi - xi(1))*(1.0_ReKi + xi(2))*(1.0_ReKi + xi(3))*(1.0_ReKi - xi(4)) + N(8, 1) = (1.0_ReKi + xi(1))*(1.0_ReKi + xi(2))*(1.0_ReKi + xi(3))*(1.0_ReKi - xi(4)) + N(9, 1) = (1.0_ReKi - xi(1))*(1.0_ReKi - xi(2))*(1.0_ReKi - xi(3))*(1.0_ReKi + xi(4)) + N(10, 1) = (1.0_ReKi + xi(1))*(1.0_ReKi - xi(2))*(1.0_ReKi - xi(3))*(1.0_ReKi + xi(4)) + N(11, 1) = (1.0_ReKi - xi(1))*(1.0_ReKi + xi(2))*(1.0_ReKi - xi(3))*(1.0_ReKi + xi(4)) + N(12, 1) = (1.0_ReKi + xi(1))*(1.0_ReKi + xi(2))*(1.0_ReKi - xi(3))*(1.0_ReKi + xi(4)) + N(13, 1) = (1.0_ReKi - xi(1))*(1.0_ReKi - xi(2))*(1.0_ReKi + xi(3))*(1.0_ReKi + xi(4)) + N(14, 1) = (1.0_ReKi + xi(1))*(1.0_ReKi - xi(2))*(1.0_ReKi + xi(3))*(1.0_ReKi + xi(4)) + N(15, 1) = (1.0_ReKi - xi(1))*(1.0_ReKi + xi(2))*(1.0_ReKi + xi(3))*(1.0_ReKi + xi(4)) + N(16, 1) = (1.0_ReKi + xi(1))*(1.0_ReKi + xi(2))*(1.0_ReKi + xi(3))*(1.0_ReKi + xi(4)) + N = N/16.0_ReKi + + !---------------------------------------------------------------------------- + ! Get point values + !---------------------------------------------------------------------------- + + P(:, 1) = EGF%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4)) + P(:, 2) = EGF%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4)) + P(:, 3) = EGF%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4)) + P(:, 4) = EGF%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4)) + P(:, 5) = EGF%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4)) + P(:, 6) = EGF%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4)) + P(:, 7) = EGF%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4)) + P(:, 8) = EGF%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4)) + P(:, 9) = EGF%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4)) + P(:, 10) = EGF%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4)) + P(:, 11) = EGF%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4)) + P(:, 12) = EGF%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4)) + P(:, 13) = EGF%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4)) + P(:, 14) = EGF%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4)) + P(:, 15) = EGF%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4)) + P(:, 16) = EGF%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4)) + + !---------------------------------------------------------------------------- + ! Interpolate + !---------------------------------------------------------------------------- + + Velocity = pack(matmul(P, N), .true.) + +end subroutine + end module diff --git a/modules/nwtc-library/src/FlowField.txt b/modules/nwtc-library/src/FlowField.txt index e1ab2aca44..eb892c96f5 100644 --- a/modules/nwtc-library/src/FlowField.txt +++ b/modules/nwtc-library/src/FlowField.txt @@ -4,11 +4,12 @@ # #---------------------------------------------------------------------------------------------------------------------------------- -param FlowField - IntKi Undef_FieldType - 0 - "This is the code for an undefined FieldType" - -param ^ - IntKi Uniform_FieldType - 1 - "Uniform FieldType from SteadyWind or Uniform Wind" - -param ^ - IntKi Grid_FieldType - 2 - "Grid-Field FieldType from TurbSim, Bladed, HAWC" - -param ^ - IntKi User_FieldType - 3 - "User FieldType configured by the user" - -param ^ - IntKi External_FieldType - 4 - "External FieldType from OpFM or similar" - +param FlowField - IntKi Undef_FieldType - 0 - "This is the code for an undefined FieldType" - +param ^ - IntKi Uniform_FieldType - 1 - "Uniform FieldType from SteadyWind or Uniform Wind" - +param ^ - IntKi Grid_FieldType - 2 - "Grid-Field FieldType from TurbSim, Bladed, HAWC" - +param ^ - IntKi ExtGrid_FieldType - 3 - "External Grid FieldType from OpFM or similar" - +param ^ - IntKi ExtPoint_FieldType - 4 - "External Point FieldType from OpFM or similar" - +param ^ - IntKi User_FieldType - 5 - "User FieldType configured by the user" - #---------------------------------------------------------------------------------------------------------------------------------- typedef ^ UniformFieldType ReKi RefHeight - - - "reference height; used to center the wind" meters @@ -84,10 +85,17 @@ typedef ^ ^ ReKi PLExp typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - #---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ ExternalFieldType ReKi Vel :: - - "Wind velocities populated by external driver" - +typedef ^ UserFieldType SiKi Dummy - - - "" - #---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ UserFieldType SiKi Dummy - - - "" - +typedef ^ ExtGridFieldType IntKi n 4 - - "number of evenly-spaced grid points in the x, y, z, and t directions" - +typedef ^ ^ ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" +typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" +typedef ^ ^ SiKi Vel ::::: - - "this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt]" - +typedef ^ ^ ReKi TimeStart - - - "this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1))" s + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ ExtPointFieldType ReKi Vel :: - - "Point velocities populated by external driver [uvw,point]" - #---------------------------------------------------------------------------------------------------------------------------------- typedef ^ FlowFieldType IntKi FieldType - 0 - "Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External}" - @@ -100,4 +108,5 @@ typedef ^ ^ ReKi RotFromWind typedef ^ ^ UniformFieldType Uniform - - - "Uniform Flow Data" typedef ^ ^ GridFieldType Grid - - - "Grid Field Wind Data" typedef ^ ^ UserFieldType User - - - "User Field Wind Data" -typedef ^ ^ ExternalFieldType External - - - "External Flow Data" +typedef ^ ^ ExtGridFieldType ExtGrid - - - "External Grid Flow Data" +typedef ^ ^ ExtPointFieldType ExtPoint - - - "External Point Flow Data" diff --git a/modules/nwtc-library/src/FlowField_Types.f90 b/modules/nwtc-library/src/FlowField_Types.f90 index 551d6a430d..64c9895ff7 100644 --- a/modules/nwtc-library/src/FlowField_Types.f90 +++ b/modules/nwtc-library/src/FlowField_Types.f90 @@ -36,8 +36,9 @@ MODULE FlowField_Types INTEGER(IntKi), PUBLIC, PARAMETER :: Undef_FieldType = 0 ! This is the code for an undefined FieldType [-] INTEGER(IntKi), PUBLIC, PARAMETER :: Uniform_FieldType = 1 ! Uniform FieldType from SteadyWind or Uniform Wind [-] INTEGER(IntKi), PUBLIC, PARAMETER :: Grid_FieldType = 2 ! Grid-Field FieldType from TurbSim, Bladed, HAWC [-] - INTEGER(IntKi), PUBLIC, PARAMETER :: User_FieldType = 3 ! User FieldType configured by the user [-] - INTEGER(IntKi), PUBLIC, PARAMETER :: External_FieldType = 4 ! External FieldType from OpFM or similar [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: ExtGrid_FieldType = 3 ! External Grid FieldType from OpFM or similar [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: ExtPoint_FieldType = 4 ! External Point FieldType from OpFM or similar [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: User_FieldType = 5 ! User FieldType configured by the user [-] ! ========= UniformFieldType ======= TYPE, PUBLIC :: UniformFieldType REAL(ReKi) :: RefHeight !< reference height; used to center the wind [meters] @@ -118,16 +119,25 @@ MODULE FlowField_Types REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] END TYPE GridFieldType ! ======================= -! ========= ExternalFieldType ======= - TYPE, PUBLIC :: ExternalFieldType - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vel !< Wind velocities populated by external driver [-] - END TYPE ExternalFieldType -! ======================= ! ========= UserFieldType ======= TYPE, PUBLIC :: UserFieldType REAL(SiKi) :: Dummy !< [-] END TYPE UserFieldType ! ======================= +! ========= ExtGridFieldType ======= + TYPE, PUBLIC :: ExtGridFieldType + INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of evenly-spaced grid points in the x, y, z, and t directions [-] + REAL(ReKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s] + REAL(ReKi) , DIMENSION(1:3) :: pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:)) [m] + REAL(SiKi) , DIMENSION(:,:,:,:,:), ALLOCATABLE :: Vel !< this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt] [-] + REAL(ReKi) :: TimeStart !< this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1)) [s] + END TYPE ExtGridFieldType +! ======================= +! ========= ExtPointFieldType ======= + TYPE, PUBLIC :: ExtPointFieldType + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vel !< Point velocities populated by external driver [uvw,point] [-] + END TYPE ExtPointFieldType +! ======================= ! ========= FlowFieldType ======= TYPE, PUBLIC :: FlowFieldType INTEGER(IntKi) :: FieldType = 0 !< Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External} [-] @@ -140,7 +150,8 @@ MODULE FlowField_Types TYPE(UniformFieldType) :: Uniform !< Uniform Flow Data [-] TYPE(GridFieldType) :: Grid !< Grid Field Wind Data [-] TYPE(UserFieldType) :: User !< User Field Wind Data [-] - TYPE(ExternalFieldType) :: External !< External Flow Data [-] + TYPE(ExtGridFieldType) :: ExtGrid !< External Grid Flow Data [-] + TYPE(ExtPointFieldType) :: ExtPoint !< External Point Flow Data [-] END TYPE FlowFieldType ! ======================= CONTAINS @@ -156,6 +167,7 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyUniformFieldType' @@ -875,6 +887,7 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackUniformFieldType' @@ -2068,9 +2081,146 @@ SUBROUTINE FlowField_UnPackGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Re_Xferred = Re_Xferred + 1 END SUBROUTINE FlowField_UnPackGridFieldType - SUBROUTINE FlowField_CopyExternalFieldType( SrcExternalFieldTypeData, DstExternalFieldTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(ExternalFieldType), INTENT(IN) :: SrcExternalFieldTypeData - TYPE(ExternalFieldType), INTENT(INOUT) :: DstExternalFieldTypeData + SUBROUTINE FlowField_CopyUserFieldType( SrcUserFieldTypeData, DstUserFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UserFieldType), INTENT(IN) :: SrcUserFieldTypeData + TYPE(UserFieldType), INTENT(INOUT) :: DstUserFieldTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyUserFieldType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUserFieldTypeData%Dummy = SrcUserFieldTypeData%Dummy + END SUBROUTINE FlowField_CopyUserFieldType + + SUBROUTINE FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(UserFieldType), INTENT(INOUT) :: UserFieldTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyUserFieldType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE FlowField_DestroyUserFieldType + + SUBROUTINE FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(UserFieldType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackUserFieldType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! Dummy + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%Dummy + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_PackUserFieldType + + SUBROUTINE FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(UserFieldType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackUserFieldType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_UnPackUserFieldType + + SUBROUTINE FlowField_CopyExtGridFieldType( SrcExtGridFieldTypeData, DstExtGridFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtGridFieldType), INTENT(IN) :: SrcExtGridFieldTypeData + TYPE(ExtGridFieldType), INTENT(INOUT) :: DstExtGridFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2078,30 +2228,43 @@ SUBROUTINE FlowField_CopyExternalFieldType( SrcExternalFieldTypeData, DstExterna INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyExternalFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyExtGridFieldType' ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(SrcExternalFieldTypeData%Vel)) THEN - i1_l = LBOUND(SrcExternalFieldTypeData%Vel,1) - i1_u = UBOUND(SrcExternalFieldTypeData%Vel,1) - i2_l = LBOUND(SrcExternalFieldTypeData%Vel,2) - i2_u = UBOUND(SrcExternalFieldTypeData%Vel,2) - IF (.NOT. ALLOCATED(DstExternalFieldTypeData%Vel)) THEN - ALLOCATE(DstExternalFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + DstExtGridFieldTypeData%n = SrcExtGridFieldTypeData%n + DstExtGridFieldTypeData%delta = SrcExtGridFieldTypeData%delta + DstExtGridFieldTypeData%pZero = SrcExtGridFieldTypeData%pZero +IF (ALLOCATED(SrcExtGridFieldTypeData%Vel)) THEN + i1_l = LBOUND(SrcExtGridFieldTypeData%Vel,1) + i1_u = UBOUND(SrcExtGridFieldTypeData%Vel,1) + i2_l = LBOUND(SrcExtGridFieldTypeData%Vel,2) + i2_u = UBOUND(SrcExtGridFieldTypeData%Vel,2) + i3_l = LBOUND(SrcExtGridFieldTypeData%Vel,3) + i3_u = UBOUND(SrcExtGridFieldTypeData%Vel,3) + i4_l = LBOUND(SrcExtGridFieldTypeData%Vel,4) + i4_u = UBOUND(SrcExtGridFieldTypeData%Vel,4) + i5_l = LBOUND(SrcExtGridFieldTypeData%Vel,5) + i5_u = UBOUND(SrcExtGridFieldTypeData%Vel,5) + IF (.NOT. ALLOCATED(DstExtGridFieldTypeData%Vel)) THEN + ALLOCATE(DstExtGridFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u,i5_l:i5_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstExternalFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstExtGridFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstExternalFieldTypeData%Vel = SrcExternalFieldTypeData%Vel + DstExtGridFieldTypeData%Vel = SrcExtGridFieldTypeData%Vel ENDIF - END SUBROUTINE FlowField_CopyExternalFieldType + DstExtGridFieldTypeData%TimeStart = SrcExtGridFieldTypeData%TimeStart + END SUBROUTINE FlowField_CopyExtGridFieldType - SUBROUTINE FlowField_DestroyExternalFieldType( ExternalFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(ExternalFieldType), INTENT(INOUT) :: ExternalFieldTypeData + SUBROUTINE FlowField_DestroyExtGridFieldType( ExtGridFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(ExtGridFieldType), INTENT(INOUT) :: ExtGridFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -2110,7 +2273,7 @@ SUBROUTINE FlowField_DestroyExternalFieldType( ExternalFieldTypeData, ErrStat, E LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyExternalFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyExtGridFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -2121,16 +2284,16 @@ SUBROUTINE FlowField_DestroyExternalFieldType( ExternalFieldTypeData, ErrStat, E DEALLOCATEpointers_local = .true. END IF -IF (ALLOCATED(ExternalFieldTypeData%Vel)) THEN - DEALLOCATE(ExternalFieldTypeData%Vel) +IF (ALLOCATED(ExtGridFieldTypeData%Vel)) THEN + DEALLOCATE(ExtGridFieldTypeData%Vel) ENDIF - END SUBROUTINE FlowField_DestroyExternalFieldType + END SUBROUTINE FlowField_DestroyExtGridFieldType - SUBROUTINE FlowField_PackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_PackExtGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(ExternalFieldType), INTENT(IN) :: InData + TYPE(ExtGridFieldType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -2145,7 +2308,7 @@ SUBROUTINE FlowField_PackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackExternalFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackExtGridFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2161,11 +2324,15 @@ SUBROUTINE FlowField_PackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + SIZE(InData%n) ! n + Re_BufSz = Re_BufSz + SIZE(InData%delta) ! delta + Re_BufSz = Re_BufSz + SIZE(InData%pZero) ! pZero Int_BufSz = Int_BufSz + 1 ! Vel allocated yes/no IF ( ALLOCATED(InData%Vel) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Vel upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + 2*5 ! Vel upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%Vel) ! Vel END IF + Re_BufSz = Re_BufSz + 1 ! TimeStart IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2193,6 +2360,18 @@ SUBROUTINE FlowField_PackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Db_Xferred = 1 Int_Xferred = 1 + DO i1 = LBOUND(InData%n,1), UBOUND(InData%n,1) + IntKiBuf(Int_Xferred) = InData%n(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%delta,1), UBOUND(InData%delta,1) + ReKiBuf(Re_Xferred) = InData%delta(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%pZero,1), UBOUND(InData%pZero,1) + ReKiBuf(Re_Xferred) = InData%pZero(i1) + Re_Xferred = Re_Xferred + 1 + END DO IF ( .NOT. ALLOCATED(InData%Vel) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2204,22 +2383,39 @@ SUBROUTINE FlowField_PackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Int_Xferred = Int_Xferred + 2 IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,2) IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,3) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,4) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,4) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,5) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,5) Int_Xferred = Int_Xferred + 2 - DO i2 = LBOUND(InData%Vel,2), UBOUND(InData%Vel,2) - DO i1 = LBOUND(InData%Vel,1), UBOUND(InData%Vel,1) - ReKiBuf(Re_Xferred) = InData%Vel(i1,i2) - Re_Xferred = Re_Xferred + 1 + DO i5 = LBOUND(InData%Vel,5), UBOUND(InData%Vel,5) + DO i4 = LBOUND(InData%Vel,4), UBOUND(InData%Vel,4) + DO i3 = LBOUND(InData%Vel,3), UBOUND(InData%Vel,3) + DO i2 = LBOUND(InData%Vel,2), UBOUND(InData%Vel,2) + DO i1 = LBOUND(InData%Vel,1), UBOUND(InData%Vel,1) + ReKiBuf(Re_Xferred) = InData%Vel(i1,i2,i3,i4,i5) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO END DO END DO END IF - END SUBROUTINE FlowField_PackExternalFieldType + ReKiBuf(Re_Xferred) = InData%TimeStart + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_PackExtGridFieldType - SUBROUTINE FlowField_UnPackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_UnPackExtGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(ExternalFieldType), INTENT(INOUT) :: OutData + TYPE(ExtGridFieldType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -2230,9 +2426,12 @@ SUBROUTINE FlowField_UnPackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdat INTEGER(IntKi) :: i INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 + INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 + INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackExternalFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackExtGridFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2243,6 +2442,24 @@ SUBROUTINE FlowField_UnPackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdat Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 + i1_l = LBOUND(OutData%n,1) + i1_u = UBOUND(OutData%n,1) + DO i1 = LBOUND(OutData%n,1), UBOUND(OutData%n,1) + OutData%n(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%delta,1) + i1_u = UBOUND(OutData%delta,1) + DO i1 = LBOUND(OutData%delta,1), UBOUND(OutData%delta,1) + OutData%delta(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%pZero,1) + i1_u = UBOUND(OutData%pZero,1) + DO i1 = LBOUND(OutData%pZero,1), UBOUND(OutData%pZero,1) + OutData%pZero(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vel not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -2253,40 +2470,72 @@ SUBROUTINE FlowField_UnPackExternalFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdat i2_l = IntKiBuf( Int_Xferred ) i2_u = IntKiBuf( Int_Xferred + 1) Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i4_l = IntKiBuf( Int_Xferred ) + i4_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i5_l = IntKiBuf( Int_Xferred ) + i5_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 IF (ALLOCATED(OutData%Vel)) DEALLOCATE(OutData%Vel) - ALLOCATE(OutData%Vel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + ALLOCATE(OutData%Vel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u,i5_l:i5_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vel.', ErrStat, ErrMsg,RoutineName) RETURN END IF - DO i2 = LBOUND(OutData%Vel,2), UBOUND(OutData%Vel,2) - DO i1 = LBOUND(OutData%Vel,1), UBOUND(OutData%Vel,1) - OutData%Vel(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + DO i5 = LBOUND(OutData%Vel,5), UBOUND(OutData%Vel,5) + DO i4 = LBOUND(OutData%Vel,4), UBOUND(OutData%Vel,4) + DO i3 = LBOUND(OutData%Vel,3), UBOUND(OutData%Vel,3) + DO i2 = LBOUND(OutData%Vel,2), UBOUND(OutData%Vel,2) + DO i1 = LBOUND(OutData%Vel,1), UBOUND(OutData%Vel,1) + OutData%Vel(i1,i2,i3,i4,i5) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO END DO END DO END IF - END SUBROUTINE FlowField_UnPackExternalFieldType + OutData%TimeStart = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_UnPackExtGridFieldType - SUBROUTINE FlowField_CopyUserFieldType( SrcUserFieldTypeData, DstUserFieldTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(UserFieldType), INTENT(IN) :: SrcUserFieldTypeData - TYPE(UserFieldType), INTENT(INOUT) :: DstUserFieldTypeData + SUBROUTINE FlowField_CopyExtPointFieldType( SrcExtPointFieldTypeData, DstExtPointFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPointFieldType), INTENT(IN) :: SrcExtPointFieldTypeData + TYPE(ExtPointFieldType), INTENT(INOUT) :: DstExtPointFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyUserFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyExtPointFieldType' ! ErrStat = ErrID_None ErrMsg = "" - DstUserFieldTypeData%Dummy = SrcUserFieldTypeData%Dummy - END SUBROUTINE FlowField_CopyUserFieldType +IF (ALLOCATED(SrcExtPointFieldTypeData%Vel)) THEN + i1_l = LBOUND(SrcExtPointFieldTypeData%Vel,1) + i1_u = UBOUND(SrcExtPointFieldTypeData%Vel,1) + i2_l = LBOUND(SrcExtPointFieldTypeData%Vel,2) + i2_u = UBOUND(SrcExtPointFieldTypeData%Vel,2) + IF (.NOT. ALLOCATED(DstExtPointFieldTypeData%Vel)) THEN + ALLOCATE(DstExtPointFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstExtPointFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstExtPointFieldTypeData%Vel = SrcExtPointFieldTypeData%Vel +ENDIF + END SUBROUTINE FlowField_CopyExtPointFieldType - SUBROUTINE FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(UserFieldType), INTENT(INOUT) :: UserFieldTypeData + SUBROUTINE FlowField_DestroyExtPointFieldType( ExtPointFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(ExtPointFieldType), INTENT(INOUT) :: ExtPointFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -2295,7 +2544,7 @@ SUBROUTINE FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, D LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyUserFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyExtPointFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -2306,13 +2555,16 @@ SUBROUTINE FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, D DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE FlowField_DestroyUserFieldType +IF (ALLOCATED(ExtPointFieldTypeData%Vel)) THEN + DEALLOCATE(ExtPointFieldTypeData%Vel) +ENDIF + END SUBROUTINE FlowField_DestroyExtPointFieldType - SUBROUTINE FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_PackExtPointFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(UserFieldType), INTENT(IN) :: InData + TYPE(ExtPointFieldType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -2327,7 +2579,7 @@ SUBROUTINE FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackUserFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackExtPointFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2343,7 +2595,11 @@ SUBROUTINE FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! Dummy + Int_BufSz = Int_BufSz + 1 ! Vel allocated yes/no + IF ( ALLOCATED(InData%Vel) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! Vel upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%Vel) ! Vel + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2371,15 +2627,33 @@ SUBROUTINE FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Db_Xferred = 1 Int_Xferred = 1 - ReKiBuf(Re_Xferred) = InData%Dummy - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_PackUserFieldType + IF ( .NOT. ALLOCATED(InData%Vel) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%Vel,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vel,2) + Int_Xferred = Int_Xferred + 2 - SUBROUTINE FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + DO i2 = LBOUND(InData%Vel,2), UBOUND(InData%Vel,2) + DO i1 = LBOUND(InData%Vel,1), UBOUND(InData%Vel,1) + ReKiBuf(Re_Xferred) = InData%Vel(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FlowField_PackExtPointFieldType + + SUBROUTINE FlowField_UnPackExtPointFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(UserFieldType), INTENT(INOUT) :: OutData + TYPE(ExtPointFieldType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -2388,9 +2662,11 @@ SUBROUTINE FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E INTEGER(IntKi) :: Db_Xferred INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackUserFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackExtPointFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2401,9 +2677,30 @@ SUBROUTINE FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_UnPackUserFieldType + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vel not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%Vel)) DEALLOCATE(OutData%Vel) + ALLOCATE(OutData%Vel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vel.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%Vel,2), UBOUND(OutData%Vel,2) + DO i1 = LBOUND(OutData%Vel,1), UBOUND(OutData%Vel,1) + OutData%Vel(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + END SUBROUTINE FlowField_UnPackExtPointFieldType SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(FlowFieldType), INTENT(IN) :: SrcFlowFieldTypeData @@ -2437,7 +2734,10 @@ SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeDa CALL FlowField_Copyuserfieldtype( SrcFlowFieldTypeData%User, DstFlowFieldTypeData%User, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_Copyexternalfieldtype( SrcFlowFieldTypeData%External, DstFlowFieldTypeData%External, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_Copyextgridfieldtype( SrcFlowFieldTypeData%ExtGrid, DstFlowFieldTypeData%ExtGrid, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL FlowField_Copyextpointfieldtype( SrcFlowFieldTypeData%ExtPoint, DstFlowFieldTypeData%ExtPoint, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE FlowField_CopyFlowFieldType @@ -2469,7 +2769,9 @@ SUBROUTINE FlowField_DestroyFlowFieldType( FlowFieldTypeData, ErrStat, ErrMsg, D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL FlowField_Destroyuserfieldtype( FlowFieldTypeData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_Destroyexternalfieldtype( FlowFieldTypeData%External, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_Destroyextgridfieldtype( FlowFieldTypeData%ExtGrid, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL FlowField_Destroyextpointfieldtype( FlowFieldTypeData%ExtPoint, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE FlowField_DestroyFlowFieldType @@ -2567,20 +2869,37 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! External: size of buffers for each call to pack subtype - CALL FlowField_Packexternalfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%External, ErrStat2, ErrMsg2, .TRUE. ) ! External + Int_BufSz = Int_BufSz + 3 ! ExtGrid: size of buffers for each call to pack subtype + CALL FlowField_Packextgridfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, .TRUE. ) ! ExtGrid + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ExtGrid + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ExtGrid + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ExtGrid + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ExtPoint: size of buffers for each call to pack subtype + CALL FlowField_Packextpointfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, .TRUE. ) ! ExtPoint CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! External + IF(ALLOCATED(Re_Buf)) THEN ! ExtPoint Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! External + IF(ALLOCATED(Db_Buf)) THEN ! ExtPoint Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! External + IF(ALLOCATED(Int_Buf)) THEN ! ExtPoint Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -2719,7 +3038,35 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_Packexternalfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%External, ErrStat2, ErrMsg2, OnlySize ) ! External + CALL FlowField_Packextgridfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, OnlySize ) ! ExtGrid + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL FlowField_Packextpointfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, OnlySize ) ! ExtPoint CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2964,7 +3311,47 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackexternalfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%External, ErrStat2, ErrMsg2 ) ! External + CALL FlowField_Unpackextgridfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtGrid, ErrStat2, ErrMsg2 ) ! ExtGrid + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL FlowField_Unpackextpointfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtPoint, ErrStat2, ErrMsg2 ) ! ExtPoint CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN From 385dd41b71865793e9ae849a91ec353bb6abd801 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 28 Dec 2022 21:37:16 +0000 Subject: [PATCH 07/51] inflowwind: added ExtGrid & ExtPoint to FlowField Changes to InflowWind to support addition of FlowField types --- modules/inflowwind/src/IfW_FlowField.f90 | 65 ++ modules/inflowwind/src/IfW_FlowField.txt | 45 +- .../inflowwind/src/IfW_FlowField_Types.f90 | 591 ++++++++++++++++++ 3 files changed, 683 insertions(+), 18 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index dec9d179b7..0e56b5385e 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -88,29 +88,50 @@ subroutine IfW_FlowField_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) case (1) ! Steady FF%FieldType = Uniform_FieldType call SteadyWind_Init(InitInp%Steady, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) + case (2) ! Uniform FF%FieldType = Uniform_FieldType call UniformWind_Init(InitInp%Uniform, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) + case (3) ! Binary TurbSim FF FF%FieldType = Grid_FieldType call TurbSim_Init(InitInp%TurbSim, InitInp%SumFileUnit, FF%Grid, InitOut%FileDat, TmpErrStat, TmpErrMsg) + case (4) ! Binary Bladed-Style FF FF%FieldType = Grid_FieldType ! call Read_Bladed_Binary(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) TmpErrStat = ErrID_Fatal TmpErrMsg = "Binary Bladed Wind is not implemented" + case (5) ! HAWC FF%FieldType = Grid_FieldType call HAWC_Init(InitInp%HAWC, InitInp%SumFileUnit, FF%Grid, InitOut%FileDat, TmpErrStat, TmpErrMsg) + case (6) ! User Defined FF%FieldType = Grid_FieldType TmpErrStat = ErrID_Fatal TmpErrMsg = "User Wind is not implemented" + case (7) ! Native Bladed FF FF%FieldType = Grid_FieldType ! call Read_Bladed_Native(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) TmpErrStat = ErrID_Fatal TmpErrMsg = "Native Bladed Wind is not implemented" + + case (8) ! External Grid + FF%FieldType = ExtGrid_FieldType + TmpErrStat = ErrID_Fatal + TmpErrMsg = "ExtGrid Wind is not implemented" + + case (9) ! External Point + FF%FieldType = ExtPoint_FieldType + TmpErrStat = ErrID_Fatal + TmpErrMsg = "ExtPoint Wind is not implemented" + + case default ! Others + TmpErrStat = ErrID_Fatal + TmpErrMsg = "Unknown wind type" + end select call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -133,6 +154,12 @@ subroutine IfW_FlowField_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return end if + + case default + if (InitInp%CalcAccel) then + call SetErrStat(ErrID_Fatal, "Acceleration not implemented for field type", & + ErrStat, ErrMsg, RoutineName) + end if end select !---------------------------------------------------------------------------- @@ -1092,6 +1119,44 @@ subroutine User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) end subroutine +!> ExtGrid_Init initializes a wind field defined by a 4D grid. +subroutine ExtGrid_Init(InitInp, SumFileUnit, EGF, FileDat, ErrStat, ErrMsg) + + type(ExtGridInitInputType), intent(in) :: InitInp + integer(IntKi), intent(in) :: SumFileUnit + type(ExtGridFieldType), intent(out) :: EGF + type(WindFileDat), intent(out) :: FileDat + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = "ExtGrid_Init" + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + + ErrStat = ErrID_None + ErrMsg = "" + + ! Initialize field from inputs + EGF%n = InitInp%n + EGF%delta = InitInp%delta + EGF%pZero = InitInp%pZero + EGF%TimeStart = 0.0_ReKi + + ! uvw velocity components at x,y,z,t coordinates + call AllocAry(EGF%Vel, 3, EGF%n(1), EGF%n(2), EGF%n(3), EGF%n(4), & + 'External Grid Velocity', TmpErrStat, TmpErrMsg) + call SetErrStat(ErrStat, ErrMsg, TmpErrStat, TmpErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Initialize velocities to zero + EGF%Vel = 0.0_SiKi + + if (SumFileUnit > 0) then + write (SumFileUnit, '(A)') InitInp%n + end if + +end subroutine + subroutine PopulateWindFileDatFromGridField(GridField, FileName, WindType, HasTower, FileDat) type(GridFieldType), intent(in) :: GridField diff --git a/modules/inflowwind/src/IfW_FlowField.txt b/modules/inflowwind/src/IfW_FlowField.txt index 8073f4a7b5..0d9080ea69 100644 --- a/modules/inflowwind/src/IfW_FlowField.txt +++ b/modules/inflowwind/src/IfW_FlowField.txt @@ -57,6 +57,12 @@ typedef ^ ^ ReKi XOffset typedef ^ UserInitInputType SiKi Dummy - - - "User field initialization input dummy value" - +typedef ^ ExtGridInitInputType IntKi n 4 - - "number of grid points in the x, y, z, and t directions" - +typedef ^ ^ ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" +typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" + +typedef ^ ExtPointInitInputType IntKi Dummy - - - "External Point field initialization input dummy value" - + typedef ^ InitInputType IntKi WindType - 0 - "Type of the windfile" - typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians @@ -67,25 +73,28 @@ typedef ^ ^ UniformInitInputType Uniform typedef ^ ^ TurbSimInitInputType TurbSim - - - "" - typedef ^ ^ BladedInitInputType Bladed - - - "" - typedef ^ ^ HAWCInitInputType HAWC - - - "" - +typedef ^ ^ UserInitInputType User - - - "" - +typedef ^ ^ ExtGridInitInputType ExtGrid - - - "" - +typedef ^ ^ ExtPointInitInputType ExtPoint - - - "" - -typedef ^ WindFileDat character(1024) FileName - - - "Name of the windfile retrieved" - -typedef ^ ^ IntKi WindType - 0 - "Type of the windfile" - -typedef ^ ^ ReKi RefHt - - - "Reference height given in file" meters -typedef ^ ^ Logical RefHt_Set - - - "Reference height was given in file" - -typedef ^ ^ DbKi DT - - - "TimeStep of the wind file -- zero value for none" seconds -typedef ^ ^ IntKi NumTSteps - - - "Number of timesteps in the time range of wind file" - -typedef ^ ^ Logical ConstantDT - - - "Timesteps are the same throughout file" - -typedef ^ ^ ReKi TRange {2} - - "Time range of the wind file" seconds -typedef ^ ^ Logical TRange_Limited - - - "TRange limits strictly enforced" - -typedef ^ ^ ReKi YRange {2} - - "Range in y direction" meters -typedef ^ ^ Logical YRange_Limited - - - "YRange limits strictly enforced" - -typedef ^ ^ ReKi ZRange {2} - - "Range in z direction" meters -typedef ^ ^ Logical ZRange_Limited - - - "ZRange limits strictly enforced" - -typedef ^ ^ IntKi BinaryFormat - - - "Binary format identifier" - -typedef ^ ^ Logical IsBinary - - - "Windfile is a binary file" - -typedef ^ ^ ReKi TI {3} - - "Turbulence intensity (U,V,W)" - -typedef ^ ^ Logical TI_listed - - - "Turbulence intesity given in file" - -typedef ^ ^ ReKi MWS - - - "Approximate mean wind speed" - +typedef ^ WindFileDat character(1024) FileName - - - "Name of the windfile retrieved" - +typedef ^ ^ IntKi WindType - 0 - "Type of the windfile" - +typedef ^ ^ ReKi RefHt - - - "Reference height given in file" meters +typedef ^ ^ Logical RefHt_Set - - - "Reference height was given in file" - +typedef ^ ^ DbKi DT - - - "TimeStep of the wind file -- zero value for none" seconds +typedef ^ ^ IntKi NumTSteps - - - "Number of timesteps in the time range of wind file" - +typedef ^ ^ Logical ConstantDT - - - "Timesteps are the same throughout file" - +typedef ^ ^ ReKi TRange {2} - - "Time range of the wind file" seconds +typedef ^ ^ Logical TRange_Limited - - - "TRange limits strictly enforced" - +typedef ^ ^ ReKi YRange {2} - - "Range in y direction" meters +typedef ^ ^ Logical YRange_Limited - - - "YRange limits strictly enforced" - +typedef ^ ^ ReKi ZRange {2} - - "Range in z direction" meters +typedef ^ ^ Logical ZRange_Limited - - - "ZRange limits strictly enforced" - +typedef ^ ^ IntKi BinaryFormat - - - "Binary format identifier" - +typedef ^ ^ Logical IsBinary - - - "Windfile is a binary file" - +typedef ^ ^ ReKi TI {3} - - "Turbulence intensity (U,V,W)" - +typedef ^ ^ Logical TI_listed - - - "Turbulence intesity given in file" - +typedef ^ ^ ReKi MWS - - - "Approximate mean wind speed" - typedef ^ InitOutputType ProgDesc Ver - - - "Version information off FFWind submodule" - typedef ^ ^ WindFileDat FileDat - - - "" - diff --git a/modules/inflowwind/src/IfW_FlowField_Types.f90 b/modules/inflowwind/src/IfW_FlowField_Types.f90 index 9212d16149..26f32019c4 100644 --- a/modules/inflowwind/src/IfW_FlowField_Types.f90 +++ b/modules/inflowwind/src/IfW_FlowField_Types.f90 @@ -126,6 +126,18 @@ MODULE IfW_FlowField_Types REAL(SiKi) :: Dummy !< User field initialization input dummy value [-] END TYPE UserInitInputType ! ======================= +! ========= ExtGridInitInputType ======= + TYPE, PUBLIC :: ExtGridInitInputType + INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of grid points in the x, y, z, and t directions [-] + REAL(ReKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s] + REAL(ReKi) , DIMENSION(1:3) :: pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:)) [m] + END TYPE ExtGridInitInputType +! ======================= +! ========= ExtPointInitInputType ======= + TYPE, PUBLIC :: ExtPointInitInputType + INTEGER(IntKi) :: Dummy !< External Point field initialization input dummy value [-] + END TYPE ExtPointInitInputType +! ======================= ! ========= IfW_FlowField_InitInputType ======= TYPE, PUBLIC :: IfW_FlowField_InitInputType INTEGER(IntKi) :: WindType = 0 !< Type of the windfile [-] @@ -138,6 +150,9 @@ MODULE IfW_FlowField_Types TYPE(TurbSimInitInputType) :: TurbSim !< [-] TYPE(BladedInitInputType) :: Bladed !< [-] TYPE(HAWCInitInputType) :: HAWC !< [-] + TYPE(UserInitInputType) :: User !< [-] + TYPE(ExtGridInitInputType) :: ExtGrid !< [-] + TYPE(ExtPointInitInputType) :: ExtPoint !< [-] END TYPE IfW_FlowField_InitInputType ! ======================= ! ========= WindFileDat ======= @@ -2309,6 +2324,312 @@ SUBROUTINE IfW_FlowField_UnPackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Ou Re_Xferred = Re_Xferred + 1 END SUBROUTINE IfW_FlowField_UnPackUserInitInputType + SUBROUTINE IfW_FlowField_CopyExtGridInitInputType( SrcExtGridInitInputTypeData, DstExtGridInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtGridInitInputType), INTENT(IN) :: SrcExtGridInitInputTypeData + TYPE(ExtGridInitInputType), INTENT(INOUT) :: DstExtGridInitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyExtGridInitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstExtGridInitInputTypeData%n = SrcExtGridInitInputTypeData%n + DstExtGridInitInputTypeData%delta = SrcExtGridInitInputTypeData%delta + DstExtGridInitInputTypeData%pZero = SrcExtGridInitInputTypeData%pZero + END SUBROUTINE IfW_FlowField_CopyExtGridInitInputType + + SUBROUTINE IfW_FlowField_DestroyExtGridInitInputType( ExtGridInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(ExtGridInitInputType), INTENT(INOUT) :: ExtGridInitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyExtGridInitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyExtGridInitInputType + + SUBROUTINE IfW_FlowField_PackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(ExtGridInitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackExtGridInitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + SIZE(InData%n) ! n + Re_BufSz = Re_BufSz + SIZE(InData%delta) ! delta + Re_BufSz = Re_BufSz + SIZE(InData%pZero) ! pZero + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO i1 = LBOUND(InData%n,1), UBOUND(InData%n,1) + IntKiBuf(Int_Xferred) = InData%n(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%delta,1), UBOUND(InData%delta,1) + ReKiBuf(Re_Xferred) = InData%delta(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%pZero,1), UBOUND(InData%pZero,1) + ReKiBuf(Re_Xferred) = InData%pZero(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE IfW_FlowField_PackExtGridInitInputType + + SUBROUTINE IfW_FlowField_UnPackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(ExtGridInitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackExtGridInitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + i1_l = LBOUND(OutData%n,1) + i1_u = UBOUND(OutData%n,1) + DO i1 = LBOUND(OutData%n,1), UBOUND(OutData%n,1) + OutData%n(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%delta,1) + i1_u = UBOUND(OutData%delta,1) + DO i1 = LBOUND(OutData%delta,1), UBOUND(OutData%delta,1) + OutData%delta(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%pZero,1) + i1_u = UBOUND(OutData%pZero,1) + DO i1 = LBOUND(OutData%pZero,1), UBOUND(OutData%pZero,1) + OutData%pZero(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE IfW_FlowField_UnPackExtGridInitInputType + + SUBROUTINE IfW_FlowField_CopyExtPointInitInputType( SrcExtPointInitInputTypeData, DstExtPointInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(ExtPointInitInputType), INTENT(IN) :: SrcExtPointInitInputTypeData + TYPE(ExtPointInitInputType), INTENT(INOUT) :: DstExtPointInitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyExtPointInitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstExtPointInitInputTypeData%Dummy = SrcExtPointInitInputTypeData%Dummy + END SUBROUTINE IfW_FlowField_CopyExtPointInitInputType + + SUBROUTINE IfW_FlowField_DestroyExtPointInitInputType( ExtPointInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(ExtPointInitInputType), INTENT(INOUT) :: ExtPointInitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyExtPointInitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyExtPointInitInputType + + SUBROUTINE IfW_FlowField_PackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(ExtPointInitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackExtPointInitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! Dummy + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%Dummy + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackExtPointInitInputType + + SUBROUTINE IfW_FlowField_UnPackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(ExtPointInitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackExtPointInitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%Dummy = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackExtPointInitInputType + SUBROUTINE IfW_FlowField_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) TYPE(IfW_FlowField_InitInputType), INTENT(IN) :: SrcInitInputData TYPE(IfW_FlowField_InitInputType), INTENT(INOUT) :: DstInitInputData @@ -2343,6 +2664,15 @@ SUBROUTINE IfW_FlowField_CopyInitInput( SrcInitInputData, DstInitInputData, Ctrl CALL IfW_FlowField_Copyhawcinitinputtype( SrcInitInputData%HAWC, DstInitInputData%HAWC, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copyuserinitinputtype( SrcInitInputData%User, DstInitInputData%User, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copyextgridinitinputtype( SrcInitInputData%ExtGrid, DstInitInputData%ExtGrid, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copyextpointinitinputtype( SrcInitInputData%ExtPoint, DstInitInputData%ExtPoint, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE IfW_FlowField_CopyInitInput SUBROUTINE IfW_FlowField_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -2376,6 +2706,12 @@ SUBROUTINE IfW_FlowField_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALL CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL IfW_FlowField_Destroyhawcinitinputtype( InitInputData%HAWC, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroyuserinitinputtype( InitInputData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroyextgridinitinputtype( InitInputData%ExtGrid, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroyextpointinitinputtype( InitInputData%ExtPoint, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE IfW_FlowField_DestroyInitInput SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -2504,6 +2840,57 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + Int_BufSz = Int_BufSz + 3 ! User: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, .TRUE. ) ! User + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! User + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! User + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! User + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ExtGrid: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, .TRUE. ) ! ExtGrid + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ExtGrid + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ExtGrid + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ExtGrid + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + Int_BufSz = Int_BufSz + 3 ! ExtPoint: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, .TRUE. ) ! ExtPoint + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! ExtPoint + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! ExtPoint + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! ExtPoint + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2681,6 +3068,90 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + CALL IfW_FlowField_Packuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, OnlySize ) ! User + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL IfW_FlowField_Packextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, OnlySize ) ! ExtGrid + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + CALL IfW_FlowField_Packextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, OnlySize ) ! ExtPoint + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF END SUBROUTINE IfW_FlowField_PackInitInput SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -2919,6 +3390,126 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%User, ErrStat2, ErrMsg2 ) ! User + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtGrid, ErrStat2, ErrMsg2 ) ! ExtGrid + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtPoint, ErrStat2, ErrMsg2 ) ! ExtPoint + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE IfW_FlowField_UnPackInitInput SUBROUTINE IfW_FlowField_CopyWindFileDat( SrcWindFileDatData, DstWindFileDatData, CtrlCode, ErrStat, ErrMsg ) From ed24fc1113eea174540995e47d37d8b980774b89 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 25 Jan 2023 21:30:57 +0000 Subject: [PATCH 08/51] flowfield: set end derivatives of cubic spline = 0 --- modules/nwtc-library/src/FlowField.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/nwtc-library/src/FlowField.f90 b/modules/nwtc-library/src/FlowField.f90 index 627ce34d20..01638a2d5f 100644 --- a/modules/nwtc-library/src/FlowField.f90 +++ b/modules/nwtc-library/src/FlowField.f90 @@ -629,7 +629,7 @@ subroutine CalcCubicSplineDeriv(x, y, dy) dy2(i) = dy2(i)*dy2(i + 1) + u(i) dy(i) = real(b(i) - (x(i + 1) - x(i))*(dy2(i)/3.0_ReKi + dy2(i + 1)/6.0_ReKi), SiKi) end do - dy(n) = real(b(n - 1) + (x(n) - x(n - 1))*(dy2(n - 1)/6.0_ReKi + dy2(n)/3.0_ReKi), SiKi) + dy(n) = 0.0_ReKi end subroutine @@ -1329,7 +1329,7 @@ subroutine CalcCubicSplineDeriv(h, y, dy) dy2(i) = dy2(i)*dy2(i + 1) + u(i) dy(i) = real(b(i) - h*(dy2(i)/3.0_ReKi + dy2(i + 1)/6.0_ReKi), SiKi) end do - dy(n) = real(b(n - 1) + h*(dy2(n - 1)/6.0_ReKi + dy2(n)/3.0_ReKi), SiKi) + dy(n) = 0.0_ReKi end subroutine From 3519095265a4b842300a17c01a501c5d1b9aa0ba Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 17 Feb 2023 22:39:40 +0000 Subject: [PATCH 09/51] Moved FlowField module to InflowWind --- modules/inflowwind/CMakeLists.txt | 9 +- .../src/FlowField.f90 | 0 .../src/FlowField.txt | 0 .../{IfW_FlowField.f90 => FlowField_IO.f90} | 0 .../{IfW_FlowField.txt => FlowField_IO.txt} | 0 ...Field_Types.f90 => FlowField_IO_Types.f90} | 0 .../src/FlowField_Types.f90 | 0 modules/inflowwind/src/InflowWind_Driver.f90 | 115 +++++++++++++----- .../inflowwind/src/InflowWind_Driver_Subs.f90 | 5 +- .../src/InflowWind_Driver_Types.f90 | 6 +- modules/nwtc-library/CMakeLists.txt | 6 - 11 files changed, 97 insertions(+), 44 deletions(-) rename modules/{nwtc-library => inflowwind}/src/FlowField.f90 (100%) rename modules/{nwtc-library => inflowwind}/src/FlowField.txt (100%) rename modules/inflowwind/src/{IfW_FlowField.f90 => FlowField_IO.f90} (100%) rename modules/inflowwind/src/{IfW_FlowField.txt => FlowField_IO.txt} (100%) rename modules/inflowwind/src/{IfW_FlowField_Types.f90 => FlowField_IO_Types.f90} (100%) rename modules/{nwtc-library => inflowwind}/src/FlowField_Types.f90 (100%) diff --git a/modules/inflowwind/CMakeLists.txt b/modules/inflowwind/CMakeLists.txt index d95ef84def..e056b4dfee 100644 --- a/modules/inflowwind/CMakeLists.txt +++ b/modules/inflowwind/CMakeLists.txt @@ -17,7 +17,6 @@ if (GENERATE_TYPES) generate_f90_types(src/InflowWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/InflowWind_Types.f90) generate_f90_types(src/Lidar.txt ${CMAKE_CURRENT_LIST_DIR}/src/Lidar_Types.f90) - generate_f90_types(src/IfW_FlowField.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_FlowField_Types.f90 -noextrap) generate_f90_types(src/IfW_BladedFFWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_BladedFFWind_Types.f90 -noextrap) generate_f90_types(src/IfW_4Dext.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_4Dext_Types.f90 -noextrap) generate_f90_types(src/IfW_HAWCWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_HAWCWind_Types.f90 -noextrap) @@ -25,10 +24,15 @@ if (GENERATE_TYPES) generate_f90_types(src/IfW_UniformWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_UniformWind_Types.f90 -noextrap) generate_f90_types(src/IfW_UserWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_UserWind_Types.f90 -noextrap) generate_f90_types(src/IfW_FFWind_Base.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_FFWind_Base_Types.f90 -noextrap) + generate_f90_types(src/FlowField.txt ${CMAKE_CURRENT_LIST_DIR}/src/FlowField_Types.f90 -noextrap) + generate_f90_types(src/FlowField_IO.txt ${CMAKE_CURRENT_LIST_DIR}/src/FlowField_IO_Types.f90 -noextrap) endif() set(IFW_SOURCES - src/IfW_FlowField.f90 + src/FlowField_Types.f90 + src/FlowField.f90 + src/FlowField_IO_Types.f90 + src/FlowField_IO.f90 src/IfW_BladedFFWind.f90 src/IfW_4Dext.f90 src/IfW_HAWCWind.f90 @@ -38,7 +42,6 @@ set(IFW_SOURCES src/InflowWind_Subs.f90 src/InflowWind.f90 src/Lidar.f90 - src/IfW_FlowField_Types.f90 src/IfW_FFWind_Base.f90 src/IfW_FFWind_Base_Types.f90 src/IfW_BladedFFWind_Types.f90 diff --git a/modules/nwtc-library/src/FlowField.f90 b/modules/inflowwind/src/FlowField.f90 similarity index 100% rename from modules/nwtc-library/src/FlowField.f90 rename to modules/inflowwind/src/FlowField.f90 diff --git a/modules/nwtc-library/src/FlowField.txt b/modules/inflowwind/src/FlowField.txt similarity index 100% rename from modules/nwtc-library/src/FlowField.txt rename to modules/inflowwind/src/FlowField.txt diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/FlowField_IO.f90 similarity index 100% rename from modules/inflowwind/src/IfW_FlowField.f90 rename to modules/inflowwind/src/FlowField_IO.f90 diff --git a/modules/inflowwind/src/IfW_FlowField.txt b/modules/inflowwind/src/FlowField_IO.txt similarity index 100% rename from modules/inflowwind/src/IfW_FlowField.txt rename to modules/inflowwind/src/FlowField_IO.txt diff --git a/modules/inflowwind/src/IfW_FlowField_Types.f90 b/modules/inflowwind/src/FlowField_IO_Types.f90 similarity index 100% rename from modules/inflowwind/src/IfW_FlowField_Types.f90 rename to modules/inflowwind/src/FlowField_IO_Types.f90 diff --git a/modules/nwtc-library/src/FlowField_Types.f90 b/modules/inflowwind/src/FlowField_Types.f90 similarity index 100% rename from modules/nwtc-library/src/FlowField_Types.f90 rename to modules/inflowwind/src/FlowField_Types.f90 diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index c2d4b104da..6b49036f4b 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -30,6 +30,7 @@ PROGRAM InflowWind_Driver USE InflowWind_Types USE InflowWind_Driver_Types ! Contains types and routines for handling the input arguments USE InflowWind_Driver_Subs ! Contains subroutines for the driver program + USE FlowField IMPLICIT NONE @@ -60,6 +61,7 @@ PROGRAM InflowWind_Driver TYPE(IfWDriver_Flags) :: SettingsFlags ! Flags indicating which settings were specified (includes CL and ipt file) TYPE(IfWDriver_Settings) :: Settings ! Driver settings REAL(DbKi) :: Timer(1:2) ! Keep track of how long this takes to run + REAL(DbKi) :: Timer2(2) ! Keep track of how long this takes to run REAL(DbKi) :: TimeNow ! The current time INTEGER(IntKi) :: NumTotalPoints ! Number of points for this iteration LOGICAL :: TempFileExist ! Flag for inquiring file existence @@ -322,16 +324,24 @@ PROGRAM InflowWind_Driver ErrStat = ErrID_None ENDIF + CALL WrScr(NewLine//"Read "//TRIM(Num2LStr(SIZE(PointsXYZ,DIM=2)))//" points from '"//TRIM(Settings%PointsFileName)//"'.") + ! Make name for output - CALL GetRoot( Settings%PointsFileName, Settings%PointsOutputName ) - Settings%PointsOutputName = TRIM(Settings%PointsOutputName)//'.Velocity.dat' + CALL GetRoot( Settings%PointsFileName, Settings%PointsOutputName(1) ) + Settings%PointsOutputName(1) = TRIM(Settings%PointsOutputName(1))//'.Velocity.dat' - CALL WrScr(NewLine//"Read "//TRIM(Num2LStr(SIZE(PointsXYZ,DIM=2)))//" points from '"//TRIM(Settings%PointsFileName)// & - "'. Results output to '"//TRIM(Settings%PointsOutputName)//"'.") + CALL GetRoot( Settings%PointsFileName, Settings%PointsOutputName(2) ) + Settings%PointsOutputName(2) = TRIM(Settings%PointsOutputName(2))//'.Velocity.FF.dat' - ! If the output file already exists, warn that it will be overwritten - INQUIRE( file=TRIM(Settings%PointsOutputName), exist=TempFileExist ) - IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsOutputName)) + CALL GetRoot( Settings%PointsFileName, Settings%PointsOutputName(3) ) + Settings%PointsOutputName(3) = TRIM(Settings%PointsOutputName(3))//'.Accel.FF.dat' + + ! Display that file will be created, output message if it will be overwritten + do i = 1, size(Settings%PointsOutputName) + CALL WrScr(NewLine//"Results output to '"//TRIM(Settings%PointsOutputName(i))//"'.") + INQUIRE( file=TRIM(Settings%PointsOutputName(i)), exist=TempFileExist ) + IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsOutputName(i))) + end do ENDIF @@ -464,6 +474,8 @@ PROGRAM InflowWind_Driver IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr('Calling InflowWind_Init...') + ! Set flag to calculate acceleration + InflowWind_InitInp%CalcAccel = .TRUE. CALL InflowWind_Init( InflowWind_InitInp, InflowWind_u1, InflowWind_p, & InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & @@ -679,6 +691,14 @@ PROGRAM InflowWind_Driver CALL ProgAbort( ErrMsg ) ENDIF + ! Allocate the array for the acceleration results -- 3 x Npoints + CALL AllocAry( InflowWind_y2%AccelUVW, 3, SIZE(InflowWind_u2%PositionXYZ, DIM=2 ), & + "Array of accelerations corresponding to Points file", ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + ENDIF + ! WriteOutput info IF ( ALLOCATED(InflowWind_y1%WriteOutput) ) THEN ALLOCATE( InflowWind_y2%WriteOutput(SIZE(InflowWind_y1%WriteOutput)), STAT=ErrStat ) @@ -689,10 +709,12 @@ PROGRAM InflowWind_Driver InflowWind_y2%WriteOutput = InflowWind_y1%WriteOutput ENDIF - ! Now create the output file. Write header information - CALL PointsVel_OutputWrite( Settings%PointsOutputUnit, Settings%PointsOutputName, SettingsFlags%PointsOutputInit, & - Settings, InflowWind_u2%PositionXYZ, InflowWind_y2%VelocityUVW, & - TimeNow, ErrStat, ErrMsg ) + ! Now create the output files. Write header information + do i = 1, size(Settings%PointsOutputUnit) + CALL PointsVel_OutputWrite( Settings%PointsOutputUnit(i), Settings%PointsOutputName(i), & + SettingsFlags%PointsOutputInit(i), Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, TimeNow, ErrStat, ErrMsg ) + end do ENDIF @@ -815,25 +837,6 @@ PROGRAM InflowWind_Driver ENDIF - - - ! Calculate results for the Points and export them for this timestep - IF ( SettingsFlags%PointsFile ) THEN - - ! Get results for Points data from IfW - CALL InflowWind_CalcOutput( TimeNow, InflowWind_u2, InflowWind_p, & - InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & - InflowWind_y2, InflowWind_MiscVars, ErrStat, ErrMsg) - - ! Output the Points results for this timestep - CALL PointsVel_OutputWrite( Settings%PointsOutputUnit, Settings%PointsOutputName, SettingsFlags%PointsOutputInit, & - Settings, InflowWind_u2%PositionXYZ, InflowWind_y2%VelocityUVW, & - TimeNow, ErrStat, ErrMsg ) - - ENDIF - - - ! Calculate results for FFT if we are performing one IF ( SettingsFlags%FFTcalc ) THEN @@ -849,6 +852,54 @@ PROGRAM InflowWind_Driver ENDDO ! ITime loop + ! Calculate results for the Points and export them for this timestep + IF ( SettingsFlags%PointsFile ) THEN + + call CPU_TIME( Timer2(1) ) + + ! Get results for Points data from IfW + do ITime = 0, MAX( Settings%NumTimeSteps, 1_IntKi ) + TimeNow = Settings%TStart + Settings%DT*(ITime) + + call InflowWind_CalcOutput( TimeNow, InflowWind_u2, InflowWind_p, & + InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & + InflowWind_y2, InflowWind_MiscVars, ErrStat, ErrMsg) + + ! Output the Points results for this timestep + call PointsVel_OutputWrite( Settings%PointsOutputUnit(1), Settings%PointsOutputName(1), & + SettingsFlags%PointsOutputInit(1), Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, TimeNow, ErrStat, ErrMsg ) + end do + + call CPU_TIME(Timer2(2)) + call WrScr(NewLine//'Elapsed time IfW: '//TRIM(Num2LStr(Timer2(2)-Timer2(1)))//' seconds') + call CPU_TIME( Timer2(1) ) + + ! Get results for Points data from FlowField + do ITime = 0, MAX( Settings%NumTimeSteps, 1_IntKi ) + TimeNow = Settings%TStart + Settings%DT*(ITime) + + call FlowField_GetVelAcc(InflowWind_p%FlowField, 0, TimeNow, & + InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, & + InflowWind_y2%AccelUVW, ErrStat, ErrMsg) + + ! Output the Points velocity results for this timestep + call PointsVel_OutputWrite( Settings%PointsOutputUnit(2), Settings%PointsOutputName(2), & + SettingsFlags%PointsOutputInit(2), Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, TimeNow, ErrStat, ErrMsg ) + + ! Output the Points acceleration results for this timestep + call PointsVel_OutputWrite( Settings%PointsOutputUnit(3), Settings%PointsOutputName(3), & + SettingsFlags%PointsOutputInit(3), Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%AccelUVW, TimeNow, ErrStat, ErrMsg ) + end do + + call CPU_TIME(Timer2(2)) + call WrScr(NewLine//'Elapsed time FF: '//TRIM(Num2LStr(Timer2(2)-Timer2(1)))//' seconds') + + end if + ! output table of results for the outlist comparison and check if very verbose -- print statements are @@ -982,7 +1033,9 @@ SUBROUTINE DriverCleanup() if (Settings%WindGridOutputUnit > -1_IntKi ) CLOSE( Settings%WindGridOutputUnit ) - if (Settings%PointsOutputUnit > -1_IntKi ) CLOSE( Settings%PointsOutputUnit ) + do i = 1, size(Settings%PointsOutputUnit) + if (Settings%PointsOutputUnit(i) > -1_IntKi ) CLOSE( Settings%PointsOutputUnit(i) ) + end do if (Settings%FFTOutputUnit > -1_IntKi ) CLOSE( Settings%FFTOutputUnit ) diff --git a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 index ed7801e79f..8a5083ef6d 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 @@ -2405,6 +2405,7 @@ SUBROUTINE printSettings( DvrFlags, DvrSettings ) ! The arguments TYPE( IfWDriver_Flags ), INTENT(IN ) :: DvrFlags !< Flags indicating which settings were set TYPE( IfWDriver_Settings ), INTENT(IN ) :: DvrSettings !< Stored settings + integer(IntKi) :: i CALL WrsCr(TRIM(GetNVD(DvrSettings%ProgInfo))) CALL WrScr(' DvrIptFile: '//FLAG(DvrFlags%DvrIptFile)// ' '//TRIM(DvrSettings%DvrIptFileName)) @@ -2445,7 +2446,9 @@ SUBROUTINE printSettings( DvrFlags, DvrSettings ) CALL WrScr(' WindGridOutputInit: '//FLAG(DvrFlags%WindGridOutputInit)//' Unit #: '//TRIM(Num2LStr(DvrSettings%WindGridOutputUnit))) end if CALL WrScr(' FFTOutputInit: '//FLAG(DvrFlags%FFTOutputInit)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%FFTOutputUnit))) - CALL WrScr(' PointsOutputInit: '//FLAG(DvrFlags%PointsOutputInit)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%PointsOutputUnit))) + do i = 1, size(DvrSettings%PointsOutputUnit) + CALL WrScr(' PointsOutputInit: '//FLAG(DvrFlags%PointsOutputInit(i))// ' Unit #: '//TRIM(Num2LStr(DvrSettings%PointsOutputUnit(i)))) + end do RETURN END SUBROUTINE printSettings diff --git a/modules/inflowwind/src/InflowWind_Driver_Types.f90 b/modules/inflowwind/src/InflowWind_Driver_Types.f90 index 49fa3446d5..8b3cae3a64 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Types.f90 @@ -62,7 +62,7 @@ MODULE InflowWind_Driver_Types LOGICAL :: PointsFile = .FALSE. !< points filename to read in -- command line option only LOGICAL :: WindGridOutputInit = .FALSE. !< Is the WindGridOut file initialized - LOGICAL :: PointsOutputInit = .FALSE. !< Is the Points output file initialized + LOGICAL :: PointsOutputInit(3) = .FALSE. !< Is the Points output file initialized LOGICAL :: FFTOutputInit = .FALSE. !< Is the FFT output file initialized LOGICAL :: Verbose = .FALSE. !< Verbose error reporting LOGICAL :: VVerbose = .FALSE. !< Very Verbose error reporting @@ -81,12 +81,12 @@ MODULE InflowWind_Driver_Types CHARACTER(1024) :: SummaryFileName !< Filename for the summary information output CHARACTER(1024) :: PointsFileName !< Filename of points file to read in - CHARACTER(1024) :: PointsOutputName !< Filename for output from points read in from points file + CHARACTER(1024) :: PointsOutputName(3) !< Filename for output from points read in from points file CHARACTER(1024) :: FFTOutputName !< Filename for output from points read in from points file CHARACTER(1024) :: WindGridOutputName !< Filename for output from points read in from points file INTEGER(IntKi) :: WindGridOutputUnit !< Unit number for the output file for the wind grid data - INTEGER(IntKi) :: PointsOutputUnit !< Unit number for the output file for the Points file output + INTEGER(IntKi) :: PointsOutputUnit(3) !< Unit number for the output file for the Points file output INTEGER(IntKi) :: FFTOutputUnit !< Unit number for the output file for the FFT results INTEGER(IntKi) :: NumTimeSteps !< Number of timesteps diff --git a/modules/nwtc-library/CMakeLists.txt b/modules/nwtc-library/CMakeLists.txt index 33dd8e2d9a..4078fbe223 100644 --- a/modules/nwtc-library/CMakeLists.txt +++ b/modules/nwtc-library/CMakeLists.txt @@ -14,17 +14,11 @@ # limitations under the License. # -if (GENERATE_TYPES) - generate_f90_types(src/FlowField.txt ${CMAKE_CURRENT_LIST_DIR}/src/FlowField_Types.f90 -noextrap) -endif() - set(NWTCLIBS_SOURCES src/JSON.f90 src/ModMesh.f90 src/ModMesh_Mapping.f90 src/ModMesh_Types.f90 - src/FlowField.f90 - src/FlowField_Types.f90 src/NWTC_Base.f90 src/NWTC_IO.f90 src/NWTC_Library.f90 From e0e5926901d09a3cee19a612eadc285115b4f3e4 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 17 Feb 2023 23:17:27 +0000 Subject: [PATCH 10/51] Added VelInterpOrder to IfW input file --- modules/inflowwind/src/FlowField.txt | 1 + modules/inflowwind/src/FlowField_IO.f90 | 30 +- modules/inflowwind/src/FlowField_IO.txt | 3 +- modules/inflowwind/src/FlowField_IO_Types.f90 | 679 +++++++++--------- modules/inflowwind/src/FlowField_Types.f90 | 7 + modules/inflowwind/src/InflowWind.f90 | 11 +- modules/inflowwind/src/InflowWind.txt | 1 + modules/inflowwind/src/InflowWind_Subs.f90 | 4 + modules/inflowwind/src/InflowWind_Types.f90 | 7 + 9 files changed, 386 insertions(+), 357 deletions(-) diff --git a/modules/inflowwind/src/FlowField.txt b/modules/inflowwind/src/FlowField.txt index eb892c96f5..477ced3c74 100644 --- a/modules/inflowwind/src/FlowField.txt +++ b/modules/inflowwind/src/FlowField.txt @@ -102,6 +102,7 @@ typedef ^ FlowFieldType IntKi FieldType typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" radians +typedef ^ ^ IntKi VelInterpOrder - 0 - "Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7]" - typedef ^ ^ logical RotateWindBox - .false. - "flag indicating if the wind will be rotated" - typedef ^ ^ ReKi RotToWind {3}{3} - - "Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X')" - typedef ^ ^ ReKi RotFromWind {3}{3} - - "Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind)" - diff --git a/modules/inflowwind/src/FlowField_IO.f90 b/modules/inflowwind/src/FlowField_IO.f90 index 0e56b5385e..71562f8ba8 100644 --- a/modules/inflowwind/src/FlowField_IO.f90 +++ b/modules/inflowwind/src/FlowField_IO.f90 @@ -23,17 +23,17 @@ ! !********************************************************************************************************************************** -module IfW_FlowField +module FlowField_IO use NWTC_Library -use IfW_FlowField_Types +use FlowField_IO_Types use FlowField implicit none private -public :: IfW_FlowField_Init +public :: FlowField_IO_Init -type(ProgDesc), parameter :: IfW_FlowField_Ver = ProgDesc('IfW_FlowField', '', '') +type(ProgDesc), parameter :: FlowField_IO_Ver = ProgDesc('FlowField_IO', '', '') integer(IntKi), parameter :: ScaleMethod_None = 0, & !< no scaling ScaleMethod_Direct = 1, & !< direct scaling factors @@ -55,15 +55,15 @@ module IfW_FlowField !---------------------------------------------------------------------------------------------------- !> A subroutine to initialize the UserWind module. This routine will initialize the module. !---------------------------------------------------------------------------------------------------- -subroutine IfW_FlowField_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) +subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) - type(IfW_FlowField_InitInputType), intent(in) :: InitInp !< Input data for initialization + type(FlowField_IO_InitInputType), intent(in) :: InitInp !< Input data for initialization type(FlowFieldType), intent(out) :: FF !< Flow field - type(IfW_FlowField_InitOutputType), intent(out) :: InitOut !< Misc variables for optimization (not copied in glue code) + type(FlowField_IO_InitOutputType), intent(out) :: InitOut !< Misc variables for optimization (not copied in glue code) integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered character(*), intent(out) :: ErrMsg !< A message about the error. See NWTC_Library info for ErrID_* levels. - character(*), parameter :: RoutineName = 'IfW_FlowField_Init' + character(*), parameter :: RoutineName = 'FlowField_IO_Init' integer(IntKi) :: TmpErrStat ! Temp variable for the error status character(ErrMsgLen) :: TmpErrMsg ! temporary error message @@ -142,14 +142,14 @@ subroutine IfW_FlowField_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) select case (FF%FieldType) case (Uniform_FieldType) - if (InitInp%CalcAccel) then + if (InitInp%CalcAccel .or. (InitInp%VelInterpOrder == 3)) then call UniformField_CalcAccel(FF%Uniform, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return end if case (Grid_FieldType) - if (InitInp%CalcAccel) then + if (InitInp%CalcAccel .or. (InitInp%VelInterpOrder == 3)) then call GridField_CalcAccel(FF%Grid, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -197,7 +197,7 @@ subroutine IfW_FlowField_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) ! Initialization Output !---------------------------------------------------------------------------- - InitOut%Ver = IfW_FlowField_Ver + InitOut%Ver = FlowField_IO_Ver end subroutine @@ -470,7 +470,7 @@ subroutine UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) if (SumFileUnit > 0) then write (SumFileUnit, '(A)') - write (SumFileUnit, '(A)') 'Uniform wind. Module '//TRIM(IfW_FlowField_Ver%Name)//' '//TRIM(IfW_FlowField_Ver%Ver) + write (SumFileUnit, '(A)') 'Uniform wind. Module '//TRIM(FlowField_IO_Ver%Name)//' '//TRIM(FlowField_IO_Ver%Ver) write (SumFileUnit, '(A)') ' FileName: '//TRIM(InitInp%WindFileName) write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', UF%RefHeight write (SumFileUnit, '(A34,G12.4)') ' Reference length (m): ', UF%RefLength @@ -793,7 +793,7 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) if (SumFileUnit > 0) then write (SumFileUnit, '(A)') write (SumFileUnit, '(A)') 'TurbSim wind type. Read by InflowWind sub-module ' & - //TRIM(IfW_FlowField_Ver%Name)//' '//TRIM(IfW_FlowField_Ver%Ver) + //TRIM(FlowField_IO_Ver%Name)//' '//TRIM(FlowField_IO_Ver%Ver) write (SumFileUnit, '(A)') TRIM(TmpErrMsg) write (SumFileUnit, '(5x,A)') 'FileName: '//TRIM(InitInp%WindFileName) write (SumFileUnit, '(5x,A29,I3)') 'Binary file format id: ', GF%WindFileFormat @@ -1073,7 +1073,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) if (SumFileUnit > 0) then write (SumFileUnit, '(A)') - write (SumFileUnit, '(A)') 'HAWC wind type. Read by InflowWind sub-module IfW_FlowField' + write (SumFileUnit, '(A)') 'HAWC wind type. Read by InflowWind sub-module FlowField_IO' write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', GF%RefHeight write (SumFileUnit, '(A34,G12.4)') ' Timestep (s): ', GF%DTime @@ -2263,4 +2263,4 @@ subroutine PopulateWindFileDatFromGridField(GridField, FileName, WindType, HasTo ! end subroutine Read_Bladed_Tower -end module IfW_FlowField +end module FlowField_IO diff --git a/modules/inflowwind/src/FlowField_IO.txt b/modules/inflowwind/src/FlowField_IO.txt index 0d9080ea69..4e84545480 100644 --- a/modules/inflowwind/src/FlowField_IO.txt +++ b/modules/inflowwind/src/FlowField_IO.txt @@ -9,7 +9,7 @@ include Registry_NWTC_Library.txt usefrom FlowField.txt -typedef IfW_FlowField ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - +typedef FlowField_IO ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - typedef ^ OtherStateType ReKi DummyOtherState - - - "Remove this variable if you have other states" - @@ -67,6 +67,7 @@ typedef ^ InitInputType IntKi WindType typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" - +typedef ^ ^ IntKi VelInterpOrder - 0 - "Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7]" - typedef ^ ^ logical CalcAccel - .false. - "Flag to calculate acceleration data" - typedef ^ ^ SteadyInitInputType Steady - - - "" - typedef ^ ^ UniformInitInputType Uniform - - - "" - diff --git a/modules/inflowwind/src/FlowField_IO_Types.f90 b/modules/inflowwind/src/FlowField_IO_Types.f90 index 26f32019c4..667b4c3c45 100644 --- a/modules/inflowwind/src/FlowField_IO_Types.f90 +++ b/modules/inflowwind/src/FlowField_IO_Types.f90 @@ -1,13 +1,13 @@ -!STARTOFREGISTRYGENERATEDFILE 'IfW_FlowField_Types.f90' +!STARTOFREGISTRYGENERATEDFILE 'FlowField_IO_Types.f90' ! ! WARNING This file is generated automatically by the FAST registry. ! Do not edit. Your changes to this file will be lost. ! ! FAST Registry !********************************************************************************************************************************* -! IfW_FlowField_Types +! FlowField_IO_Types !................................................................................................................................. -! This file is part of IfW_FlowField. +! This file is part of FlowField_IO. ! ! Copyright (C) 2012-2016 National Renewable Energy Laboratory ! @@ -27,42 +27,42 @@ ! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. ! !********************************************************************************************************************************* -!> This module contains the user-defined types needed in IfW_FlowField. It also contains copy, destroy, pack, and +!> This module contains the user-defined types needed in FlowField_IO. It also contains copy, destroy, pack, and !! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE IfW_FlowField_Types +MODULE FlowField_IO_Types !--------------------------------------------------------------------------------------------------------------------------------- USE FlowField_Types USE NWTC_Library IMPLICIT NONE -! ========= IfW_FlowField_ContinuousStateType ======= - TYPE, PUBLIC :: IfW_FlowField_ContinuousStateType +! ========= FlowField_IO_ContinuousStateType ======= + TYPE, PUBLIC :: FlowField_IO_ContinuousStateType REAL(ReKi) :: DummyContState !< Remove this variable if you have continuous states [-] - END TYPE IfW_FlowField_ContinuousStateType + END TYPE FlowField_IO_ContinuousStateType ! ======================= -! ========= IfW_FlowField_DiscreteStateType ======= - TYPE, PUBLIC :: IfW_FlowField_DiscreteStateType +! ========= FlowField_IO_DiscreteStateType ======= + TYPE, PUBLIC :: FlowField_IO_DiscreteStateType REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] - END TYPE IfW_FlowField_DiscreteStateType + END TYPE FlowField_IO_DiscreteStateType ! ======================= -! ========= IfW_FlowField_ConstraintStateType ======= - TYPE, PUBLIC :: IfW_FlowField_ConstraintStateType +! ========= FlowField_IO_ConstraintStateType ======= + TYPE, PUBLIC :: FlowField_IO_ConstraintStateType REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] - END TYPE IfW_FlowField_ConstraintStateType + END TYPE FlowField_IO_ConstraintStateType ! ======================= -! ========= IfW_FlowField_OtherStateType ======= - TYPE, PUBLIC :: IfW_FlowField_OtherStateType +! ========= FlowField_IO_OtherStateType ======= + TYPE, PUBLIC :: FlowField_IO_OtherStateType REAL(ReKi) :: DummyOtherState !< Remove this variable if you have other states [-] - END TYPE IfW_FlowField_OtherStateType + END TYPE FlowField_IO_OtherStateType ! ======================= -! ========= IfW_FlowField_MiscVarType ======= - TYPE, PUBLIC :: IfW_FlowField_MiscVarType +! ========= FlowField_IO_MiscVarType ======= + TYPE, PUBLIC :: FlowField_IO_MiscVarType REAL(ReKi) :: DummyMiscVar !< Remove this variable if you have misc variables [-] - END TYPE IfW_FlowField_MiscVarType + END TYPE FlowField_IO_MiscVarType ! ======================= -! ========= IfW_FlowField_InputType ======= - TYPE, PUBLIC :: IfW_FlowField_InputType +! ========= FlowField_IO_InputType ======= + TYPE, PUBLIC :: FlowField_IO_InputType REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Position !< Array holding the input positions at a given timestep [meters] - END TYPE IfW_FlowField_InputType + END TYPE FlowField_IO_InputType ! ======================= ! ========= SteadyInitInputType ======= TYPE, PUBLIC :: SteadyInitInputType @@ -138,12 +138,13 @@ MODULE IfW_FlowField_Types INTEGER(IntKi) :: Dummy !< External Point field initialization input dummy value [-] END TYPE ExtPointInitInputType ! ======================= -! ========= IfW_FlowField_InitInputType ======= - TYPE, PUBLIC :: IfW_FlowField_InitInputType +! ========= FlowField_IO_InitInputType ======= + TYPE, PUBLIC :: FlowField_IO_InitInputType INTEGER(IntKi) :: WindType = 0 !< Type of the windfile [-] INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file (-1 for none). Provided by IfW. [-] REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [-] + INTEGER(IntKi) :: VelInterpOrder = 0 !< Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] [-] LOGICAL :: CalcAccel = .false. !< Flag to calculate acceleration data [-] TYPE(SteadyInitInputType) :: Steady !< [-] TYPE(UniformInitInputType) :: Uniform !< [-] @@ -153,7 +154,7 @@ MODULE IfW_FlowField_Types TYPE(UserInitInputType) :: User !< [-] TYPE(ExtGridInitInputType) :: ExtGrid !< [-] TYPE(ExtPointInitInputType) :: ExtPoint !< [-] - END TYPE IfW_FlowField_InitInputType + END TYPE FlowField_IO_InitInputType ! ======================= ! ========= WindFileDat ======= TYPE, PUBLIC :: WindFileDat @@ -177,17 +178,17 @@ MODULE IfW_FlowField_Types REAL(ReKi) :: MWS !< Approximate mean wind speed [-] END TYPE WindFileDat ! ======================= -! ========= IfW_FlowField_InitOutputType ======= - TYPE, PUBLIC :: IfW_FlowField_InitOutputType +! ========= FlowField_IO_InitOutputType ======= + TYPE, PUBLIC :: FlowField_IO_InitOutputType TYPE(ProgDesc) :: Ver !< Version information off FFWind submodule [-] TYPE(WindFileDat) :: FileDat !< [-] TYPE(BladedInitOutputType) :: Bladed !< [-] - END TYPE IfW_FlowField_InitOutputType + END TYPE FlowField_IO_InitOutputType ! ======================= CONTAINS - SUBROUTINE IfW_FlowField_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FlowField_ContinuousStateType), INTENT(IN) :: SrcContStateData - TYPE(IfW_FlowField_ContinuousStateType), INTENT(INOUT) :: DstContStateData + SUBROUTINE FlowField_IO_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FlowField_IO_ContinuousStateType), INTENT(IN) :: SrcContStateData + TYPE(FlowField_IO_ContinuousStateType), INTENT(INOUT) :: DstContStateData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -197,15 +198,15 @@ SUBROUTINE IfW_FlowField_CopyContState( SrcContStateData, DstContStateData, Ctrl INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyContState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyContState' ! ErrStat = ErrID_None ErrMsg = "" DstContStateData%DummyContState = SrcContStateData%DummyContState - END SUBROUTINE IfW_FlowField_CopyContState + END SUBROUTINE FlowField_IO_CopyContState - SUBROUTINE IfW_FlowField_DestroyContState( ContStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FlowField_ContinuousStateType), INTENT(INOUT) :: ContStateData + SUBROUTINE FlowField_IO_DestroyContState( ContStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(FlowField_IO_ContinuousStateType), INTENT(INOUT) :: ContStateData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -214,7 +215,7 @@ SUBROUTINE IfW_FlowField_DestroyContState( ContStateData, ErrStat, ErrMsg, DEALL LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyContState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyContState' ErrStat = ErrID_None ErrMsg = "" @@ -225,13 +226,13 @@ SUBROUTINE IfW_FlowField_DestroyContState( ContStateData, ErrStat, ErrMsg, DEALL DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyContState + END SUBROUTINE FlowField_IO_DestroyContState - SUBROUTINE IfW_FlowField_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FlowField_ContinuousStateType), INTENT(IN) :: InData + TYPE(FlowField_IO_ContinuousStateType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -246,7 +247,7 @@ SUBROUTINE IfW_FlowField_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackContState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackContState' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -292,13 +293,13 @@ SUBROUTINE IfW_FlowField_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ReKiBuf(Re_Xferred) = InData%DummyContState Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackContState + END SUBROUTINE FlowField_IO_PackContState - SUBROUTINE IfW_FlowField_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FlowField_ContinuousStateType), INTENT(INOUT) :: OutData + TYPE(FlowField_IO_ContinuousStateType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -311,7 +312,7 @@ SUBROUTINE IfW_FlowField_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackContState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackContState' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -324,11 +325,11 @@ SUBROUTINE IfW_FlowField_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Xferred = 1 OutData%DummyContState = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackContState + END SUBROUTINE FlowField_IO_UnPackContState - SUBROUTINE IfW_FlowField_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FlowField_DiscreteStateType), INTENT(IN) :: SrcDiscStateData - TYPE(IfW_FlowField_DiscreteStateType), INTENT(INOUT) :: DstDiscStateData + SUBROUTINE FlowField_IO_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FlowField_IO_DiscreteStateType), INTENT(IN) :: SrcDiscStateData + TYPE(FlowField_IO_DiscreteStateType), INTENT(INOUT) :: DstDiscStateData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -336,15 +337,15 @@ SUBROUTINE IfW_FlowField_CopyDiscState( SrcDiscStateData, DstDiscStateData, Ctrl INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyDiscState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyDiscState' ! ErrStat = ErrID_None ErrMsg = "" DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState - END SUBROUTINE IfW_FlowField_CopyDiscState + END SUBROUTINE FlowField_IO_CopyDiscState - SUBROUTINE IfW_FlowField_DestroyDiscState( DiscStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FlowField_DiscreteStateType), INTENT(INOUT) :: DiscStateData + SUBROUTINE FlowField_IO_DestroyDiscState( DiscStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(FlowField_IO_DiscreteStateType), INTENT(INOUT) :: DiscStateData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -353,7 +354,7 @@ SUBROUTINE IfW_FlowField_DestroyDiscState( DiscStateData, ErrStat, ErrMsg, DEALL LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyDiscState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyDiscState' ErrStat = ErrID_None ErrMsg = "" @@ -364,13 +365,13 @@ SUBROUTINE IfW_FlowField_DestroyDiscState( DiscStateData, ErrStat, ErrMsg, DEALL DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyDiscState + END SUBROUTINE FlowField_IO_DestroyDiscState - SUBROUTINE IfW_FlowField_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FlowField_DiscreteStateType), INTENT(IN) :: InData + TYPE(FlowField_IO_DiscreteStateType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -385,7 +386,7 @@ SUBROUTINE IfW_FlowField_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackDiscState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackDiscState' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -431,13 +432,13 @@ SUBROUTINE IfW_FlowField_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ReKiBuf(Re_Xferred) = InData%DummyDiscState Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackDiscState + END SUBROUTINE FlowField_IO_PackDiscState - SUBROUTINE IfW_FlowField_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FlowField_DiscreteStateType), INTENT(INOUT) :: OutData + TYPE(FlowField_IO_DiscreteStateType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -448,7 +449,7 @@ SUBROUTINE IfW_FlowField_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackDiscState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackDiscState' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -461,11 +462,11 @@ SUBROUTINE IfW_FlowField_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Xferred = 1 OutData%DummyDiscState = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackDiscState + END SUBROUTINE FlowField_IO_UnPackDiscState - SUBROUTINE IfW_FlowField_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FlowField_ConstraintStateType), INTENT(IN) :: SrcConstrStateData - TYPE(IfW_FlowField_ConstraintStateType), INTENT(INOUT) :: DstConstrStateData + SUBROUTINE FlowField_IO_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FlowField_IO_ConstraintStateType), INTENT(IN) :: SrcConstrStateData + TYPE(FlowField_IO_ConstraintStateType), INTENT(INOUT) :: DstConstrStateData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -473,15 +474,15 @@ SUBROUTINE IfW_FlowField_CopyConstrState( SrcConstrStateData, DstConstrStateData INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyConstrState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyConstrState' ! ErrStat = ErrID_None ErrMsg = "" DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState - END SUBROUTINE IfW_FlowField_CopyConstrState + END SUBROUTINE FlowField_IO_CopyConstrState - SUBROUTINE IfW_FlowField_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FlowField_ConstraintStateType), INTENT(INOUT) :: ConstrStateData + SUBROUTINE FlowField_IO_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(FlowField_IO_ConstraintStateType), INTENT(INOUT) :: ConstrStateData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -490,7 +491,7 @@ SUBROUTINE IfW_FlowField_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg, D LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyConstrState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyConstrState' ErrStat = ErrID_None ErrMsg = "" @@ -501,13 +502,13 @@ SUBROUTINE IfW_FlowField_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg, D DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyConstrState + END SUBROUTINE FlowField_IO_DestroyConstrState - SUBROUTINE IfW_FlowField_PackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FlowField_ConstraintStateType), INTENT(IN) :: InData + TYPE(FlowField_IO_ConstraintStateType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -522,7 +523,7 @@ SUBROUTINE IfW_FlowField_PackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackConstrState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackConstrState' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -568,13 +569,13 @@ SUBROUTINE IfW_FlowField_PackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er ReKiBuf(Re_Xferred) = InData%DummyConstrState Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackConstrState + END SUBROUTINE FlowField_IO_PackConstrState - SUBROUTINE IfW_FlowField_UnPackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FlowField_ConstraintStateType), INTENT(INOUT) :: OutData + TYPE(FlowField_IO_ConstraintStateType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -585,7 +586,7 @@ SUBROUTINE IfW_FlowField_UnPackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackConstrState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackConstrState' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -598,11 +599,11 @@ SUBROUTINE IfW_FlowField_UnPackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Int_Xferred = 1 OutData%DummyConstrState = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackConstrState + END SUBROUTINE FlowField_IO_UnPackConstrState - SUBROUTINE IfW_FlowField_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FlowField_OtherStateType), INTENT(IN) :: SrcOtherStateData - TYPE(IfW_FlowField_OtherStateType), INTENT(INOUT) :: DstOtherStateData + SUBROUTINE FlowField_IO_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FlowField_IO_OtherStateType), INTENT(IN) :: SrcOtherStateData + TYPE(FlowField_IO_OtherStateType), INTENT(INOUT) :: DstOtherStateData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -610,15 +611,15 @@ SUBROUTINE IfW_FlowField_CopyOtherState( SrcOtherStateData, DstOtherStateData, C INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyOtherState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyOtherState' ! ErrStat = ErrID_None ErrMsg = "" DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState - END SUBROUTINE IfW_FlowField_CopyOtherState + END SUBROUTINE FlowField_IO_CopyOtherState - SUBROUTINE IfW_FlowField_DestroyOtherState( OtherStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FlowField_OtherStateType), INTENT(INOUT) :: OtherStateData + SUBROUTINE FlowField_IO_DestroyOtherState( OtherStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(FlowField_IO_OtherStateType), INTENT(INOUT) :: OtherStateData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -627,7 +628,7 @@ SUBROUTINE IfW_FlowField_DestroyOtherState( OtherStateData, ErrStat, ErrMsg, DEA LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyOtherState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyOtherState' ErrStat = ErrID_None ErrMsg = "" @@ -638,13 +639,13 @@ SUBROUTINE IfW_FlowField_DestroyOtherState( OtherStateData, ErrStat, ErrMsg, DEA DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyOtherState + END SUBROUTINE FlowField_IO_DestroyOtherState - SUBROUTINE IfW_FlowField_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FlowField_OtherStateType), INTENT(IN) :: InData + TYPE(FlowField_IO_OtherStateType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -659,7 +660,7 @@ SUBROUTINE IfW_FlowField_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Err LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackOtherState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackOtherState' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -705,13 +706,13 @@ SUBROUTINE IfW_FlowField_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Err ReKiBuf(Re_Xferred) = InData%DummyOtherState Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackOtherState + END SUBROUTINE FlowField_IO_PackOtherState - SUBROUTINE IfW_FlowField_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FlowField_OtherStateType), INTENT(INOUT) :: OutData + TYPE(FlowField_IO_OtherStateType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -722,7 +723,7 @@ SUBROUTINE IfW_FlowField_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackOtherState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackOtherState' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -735,11 +736,11 @@ SUBROUTINE IfW_FlowField_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Int_Xferred = 1 OutData%DummyOtherState = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackOtherState + END SUBROUTINE FlowField_IO_UnPackOtherState - SUBROUTINE IfW_FlowField_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FlowField_MiscVarType), INTENT(IN) :: SrcMiscData - TYPE(IfW_FlowField_MiscVarType), INTENT(INOUT) :: DstMiscData + SUBROUTINE FlowField_IO_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FlowField_IO_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(FlowField_IO_MiscVarType), INTENT(INOUT) :: DstMiscData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -747,15 +748,15 @@ SUBROUTINE IfW_FlowField_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyMisc' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyMisc' ! ErrStat = ErrID_None ErrMsg = "" DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar - END SUBROUTINE IfW_FlowField_CopyMisc + END SUBROUTINE FlowField_IO_CopyMisc - SUBROUTINE IfW_FlowField_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FlowField_MiscVarType), INTENT(INOUT) :: MiscData + SUBROUTINE FlowField_IO_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(FlowField_IO_MiscVarType), INTENT(INOUT) :: MiscData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -764,7 +765,7 @@ SUBROUTINE IfW_FlowField_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpoint LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyMisc' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyMisc' ErrStat = ErrID_None ErrMsg = "" @@ -775,13 +776,13 @@ SUBROUTINE IfW_FlowField_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpoint DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyMisc + END SUBROUTINE FlowField_IO_DestroyMisc - SUBROUTINE IfW_FlowField_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FlowField_MiscVarType), INTENT(IN) :: InData + TYPE(FlowField_IO_MiscVarType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -796,7 +797,7 @@ SUBROUTINE IfW_FlowField_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackMisc' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackMisc' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -842,13 +843,13 @@ SUBROUTINE IfW_FlowField_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ReKiBuf(Re_Xferred) = InData%DummyMiscVar Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackMisc + END SUBROUTINE FlowField_IO_PackMisc - SUBROUTINE IfW_FlowField_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FlowField_MiscVarType), INTENT(INOUT) :: OutData + TYPE(FlowField_IO_MiscVarType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -859,7 +860,7 @@ SUBROUTINE IfW_FlowField_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackMisc' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackMisc' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -872,11 +873,11 @@ SUBROUTINE IfW_FlowField_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta Int_Xferred = 1 OutData%DummyMiscVar = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackMisc + END SUBROUTINE FlowField_IO_UnPackMisc - SUBROUTINE IfW_FlowField_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FlowField_InputType), INTENT(IN) :: SrcInputData - TYPE(IfW_FlowField_InputType), INTENT(INOUT) :: DstInputData + SUBROUTINE FlowField_IO_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FlowField_IO_InputType), INTENT(IN) :: SrcInputData + TYPE(FlowField_IO_InputType), INTENT(INOUT) :: DstInputData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -886,7 +887,7 @@ SUBROUTINE IfW_FlowField_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrSta INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyInput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyInput' ! ErrStat = ErrID_None ErrMsg = "" @@ -904,10 +905,10 @@ SUBROUTINE IfW_FlowField_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrSta END IF DstInputData%Position = SrcInputData%Position ENDIF - END SUBROUTINE IfW_FlowField_CopyInput + END SUBROUTINE FlowField_IO_CopyInput - SUBROUTINE IfW_FlowField_DestroyInput( InputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FlowField_InputType), INTENT(INOUT) :: InputData + SUBROUTINE FlowField_IO_DestroyInput( InputData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(FlowField_IO_InputType), INTENT(INOUT) :: InputData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -916,7 +917,7 @@ SUBROUTINE IfW_FlowField_DestroyInput( InputData, ErrStat, ErrMsg, DEALLOCATEpoi LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyInput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyInput' ErrStat = ErrID_None ErrMsg = "" @@ -930,13 +931,13 @@ SUBROUTINE IfW_FlowField_DestroyInput( InputData, ErrStat, ErrMsg, DEALLOCATEpoi IF (ALLOCATED(InputData%Position)) THEN DEALLOCATE(InputData%Position) ENDIF - END SUBROUTINE IfW_FlowField_DestroyInput + END SUBROUTINE FlowField_IO_DestroyInput - SUBROUTINE IfW_FlowField_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FlowField_InputType), INTENT(IN) :: InData + TYPE(FlowField_IO_InputType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -951,7 +952,7 @@ SUBROUTINE IfW_FlowField_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackInput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackInput' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1019,13 +1020,13 @@ SUBROUTINE IfW_FlowField_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, END DO END DO END IF - END SUBROUTINE IfW_FlowField_PackInput + END SUBROUTINE FlowField_IO_PackInput - SUBROUTINE IfW_FlowField_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FlowField_InputType), INTENT(INOUT) :: OutData + TYPE(FlowField_IO_InputType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -1038,7 +1039,7 @@ SUBROUTINE IfW_FlowField_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackInput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackInput' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1072,9 +1073,9 @@ SUBROUTINE IfW_FlowField_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSt END DO END DO END IF - END SUBROUTINE IfW_FlowField_UnPackInput + END SUBROUTINE FlowField_IO_UnPackInput - SUBROUTINE IfW_FlowField_CopySteadyInitInputType( SrcSteadyInitInputTypeData, DstSteadyInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopySteadyInitInputType( SrcSteadyInitInputTypeData, DstSteadyInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(SteadyInitInputType), INTENT(IN) :: SrcSteadyInitInputTypeData TYPE(SteadyInitInputType), INTENT(INOUT) :: DstSteadyInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -1084,16 +1085,16 @@ SUBROUTINE IfW_FlowField_CopySteadyInitInputType( SrcSteadyInitInputTypeData, Ds INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopySteadyInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopySteadyInitInputType' ! ErrStat = ErrID_None ErrMsg = "" DstSteadyInitInputTypeData%HWindSpeed = SrcSteadyInitInputTypeData%HWindSpeed DstSteadyInitInputTypeData%RefHt = SrcSteadyInitInputTypeData%RefHt DstSteadyInitInputTypeData%PLExp = SrcSteadyInitInputTypeData%PLExp - END SUBROUTINE IfW_FlowField_CopySteadyInitInputType + END SUBROUTINE FlowField_IO_CopySteadyInitInputType - SUBROUTINE IfW_FlowField_DestroySteadyInitInputType( SteadyInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroySteadyInitInputType( SteadyInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(SteadyInitInputType), INTENT(INOUT) :: SteadyInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1103,7 +1104,7 @@ SUBROUTINE IfW_FlowField_DestroySteadyInitInputType( SteadyInitInputTypeData, Er LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroySteadyInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroySteadyInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -1114,9 +1115,9 @@ SUBROUTINE IfW_FlowField_DestroySteadyInitInputType( SteadyInitInputTypeData, Er DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroySteadyInitInputType + END SUBROUTINE FlowField_IO_DestroySteadyInitInputType - SUBROUTINE IfW_FlowField_PackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -1135,7 +1136,7 @@ SUBROUTINE IfW_FlowField_PackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, In LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackSteadyInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackSteadyInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1187,9 +1188,9 @@ SUBROUTINE IfW_FlowField_PackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, In Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%PLExp Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackSteadyInitInputType + END SUBROUTINE FlowField_IO_PackSteadyInitInputType - SUBROUTINE IfW_FlowField_UnPackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -1204,7 +1205,7 @@ SUBROUTINE IfW_FlowField_UnPackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackSteadyInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackSteadyInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1221,9 +1222,9 @@ SUBROUTINE IfW_FlowField_UnPackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Re_Xferred = Re_Xferred + 1 OutData%PLExp = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackSteadyInitInputType + END SUBROUTINE FlowField_IO_UnPackSteadyInitInputType - SUBROUTINE IfW_FlowField_CopyUniformInitInputType( SrcUniformInitInputTypeData, DstUniformInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopyUniformInitInputType( SrcUniformInitInputTypeData, DstUniformInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(UniformInitInputType), INTENT(IN) :: SrcUniformInitInputTypeData TYPE(UniformInitInputType), INTENT(INOUT) :: DstUniformInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -1233,7 +1234,7 @@ SUBROUTINE IfW_FlowField_CopyUniformInitInputType( SrcUniformInitInputTypeData, INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyUniformInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyUniformInitInputType' ! ErrStat = ErrID_None ErrMsg = "" @@ -1245,9 +1246,9 @@ SUBROUTINE IfW_FlowField_CopyUniformInitInputType( SrcUniformInitInputTypeData, CALL NWTC_Library_Copyfileinfotype( SrcUniformInitInputTypeData%PassedFileData, DstUniformInitInputTypeData%PassedFileData, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_FlowField_CopyUniformInitInputType + END SUBROUTINE FlowField_IO_CopyUniformInitInputType - SUBROUTINE IfW_FlowField_DestroyUniformInitInputType( UniformInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroyUniformInitInputType( UniformInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(UniformInitInputType), INTENT(INOUT) :: UniformInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1257,7 +1258,7 @@ SUBROUTINE IfW_FlowField_DestroyUniformInitInputType( UniformInitInputTypeData, LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyUniformInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyUniformInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -1270,9 +1271,9 @@ SUBROUTINE IfW_FlowField_DestroyUniformInitInputType( UniformInitInputTypeData, CALL NWTC_Library_Destroyfileinfotype( UniformInitInputTypeData%PassedFileData, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_FlowField_DestroyUniformInitInputType + END SUBROUTINE FlowField_IO_DestroyUniformInitInputType - SUBROUTINE IfW_FlowField_PackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -1291,7 +1292,7 @@ SUBROUTINE IfW_FlowField_PackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackUniformInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackUniformInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1397,9 +1398,9 @@ SUBROUTINE IfW_FlowField_PackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - END SUBROUTINE IfW_FlowField_PackUniformInitInputType + END SUBROUTINE FlowField_IO_PackUniformInitInputType - SUBROUTINE IfW_FlowField_UnPackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -1414,7 +1415,7 @@ SUBROUTINE IfW_FlowField_UnPackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackUniformInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackUniformInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1477,9 +1478,9 @@ SUBROUTINE IfW_FlowField_UnPackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_FlowField_UnPackUniformInitInputType + END SUBROUTINE FlowField_IO_UnPackUniformInitInputType - SUBROUTINE IfW_FlowField_CopyTurbSimInitInputType( SrcTurbSimInitInputTypeData, DstTurbSimInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopyTurbSimInitInputType( SrcTurbSimInitInputTypeData, DstTurbSimInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(TurbSimInitInputType), INTENT(IN) :: SrcTurbSimInitInputTypeData TYPE(TurbSimInitInputType), INTENT(INOUT) :: DstTurbSimInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -1489,14 +1490,14 @@ SUBROUTINE IfW_FlowField_CopyTurbSimInitInputType( SrcTurbSimInitInputTypeData, INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyTurbSimInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyTurbSimInitInputType' ! ErrStat = ErrID_None ErrMsg = "" DstTurbSimInitInputTypeData%WindFileName = SrcTurbSimInitInputTypeData%WindFileName - END SUBROUTINE IfW_FlowField_CopyTurbSimInitInputType + END SUBROUTINE FlowField_IO_CopyTurbSimInitInputType - SUBROUTINE IfW_FlowField_DestroyTurbSimInitInputType( TurbSimInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroyTurbSimInitInputType( TurbSimInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(TurbSimInitInputType), INTENT(INOUT) :: TurbSimInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1506,7 +1507,7 @@ SUBROUTINE IfW_FlowField_DestroyTurbSimInitInputType( TurbSimInitInputTypeData, LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyTurbSimInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyTurbSimInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -1517,9 +1518,9 @@ SUBROUTINE IfW_FlowField_DestroyTurbSimInitInputType( TurbSimInitInputTypeData, DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyTurbSimInitInputType + END SUBROUTINE FlowField_IO_DestroyTurbSimInitInputType - SUBROUTINE IfW_FlowField_PackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -1538,7 +1539,7 @@ SUBROUTINE IfW_FlowField_PackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackTurbSimInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackTurbSimInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1586,9 +1587,9 @@ SUBROUTINE IfW_FlowField_PackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I - END SUBROUTINE IfW_FlowField_PackTurbSimInitInputType + END SUBROUTINE FlowField_IO_PackTurbSimInitInputType - SUBROUTINE IfW_FlowField_UnPackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -1603,7 +1604,7 @@ SUBROUTINE IfW_FlowField_UnPackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackTurbSimInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackTurbSimInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1618,9 +1619,9 @@ SUBROUTINE IfW_FlowField_UnPackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) Int_Xferred = Int_Xferred + 1 END DO ! I - END SUBROUTINE IfW_FlowField_UnPackTurbSimInitInputType + END SUBROUTINE FlowField_IO_UnPackTurbSimInitInputType - SUBROUTINE IfW_FlowField_CopyBladedInitInputType( SrcBladedInitInputTypeData, DstBladedInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopyBladedInitInputType( SrcBladedInitInputTypeData, DstBladedInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(BladedInitInputType), INTENT(IN) :: SrcBladedInitInputTypeData TYPE(BladedInitInputType), INTENT(INOUT) :: DstBladedInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -1630,7 +1631,7 @@ SUBROUTINE IfW_FlowField_CopyBladedInitInputType( SrcBladedInitInputTypeData, Ds INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyBladedInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyBladedInitInputType' ! ErrStat = ErrID_None ErrMsg = "" @@ -1638,9 +1639,9 @@ SUBROUTINE IfW_FlowField_CopyBladedInitInputType( SrcBladedInitInputTypeData, Ds DstBladedInitInputTypeData%NativeBladedFmt = SrcBladedInitInputTypeData%NativeBladedFmt DstBladedInitInputTypeData%TowerFileExist = SrcBladedInitInputTypeData%TowerFileExist DstBladedInitInputTypeData%TurbineID = SrcBladedInitInputTypeData%TurbineID - END SUBROUTINE IfW_FlowField_CopyBladedInitInputType + END SUBROUTINE FlowField_IO_CopyBladedInitInputType - SUBROUTINE IfW_FlowField_DestroyBladedInitInputType( BladedInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroyBladedInitInputType( BladedInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(BladedInitInputType), INTENT(INOUT) :: BladedInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1650,7 +1651,7 @@ SUBROUTINE IfW_FlowField_DestroyBladedInitInputType( BladedInitInputTypeData, Er LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyBladedInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyBladedInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -1661,9 +1662,9 @@ SUBROUTINE IfW_FlowField_DestroyBladedInitInputType( BladedInitInputTypeData, Er DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyBladedInitInputType + END SUBROUTINE FlowField_IO_DestroyBladedInitInputType - SUBROUTINE IfW_FlowField_PackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -1682,7 +1683,7 @@ SUBROUTINE IfW_FlowField_PackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, In LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackBladedInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackBladedInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1739,9 +1740,9 @@ SUBROUTINE IfW_FlowField_PackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, In Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%TurbineID Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackBladedInitInputType + END SUBROUTINE FlowField_IO_PackBladedInitInputType - SUBROUTINE IfW_FlowField_UnPackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -1756,7 +1757,7 @@ SUBROUTINE IfW_FlowField_UnPackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackBladedInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackBladedInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1777,9 +1778,9 @@ SUBROUTINE IfW_FlowField_UnPackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Int_Xferred = Int_Xferred + 1 OutData%TurbineID = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackBladedInitInputType + END SUBROUTINE FlowField_IO_UnPackBladedInitInputType - SUBROUTINE IfW_FlowField_CopyBladedInitOutputType( SrcBladedInitOutputTypeData, DstBladedInitOutputTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopyBladedInitOutputType( SrcBladedInitOutputTypeData, DstBladedInitOutputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(BladedInitOutputType), INTENT(IN) :: SrcBladedInitOutputTypeData TYPE(BladedInitOutputType), INTENT(INOUT) :: DstBladedInitOutputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -1790,16 +1791,16 @@ SUBROUTINE IfW_FlowField_CopyBladedInitOutputType( SrcBladedInitOutputTypeData, INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyBladedInitOutputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyBladedInitOutputType' ! ErrStat = ErrID_None ErrMsg = "" DstBladedInitOutputTypeData%TI = SrcBladedInitOutputTypeData%TI DstBladedInitOutputTypeData%PropagationDir = SrcBladedInitOutputTypeData%PropagationDir DstBladedInitOutputTypeData%VFlowAngle = SrcBladedInitOutputTypeData%VFlowAngle - END SUBROUTINE IfW_FlowField_CopyBladedInitOutputType + END SUBROUTINE FlowField_IO_CopyBladedInitOutputType - SUBROUTINE IfW_FlowField_DestroyBladedInitOutputType( BladedInitOutputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroyBladedInitOutputType( BladedInitOutputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(BladedInitOutputType), INTENT(INOUT) :: BladedInitOutputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1809,7 +1810,7 @@ SUBROUTINE IfW_FlowField_DestroyBladedInitOutputType( BladedInitOutputTypeData, LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyBladedInitOutputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyBladedInitOutputType' ErrStat = ErrID_None ErrMsg = "" @@ -1820,9 +1821,9 @@ SUBROUTINE IfW_FlowField_DestroyBladedInitOutputType( BladedInitOutputTypeData, DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyBladedInitOutputType + END SUBROUTINE FlowField_IO_DestroyBladedInitOutputType - SUBROUTINE IfW_FlowField_PackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -1841,7 +1842,7 @@ SUBROUTINE IfW_FlowField_PackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, I LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackBladedInitOutputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackBladedInitOutputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1895,9 +1896,9 @@ SUBROUTINE IfW_FlowField_PackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, I Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VFlowAngle Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackBladedInitOutputType + END SUBROUTINE FlowField_IO_PackBladedInitOutputType - SUBROUTINE IfW_FlowField_UnPackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -1913,7 +1914,7 @@ SUBROUTINE IfW_FlowField_UnPackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackBladedInitOutputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackBladedInitOutputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1934,9 +1935,9 @@ SUBROUTINE IfW_FlowField_UnPackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Re_Xferred = Re_Xferred + 1 OutData%VFlowAngle = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackBladedInitOutputType + END SUBROUTINE FlowField_IO_UnPackBladedInitOutputType - SUBROUTINE IfW_FlowField_CopyHAWCInitInputType( SrcHAWCInitInputTypeData, DstHAWCInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopyHAWCInitInputType( SrcHAWCInitInputTypeData, DstHAWCInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(HAWCInitInputType), INTENT(IN) :: SrcHAWCInitInputTypeData TYPE(HAWCInitInputType), INTENT(INOUT) :: DstHAWCInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -1947,7 +1948,7 @@ SUBROUTINE IfW_FlowField_CopyHAWCInitInputType( SrcHAWCInitInputTypeData, DstHAW INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyHAWCInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyHAWCInitInputType' ! ErrStat = ErrID_None ErrMsg = "" @@ -1967,9 +1968,9 @@ SUBROUTINE IfW_FlowField_CopyHAWCInitInputType( SrcHAWCInitInputTypeData, DstHAW DstHAWCInitInputTypeData%PLExp = SrcHAWCInitInputTypeData%PLExp DstHAWCInitInputTypeData%Z0 = SrcHAWCInitInputTypeData%Z0 DstHAWCInitInputTypeData%XOffset = SrcHAWCInitInputTypeData%XOffset - END SUBROUTINE IfW_FlowField_CopyHAWCInitInputType + END SUBROUTINE FlowField_IO_CopyHAWCInitInputType - SUBROUTINE IfW_FlowField_DestroyHAWCInitInputType( HAWCInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroyHAWCInitInputType( HAWCInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(HAWCInitInputType), INTENT(INOUT) :: HAWCInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1979,7 +1980,7 @@ SUBROUTINE IfW_FlowField_DestroyHAWCInitInputType( HAWCInitInputTypeData, ErrSta LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyHAWCInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyHAWCInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -1990,9 +1991,9 @@ SUBROUTINE IfW_FlowField_DestroyHAWCInitInputType( HAWCInitInputTypeData, ErrSta DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyHAWCInitInputType + END SUBROUTINE FlowField_IO_DestroyHAWCInitInputType - SUBROUTINE IfW_FlowField_PackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -2011,7 +2012,7 @@ SUBROUTINE IfW_FlowField_PackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Inda LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackHAWCInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackHAWCInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2110,9 +2111,9 @@ SUBROUTINE IfW_FlowField_PackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Inda Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%XOffset Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackHAWCInitInputType + END SUBROUTINE FlowField_IO_PackHAWCInitInputType - SUBROUTINE IfW_FlowField_UnPackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -2128,7 +2129,7 @@ SUBROUTINE IfW_FlowField_UnPackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Ou INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackHAWCInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackHAWCInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2185,9 +2186,9 @@ SUBROUTINE IfW_FlowField_UnPackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Ou Re_Xferred = Re_Xferred + 1 OutData%XOffset = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackHAWCInitInputType + END SUBROUTINE FlowField_IO_UnPackHAWCInitInputType - SUBROUTINE IfW_FlowField_CopyUserInitInputType( SrcUserInitInputTypeData, DstUserInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopyUserInitInputType( SrcUserInitInputTypeData, DstUserInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(UserInitInputType), INTENT(IN) :: SrcUserInitInputTypeData TYPE(UserInitInputType), INTENT(INOUT) :: DstUserInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -2197,14 +2198,14 @@ SUBROUTINE IfW_FlowField_CopyUserInitInputType( SrcUserInitInputTypeData, DstUse INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyUserInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyUserInitInputType' ! ErrStat = ErrID_None ErrMsg = "" DstUserInitInputTypeData%Dummy = SrcUserInitInputTypeData%Dummy - END SUBROUTINE IfW_FlowField_CopyUserInitInputType + END SUBROUTINE FlowField_IO_CopyUserInitInputType - SUBROUTINE IfW_FlowField_DestroyUserInitInputType( UserInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroyUserInitInputType( UserInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(UserInitInputType), INTENT(INOUT) :: UserInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2214,7 +2215,7 @@ SUBROUTINE IfW_FlowField_DestroyUserInitInputType( UserInitInputTypeData, ErrSta LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyUserInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyUserInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -2225,9 +2226,9 @@ SUBROUTINE IfW_FlowField_DestroyUserInitInputType( UserInitInputTypeData, ErrSta DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyUserInitInputType + END SUBROUTINE FlowField_IO_DestroyUserInitInputType - SUBROUTINE IfW_FlowField_PackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -2246,7 +2247,7 @@ SUBROUTINE IfW_FlowField_PackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Inda LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackUserInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackUserInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2292,9 +2293,9 @@ SUBROUTINE IfW_FlowField_PackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Inda ReKiBuf(Re_Xferred) = InData%Dummy Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackUserInitInputType + END SUBROUTINE FlowField_IO_PackUserInitInputType - SUBROUTINE IfW_FlowField_UnPackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -2309,7 +2310,7 @@ SUBROUTINE IfW_FlowField_UnPackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Ou INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackUserInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackUserInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2322,9 +2323,9 @@ SUBROUTINE IfW_FlowField_UnPackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Ou Int_Xferred = 1 OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackUserInitInputType + END SUBROUTINE FlowField_IO_UnPackUserInitInputType - SUBROUTINE IfW_FlowField_CopyExtGridInitInputType( SrcExtGridInitInputTypeData, DstExtGridInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopyExtGridInitInputType( SrcExtGridInitInputTypeData, DstExtGridInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(ExtGridInitInputType), INTENT(IN) :: SrcExtGridInitInputTypeData TYPE(ExtGridInitInputType), INTENT(INOUT) :: DstExtGridInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -2335,16 +2336,16 @@ SUBROUTINE IfW_FlowField_CopyExtGridInitInputType( SrcExtGridInitInputTypeData, INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyExtGridInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyExtGridInitInputType' ! ErrStat = ErrID_None ErrMsg = "" DstExtGridInitInputTypeData%n = SrcExtGridInitInputTypeData%n DstExtGridInitInputTypeData%delta = SrcExtGridInitInputTypeData%delta DstExtGridInitInputTypeData%pZero = SrcExtGridInitInputTypeData%pZero - END SUBROUTINE IfW_FlowField_CopyExtGridInitInputType + END SUBROUTINE FlowField_IO_CopyExtGridInitInputType - SUBROUTINE IfW_FlowField_DestroyExtGridInitInputType( ExtGridInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroyExtGridInitInputType( ExtGridInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(ExtGridInitInputType), INTENT(INOUT) :: ExtGridInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2354,7 +2355,7 @@ SUBROUTINE IfW_FlowField_DestroyExtGridInitInputType( ExtGridInitInputTypeData, LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyExtGridInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyExtGridInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -2365,9 +2366,9 @@ SUBROUTINE IfW_FlowField_DestroyExtGridInitInputType( ExtGridInitInputTypeData, DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyExtGridInitInputType + END SUBROUTINE FlowField_IO_DestroyExtGridInitInputType - SUBROUTINE IfW_FlowField_PackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -2386,7 +2387,7 @@ SUBROUTINE IfW_FlowField_PackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackExtGridInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackExtGridInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2444,9 +2445,9 @@ SUBROUTINE IfW_FlowField_PackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I ReKiBuf(Re_Xferred) = InData%pZero(i1) Re_Xferred = Re_Xferred + 1 END DO - END SUBROUTINE IfW_FlowField_PackExtGridInitInputType + END SUBROUTINE FlowField_IO_PackExtGridInitInputType - SUBROUTINE IfW_FlowField_UnPackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -2462,7 +2463,7 @@ SUBROUTINE IfW_FlowField_UnPackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackExtGridInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackExtGridInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2491,9 +2492,9 @@ SUBROUTINE IfW_FlowField_UnPackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, OutData%pZero(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO - END SUBROUTINE IfW_FlowField_UnPackExtGridInitInputType + END SUBROUTINE FlowField_IO_UnPackExtGridInitInputType - SUBROUTINE IfW_FlowField_CopyExtPointInitInputType( SrcExtPointInitInputTypeData, DstExtPointInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopyExtPointInitInputType( SrcExtPointInitInputTypeData, DstExtPointInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(ExtPointInitInputType), INTENT(IN) :: SrcExtPointInitInputTypeData TYPE(ExtPointInitInputType), INTENT(INOUT) :: DstExtPointInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -2503,14 +2504,14 @@ SUBROUTINE IfW_FlowField_CopyExtPointInitInputType( SrcExtPointInitInputTypeData INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyExtPointInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyExtPointInitInputType' ! ErrStat = ErrID_None ErrMsg = "" DstExtPointInitInputTypeData%Dummy = SrcExtPointInitInputTypeData%Dummy - END SUBROUTINE IfW_FlowField_CopyExtPointInitInputType + END SUBROUTINE FlowField_IO_CopyExtPointInitInputType - SUBROUTINE IfW_FlowField_DestroyExtPointInitInputType( ExtPointInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroyExtPointInitInputType( ExtPointInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(ExtPointInitInputType), INTENT(INOUT) :: ExtPointInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2520,7 +2521,7 @@ SUBROUTINE IfW_FlowField_DestroyExtPointInitInputType( ExtPointInitInputTypeData LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyExtPointInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyExtPointInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -2531,9 +2532,9 @@ SUBROUTINE IfW_FlowField_DestroyExtPointInitInputType( ExtPointInitInputTypeData DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyExtPointInitInputType + END SUBROUTINE FlowField_IO_DestroyExtPointInitInputType - SUBROUTINE IfW_FlowField_PackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -2552,7 +2553,7 @@ SUBROUTINE IfW_FlowField_PackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackExtPointInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackExtPointInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2598,9 +2599,9 @@ SUBROUTINE IfW_FlowField_PackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, IntKiBuf(Int_Xferred) = InData%Dummy Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackExtPointInitInputType + END SUBROUTINE FlowField_IO_PackExtPointInitInputType - SUBROUTINE IfW_FlowField_UnPackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -2615,7 +2616,7 @@ SUBROUTINE IfW_FlowField_UnPackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackExtPointInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackExtPointInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2628,11 +2629,11 @@ SUBROUTINE IfW_FlowField_UnPackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf Int_Xferred = 1 OutData%Dummy = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackExtPointInitInputType + END SUBROUTINE FlowField_IO_UnPackExtPointInitInputType - SUBROUTINE IfW_FlowField_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FlowField_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(IfW_FlowField_InitInputType), INTENT(INOUT) :: DstInitInputData + SUBROUTINE FlowField_IO_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FlowField_IO_InitInputType), INTENT(IN) :: SrcInitInputData + TYPE(FlowField_IO_InitInputType), INTENT(INOUT) :: DstInitInputData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2640,7 +2641,7 @@ SUBROUTINE IfW_FlowField_CopyInitInput( SrcInitInputData, DstInitInputData, Ctrl INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyInitInput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyInitInput' ! ErrStat = ErrID_None ErrMsg = "" @@ -2648,35 +2649,36 @@ SUBROUTINE IfW_FlowField_CopyInitInput( SrcInitInputData, DstInitInputData, Ctrl DstInitInputData%SumFileUnit = SrcInitInputData%SumFileUnit DstInitInputData%PropagationDir = SrcInitInputData%PropagationDir DstInitInputData%VFlowAngle = SrcInitInputData%VFlowAngle + DstInitInputData%VelInterpOrder = SrcInitInputData%VelInterpOrder DstInitInputData%CalcAccel = SrcInitInputData%CalcAccel - CALL IfW_FlowField_Copysteadyinitinputtype( SrcInitInputData%Steady, DstInitInputData%Steady, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copysteadyinitinputtype( SrcInitInputData%Steady, DstInitInputData%Steady, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copyuniforminitinputtype( SrcInitInputData%Uniform, DstInitInputData%Uniform, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copyuniforminitinputtype( SrcInitInputData%Uniform, DstInitInputData%Uniform, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copyturbsiminitinputtype( SrcInitInputData%TurbSim, DstInitInputData%TurbSim, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copyturbsiminitinputtype( SrcInitInputData%TurbSim, DstInitInputData%TurbSim, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copybladedinitinputtype( SrcInitInputData%Bladed, DstInitInputData%Bladed, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copybladedinitinputtype( SrcInitInputData%Bladed, DstInitInputData%Bladed, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copyhawcinitinputtype( SrcInitInputData%HAWC, DstInitInputData%HAWC, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copyhawcinitinputtype( SrcInitInputData%HAWC, DstInitInputData%HAWC, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copyuserinitinputtype( SrcInitInputData%User, DstInitInputData%User, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copyuserinitinputtype( SrcInitInputData%User, DstInitInputData%User, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copyextgridinitinputtype( SrcInitInputData%ExtGrid, DstInitInputData%ExtGrid, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copyextgridinitinputtype( SrcInitInputData%ExtGrid, DstInitInputData%ExtGrid, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copyextpointinitinputtype( SrcInitInputData%ExtPoint, DstInitInputData%ExtPoint, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copyextpointinitinputtype( SrcInitInputData%ExtPoint, DstInitInputData%ExtPoint, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_FlowField_CopyInitInput + END SUBROUTINE FlowField_IO_CopyInitInput - SUBROUTINE IfW_FlowField_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FlowField_InitInputType), INTENT(INOUT) :: InitInputData + SUBROUTINE FlowField_IO_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(FlowField_IO_InitInputType), INTENT(INOUT) :: InitInputData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -2685,7 +2687,7 @@ SUBROUTINE IfW_FlowField_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALL LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyInitInput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyInitInput' ErrStat = ErrID_None ErrMsg = "" @@ -2696,29 +2698,29 @@ SUBROUTINE IfW_FlowField_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALL DEALLOCATEpointers_local = .true. END IF - CALL IfW_FlowField_Destroysteadyinitinputtype( InitInputData%Steady, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroysteadyinitinputtype( InitInputData%Steady, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroyuniforminitinputtype( InitInputData%Uniform, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroyuniforminitinputtype( InitInputData%Uniform, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroyturbsiminitinputtype( InitInputData%TurbSim, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroyturbsiminitinputtype( InitInputData%TurbSim, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroybladedinitinputtype( InitInputData%Bladed, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroybladedinitinputtype( InitInputData%Bladed, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroyhawcinitinputtype( InitInputData%HAWC, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroyhawcinitinputtype( InitInputData%HAWC, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroyuserinitinputtype( InitInputData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroyuserinitinputtype( InitInputData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroyextgridinitinputtype( InitInputData%ExtGrid, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroyextgridinitinputtype( InitInputData%ExtGrid, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroyextpointinitinputtype( InitInputData%ExtPoint, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroyextpointinitinputtype( InitInputData%ExtPoint, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_FlowField_DestroyInitInput + END SUBROUTINE FlowField_IO_DestroyInitInput - SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FlowField_InitInputType), INTENT(IN) :: InData + TYPE(FlowField_IO_InitInputType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -2733,7 +2735,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackInitInput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackInitInput' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2753,10 +2755,11 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Int_BufSz = Int_BufSz + 1 ! SumFileUnit Re_BufSz = Re_BufSz + 1 ! PropagationDir Re_BufSz = Re_BufSz + 1 ! VFlowAngle + Int_BufSz = Int_BufSz + 1 ! VelInterpOrder Int_BufSz = Int_BufSz + 1 ! CalcAccel ! Allocate buffers for subtypes, if any (we'll get sizes from these) Int_BufSz = Int_BufSz + 3 ! Steady: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, .TRUE. ) ! Steady + CALL FlowField_IO_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, .TRUE. ) ! Steady CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2773,7 +2776,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! Uniform: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, .TRUE. ) ! Uniform + CALL FlowField_IO_Packuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, .TRUE. ) ! Uniform CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2790,7 +2793,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! TurbSim: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%TurbSim, ErrStat2, ErrMsg2, .TRUE. ) ! TurbSim + CALL FlowField_IO_Packturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%TurbSim, ErrStat2, ErrMsg2, .TRUE. ) ! TurbSim CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2807,7 +2810,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! Bladed: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, .TRUE. ) ! Bladed + CALL FlowField_IO_Packbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, .TRUE. ) ! Bladed CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2824,7 +2827,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! HAWC: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%HAWC, ErrStat2, ErrMsg2, .TRUE. ) ! HAWC + CALL FlowField_IO_Packhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%HAWC, ErrStat2, ErrMsg2, .TRUE. ) ! HAWC CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2841,7 +2844,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! User: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, .TRUE. ) ! User + CALL FlowField_IO_Packuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, .TRUE. ) ! User CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2858,7 +2861,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! ExtGrid: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, .TRUE. ) ! ExtGrid + CALL FlowField_IO_Packextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, .TRUE. ) ! ExtGrid CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2875,7 +2878,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! ExtPoint: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, .TRUE. ) ! ExtPoint + CALL FlowField_IO_Packextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, .TRUE. ) ! ExtPoint CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2926,9 +2929,11 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VFlowAngle Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VelInterpOrder + Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%CalcAccel, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 - CALL IfW_FlowField_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, OnlySize ) ! Steady + CALL FlowField_IO_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, OnlySize ) ! Steady CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2956,7 +2961,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, OnlySize ) ! Uniform + CALL FlowField_IO_Packuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, OnlySize ) ! Uniform CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2984,7 +2989,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%TurbSim, ErrStat2, ErrMsg2, OnlySize ) ! TurbSim + CALL FlowField_IO_Packturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%TurbSim, ErrStat2, ErrMsg2, OnlySize ) ! TurbSim CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3012,7 +3017,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, OnlySize ) ! Bladed + CALL FlowField_IO_Packbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, OnlySize ) ! Bladed CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3040,7 +3045,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%HAWC, ErrStat2, ErrMsg2, OnlySize ) ! HAWC + CALL FlowField_IO_Packhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%HAWC, ErrStat2, ErrMsg2, OnlySize ) ! HAWC CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3068,7 +3073,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, OnlySize ) ! User + CALL FlowField_IO_Packuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, OnlySize ) ! User CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3096,7 +3101,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, OnlySize ) ! ExtGrid + CALL FlowField_IO_Packextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, OnlySize ) ! ExtGrid CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3124,7 +3129,7 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, OnlySize ) ! ExtPoint + CALL FlowField_IO_Packextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, OnlySize ) ! ExtPoint CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3152,13 +3157,13 @@ SUBROUTINE IfW_FlowField_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - END SUBROUTINE IfW_FlowField_PackInitInput + END SUBROUTINE FlowField_IO_PackInitInput - SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FlowField_InitInputType), INTENT(INOUT) :: OutData + TYPE(FlowField_IO_InitInputType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -3169,7 +3174,7 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackInitInput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackInitInput' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -3188,6 +3193,8 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Re_Xferred = Re_Xferred + 1 OutData%VFlowAngle = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%VelInterpOrder = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 OutData%CalcAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%CalcAccel) Int_Xferred = Int_Xferred + 1 Buf_size=IntKiBuf( Int_Xferred ) @@ -3223,7 +3230,7 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpacksteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Steady, ErrStat2, ErrMsg2 ) ! Steady + CALL FlowField_IO_Unpacksteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Steady, ErrStat2, ErrMsg2 ) ! Steady CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3263,7 +3270,7 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Uniform, ErrStat2, ErrMsg2 ) ! Uniform + CALL FlowField_IO_Unpackuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Uniform, ErrStat2, ErrMsg2 ) ! Uniform CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3303,7 +3310,7 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%TurbSim, ErrStat2, ErrMsg2 ) ! TurbSim + CALL FlowField_IO_Unpackturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%TurbSim, ErrStat2, ErrMsg2 ) ! TurbSim CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3343,7 +3350,7 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Bladed, ErrStat2, ErrMsg2 ) ! Bladed + CALL FlowField_IO_Unpackbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Bladed, ErrStat2, ErrMsg2 ) ! Bladed CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3383,7 +3390,7 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%HAWC, ErrStat2, ErrMsg2 ) ! HAWC + CALL FlowField_IO_Unpackhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%HAWC, ErrStat2, ErrMsg2 ) ! HAWC CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3423,7 +3430,7 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%User, ErrStat2, ErrMsg2 ) ! User + CALL FlowField_IO_Unpackuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%User, ErrStat2, ErrMsg2 ) ! User CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3463,7 +3470,7 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtGrid, ErrStat2, ErrMsg2 ) ! ExtGrid + CALL FlowField_IO_Unpackextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtGrid, ErrStat2, ErrMsg2 ) ! ExtGrid CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3503,16 +3510,16 @@ SUBROUTINE IfW_FlowField_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtPoint, ErrStat2, ErrMsg2 ) ! ExtPoint + CALL FlowField_IO_Unpackextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtPoint, ErrStat2, ErrMsg2 ) ! ExtPoint CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_FlowField_UnPackInitInput + END SUBROUTINE FlowField_IO_UnPackInitInput - SUBROUTINE IfW_FlowField_CopyWindFileDat( SrcWindFileDatData, DstWindFileDatData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_CopyWindFileDat( SrcWindFileDatData, DstWindFileDatData, CtrlCode, ErrStat, ErrMsg ) TYPE(WindFileDat), INTENT(IN) :: SrcWindFileDatData TYPE(WindFileDat), INTENT(INOUT) :: DstWindFileDatData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -3523,7 +3530,7 @@ SUBROUTINE IfW_FlowField_CopyWindFileDat( SrcWindFileDatData, DstWindFileDatData INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyWindFileDat' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyWindFileDat' ! ErrStat = ErrID_None ErrMsg = "" @@ -3545,9 +3552,9 @@ SUBROUTINE IfW_FlowField_CopyWindFileDat( SrcWindFileDatData, DstWindFileDatData DstWindFileDatData%TI = SrcWindFileDatData%TI DstWindFileDatData%TI_listed = SrcWindFileDatData%TI_listed DstWindFileDatData%MWS = SrcWindFileDatData%MWS - END SUBROUTINE IfW_FlowField_CopyWindFileDat + END SUBROUTINE FlowField_IO_CopyWindFileDat - SUBROUTINE IfW_FlowField_DestroyWindFileDat( WindFileDatData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE FlowField_IO_DestroyWindFileDat( WindFileDatData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(WindFileDat), INTENT(INOUT) :: WindFileDatData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -3557,7 +3564,7 @@ SUBROUTINE IfW_FlowField_DestroyWindFileDat( WindFileDatData, ErrStat, ErrMsg, D LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyWindFileDat' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyWindFileDat' ErrStat = ErrID_None ErrMsg = "" @@ -3568,9 +3575,9 @@ SUBROUTINE IfW_FlowField_DestroyWindFileDat( WindFileDatData, ErrStat, ErrMsg, D DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE IfW_FlowField_DestroyWindFileDat + END SUBROUTINE FlowField_IO_DestroyWindFileDat - SUBROUTINE IfW_FlowField_PackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -3589,7 +3596,7 @@ SUBROUTINE IfW_FlowField_PackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackWindFileDat' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackWindFileDat' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -3696,9 +3703,9 @@ SUBROUTINE IfW_FlowField_PackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er Int_Xferred = Int_Xferred + 1 ReKiBuf(Re_Xferred) = InData%MWS Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackWindFileDat + END SUBROUTINE FlowField_IO_PackWindFileDat - SUBROUTINE IfW_FlowField_UnPackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -3714,7 +3721,7 @@ SUBROUTINE IfW_FlowField_UnPackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackWindFileDat' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackWindFileDat' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -3779,11 +3786,11 @@ SUBROUTINE IfW_FlowField_UnPackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Int_Xferred = Int_Xferred + 1 OutData%MWS = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackWindFileDat + END SUBROUTINE FlowField_IO_UnPackWindFileDat - SUBROUTINE IfW_FlowField_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FlowField_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(IfW_FlowField_InitOutputType), INTENT(INOUT) :: DstInitOutputData + SUBROUTINE FlowField_IO_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) + TYPE(FlowField_IO_InitOutputType), INTENT(IN) :: SrcInitOutputData + TYPE(FlowField_IO_InitOutputType), INTENT(INOUT) :: DstInitOutputData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -3791,23 +3798,23 @@ SUBROUTINE IfW_FlowField_CopyInitOutput( SrcInitOutputData, DstInitOutputData, C INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyInitOutput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyInitOutput' ! ErrStat = ErrID_None ErrMsg = "" CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copywindfiledat( SrcInitOutputData%FileDat, DstInitOutputData%FileDat, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copywindfiledat( SrcInitOutputData%FileDat, DstInitOutputData%FileDat, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copybladedinitoutputtype( SrcInitOutputData%Bladed, DstInitOutputData%Bladed, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copybladedinitoutputtype( SrcInitOutputData%Bladed, DstInitOutputData%Bladed, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_FlowField_CopyInitOutput + END SUBROUTINE FlowField_IO_CopyInitOutput - SUBROUTINE IfW_FlowField_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FlowField_InitOutputType), INTENT(INOUT) :: InitOutputData + SUBROUTINE FlowField_IO_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(FlowField_IO_InitOutputType), INTENT(INOUT) :: InitOutputData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -3816,7 +3823,7 @@ SUBROUTINE IfW_FlowField_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEA LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyInitOutput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyInitOutput' ErrStat = ErrID_None ErrMsg = "" @@ -3829,17 +3836,17 @@ SUBROUTINE IfW_FlowField_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEA CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroywindfiledat( InitOutputData%FileDat, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroywindfiledat( InitOutputData%FileDat, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroybladedinitoutputtype( InitOutputData%Bladed, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroybladedinitoutputtype( InitOutputData%Bladed, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_FlowField_DestroyInitOutput + END SUBROUTINE FlowField_IO_DestroyInitOutput - SUBROUTINE IfW_FlowField_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FlowField_InitOutputType), INTENT(IN) :: InData + TYPE(FlowField_IO_InitOutputType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -3854,7 +3861,7 @@ SUBROUTINE IfW_FlowField_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Err LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackInitOutput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackInitOutput' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -3889,7 +3896,7 @@ SUBROUTINE IfW_FlowField_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Err DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! FileDat: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%FileDat, ErrStat2, ErrMsg2, .TRUE. ) ! FileDat + CALL FlowField_IO_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%FileDat, ErrStat2, ErrMsg2, .TRUE. ) ! FileDat CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3906,7 +3913,7 @@ SUBROUTINE IfW_FlowField_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Err DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! Bladed: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, .TRUE. ) ! Bladed + CALL FlowField_IO_Packbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, .TRUE. ) ! Bladed CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3977,7 +3984,7 @@ SUBROUTINE IfW_FlowField_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Err ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%FileDat, ErrStat2, ErrMsg2, OnlySize ) ! FileDat + CALL FlowField_IO_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%FileDat, ErrStat2, ErrMsg2, OnlySize ) ! FileDat CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4005,7 +4012,7 @@ SUBROUTINE IfW_FlowField_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Err ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, OnlySize ) ! Bladed + CALL FlowField_IO_Packbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, OnlySize ) ! Bladed CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4033,13 +4040,13 @@ SUBROUTINE IfW_FlowField_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Err ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - END SUBROUTINE IfW_FlowField_PackInitOutput + END SUBROUTINE FlowField_IO_PackInitOutput - SUBROUTINE IfW_FlowField_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FlowField_InitOutputType), INTENT(INOUT) :: OutData + TYPE(FlowField_IO_InitOutputType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -4050,7 +4057,7 @@ SUBROUTINE IfW_FlowField_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackInitOutput' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackInitOutput' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -4134,7 +4141,7 @@ SUBROUTINE IfW_FlowField_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackwindfiledat( Re_Buf, Db_Buf, Int_Buf, OutData%FileDat, ErrStat2, ErrMsg2 ) ! FileDat + CALL FlowField_IO_Unpackwindfiledat( Re_Buf, Db_Buf, Int_Buf, OutData%FileDat, ErrStat2, ErrMsg2 ) ! FileDat CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4174,14 +4181,14 @@ SUBROUTINE IfW_FlowField_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Bladed, ErrStat2, ErrMsg2 ) ! Bladed + CALL FlowField_IO_Unpackbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Bladed, ErrStat2, ErrMsg2 ) ! Bladed CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_FlowField_UnPackInitOutput + END SUBROUTINE FlowField_IO_UnPackInitOutput -END MODULE IfW_FlowField_Types +END MODULE FlowField_IO_Types !ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/FlowField_Types.f90 b/modules/inflowwind/src/FlowField_Types.f90 index 64c9895ff7..fd6cb9975b 100644 --- a/modules/inflowwind/src/FlowField_Types.f90 +++ b/modules/inflowwind/src/FlowField_Types.f90 @@ -144,6 +144,7 @@ MODULE FlowField_Types REAL(ReKi) , DIMENSION(1:3) :: RefPosition !< Reference position (point where box is rotated) [meters] REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [radians] + INTEGER(IntKi) :: VelInterpOrder = 0 !< Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] [-] LOGICAL :: RotateWindBox = .false. !< flag indicating if the wind will be rotated [-] REAL(ReKi) , DIMENSION(1:3,1:3) :: RotToWind !< Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X') [-] REAL(ReKi) , DIMENSION(1:3,1:3) :: RotFromWind !< Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind) [-] @@ -2722,6 +2723,7 @@ SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeDa DstFlowFieldTypeData%RefPosition = SrcFlowFieldTypeData%RefPosition DstFlowFieldTypeData%PropagationDir = SrcFlowFieldTypeData%PropagationDir DstFlowFieldTypeData%VFlowAngle = SrcFlowFieldTypeData%VFlowAngle + DstFlowFieldTypeData%VelInterpOrder = SrcFlowFieldTypeData%VelInterpOrder DstFlowFieldTypeData%RotateWindBox = SrcFlowFieldTypeData%RotateWindBox DstFlowFieldTypeData%RotToWind = SrcFlowFieldTypeData%RotToWind DstFlowFieldTypeData%RotFromWind = SrcFlowFieldTypeData%RotFromWind @@ -2814,6 +2816,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Re_BufSz = Re_BufSz + SIZE(InData%RefPosition) ! RefPosition Re_BufSz = Re_BufSz + 1 ! PropagationDir Re_BufSz = Re_BufSz + 1 ! VFlowAngle + Int_BufSz = Int_BufSz + 1 ! VelInterpOrder Int_BufSz = Int_BufSz + 1 ! RotateWindBox Re_BufSz = Re_BufSz + SIZE(InData%RotToWind) ! RotToWind Re_BufSz = Re_BufSz + SIZE(InData%RotFromWind) ! RotFromWind @@ -2940,6 +2943,8 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VFlowAngle Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VelInterpOrder + Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%RotateWindBox, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 DO i2 = LBOUND(InData%RotToWind,2), UBOUND(InData%RotToWind,2) @@ -3136,6 +3141,8 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Re_Xferred = Re_Xferred + 1 OutData%VFlowAngle = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%VelInterpOrder = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 OutData%RotateWindBox = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotateWindBox) Int_Xferred = Int_Xferred + 1 i1_l = LBOUND(OutData%RotToWind,1) diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 1c902ceec9..15f4fd1e40 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -44,8 +44,8 @@ MODULE InflowWind USE InflowWind_Types USE NWTC_Library USE InflowWind_Subs - USE IfW_FlowField_Types - USE IfW_FlowField + USE FlowField_IO_Types + USE FlowField_IO USE Lidar ! module for obtaining sensor data @@ -133,8 +133,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, TYPE(InflowWind_InputFile) :: InputFileData !< Data from input file - TYPE(IfW_FlowField_InitInputType) :: FlowField_InitData !< initialization info - TYPE(IfW_FlowField_InitOutputType) :: Interp_InitOutData !< initialization output info + TYPE(FlowField_IO_InitInputType) :: FlowField_InitData !< initialization info + TYPE(FlowField_IO_InitOutputType) :: Interp_InitOutData !< initialization output info TYPE(IfW_UniformWind_InitInputType) :: Uniform_InitData !< initialization info TYPE(IfW_UniformWind_InitOutputType) :: Uniform_InitOutData !< initialization output info @@ -306,6 +306,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, FlowField_InitData%SumFileUnit = SumFileUnit FlowField_InitData%PropagationDir = InputFileData%PropagationDir FlowField_InitData%VFlowAngle = InputFileData%VFlowAngle + FlowField_InitData%VelInterpOrder = InputFileData%VelInterpOrder FlowField_InitData%CalcAccel = InitInp%CalcAccel select case(FlowField_InitData%WindType) @@ -373,7 +374,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, return end select - call IfW_FlowField_Init(FlowField_InitData, p%FlowField, Interp_InitOutData, TmpErrStat, TmpErrMsg) + call FlowField_IO_Init(FlowField_InitData, p%FlowField, Interp_InitOutData, TmpErrStat, TmpErrMsg) SELECT CASE ( InputFileData%WindType ) diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 8d3522c317..7035d856aa 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -65,6 +65,7 @@ typedef InflowWind/InflowWind InflowWind_InputFile LOGICAL EchoFlag typedef ^ ^ IntKi WindType - 0 - "Type of windfile" - typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation (meteorological direction)" (degrees) typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" degrees +typedef ^ ^ IntKi VelInterpOrder - 0 - "Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7]" - typedef ^ ^ IntKi NWindVel - - - "Number of points to output the wind velocity (0 to 9)" typedef ^ ^ ReKi WindVxiList : - - "List of X coordinates for wind velocity measurements" meters typedef ^ ^ ReKi WindVyiList : - - "List of Y coordinates for wind velocity measurements" meters diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index 8b78f06800..f0cdee3c09 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -238,6 +238,10 @@ SUBROUTINE InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, In ! VFlowAngle: Upflow angle (deg) CALL ParseVarWDefault( InFileInfo, CurLine, "VFlowAng", InputFileData%VFlowAngle, 0.0_ReKi, TmpErrStat, TmpErrMsg, UnEc ) + if (Failed()) return + + ! VelInterpOrder: Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] + CALL ParseVar( InFileInfo, CurLine, "VelInterpOrder", InputFileData%VelInterpOrder, TmpErrStat, TmpErrMsg, UnEc ) if (Failed()) return ! NWindVel: Number of points to output the wind velocity (0 to 9) diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index dc91c6f9d8..1baa33147e 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -80,6 +80,7 @@ MODULE InflowWind_Types INTEGER(IntKi) :: WindType = 0 !< Type of windfile [-] REAL(ReKi) :: PropagationDir !< Direction of wind propagation (meteorological direction) [(degrees)] REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [degrees] + INTEGER(IntKi) :: VelInterpOrder = 0 !< Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] [-] INTEGER(IntKi) :: NWindVel !< Number of points to output the wind velocity (0 to 9) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WindVxiList !< List of X coordinates for wind velocity measurements [meters] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WindVyiList !< List of Y coordinates for wind velocity measurements [meters] @@ -523,6 +524,7 @@ SUBROUTINE InflowWind_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCod DstInputFileData%WindType = SrcInputFileData%WindType DstInputFileData%PropagationDir = SrcInputFileData%PropagationDir DstInputFileData%VFlowAngle = SrcInputFileData%VFlowAngle + DstInputFileData%VelInterpOrder = SrcInputFileData%VelInterpOrder DstInputFileData%NWindVel = SrcInputFileData%NWindVel IF (ALLOCATED(SrcInputFileData%WindVxiList)) THEN i1_l = LBOUND(SrcInputFileData%WindVxiList,1) @@ -680,6 +682,7 @@ SUBROUTINE InflowWind_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Int_BufSz = Int_BufSz + 1 ! WindType Re_BufSz = Re_BufSz + 1 ! PropagationDir Re_BufSz = Re_BufSz + 1 ! VFlowAngle + Int_BufSz = Int_BufSz + 1 ! VelInterpOrder Int_BufSz = Int_BufSz + 1 ! NWindVel Int_BufSz = Int_BufSz + 1 ! WindVxiList allocated yes/no IF ( ALLOCATED(InData%WindVxiList) ) THEN @@ -781,6 +784,8 @@ SUBROUTINE InflowWind_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VFlowAngle Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%VelInterpOrder + Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%NWindVel Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%WindVxiList) ) THEN @@ -982,6 +987,8 @@ SUBROUTINE InflowWind_UnPackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS Re_Xferred = Re_Xferred + 1 OutData%VFlowAngle = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%VelInterpOrder = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 OutData%NWindVel = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindVxiList not allocated From 26e690cad40d99244933acdff050662dbdc4648e Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Mon, 20 Feb 2023 18:16:27 +0000 Subject: [PATCH 11/51] Reorg FlowField module, finish VelInterpCubic flag --- cmake/OpenfastCmakeUtils.cmake | 2 +- modules/inflowwind/src/FlowField.f90 | 890 +++++++++--------- modules/inflowwind/src/FlowField.txt | 23 +- modules/inflowwind/src/FlowField_IO.f90 | 79 +- modules/inflowwind/src/FlowField_IO.txt | 10 +- modules/inflowwind/src/FlowField_IO_Types.f90 | 140 +-- modules/inflowwind/src/FlowField_Types.f90 | 447 ++++----- modules/inflowwind/src/InflowWind.f90 | 9 +- modules/inflowwind/src/InflowWind.txt | 2 +- modules/inflowwind/src/InflowWind_Subs.f90 | 4 +- modules/inflowwind/src/InflowWind_Types.f90 | 10 +- 11 files changed, 806 insertions(+), 810 deletions(-) diff --git a/cmake/OpenfastCmakeUtils.cmake b/cmake/OpenfastCmakeUtils.cmake index 4837582412..44ec6c2acc 100644 --- a/cmake/OpenfastCmakeUtils.cmake +++ b/cmake/OpenfastCmakeUtils.cmake @@ -48,7 +48,7 @@ function(generate_f90_types regfile outfile) DEPENDS openfast_registry ${input} COMMAND ${CMAKE_BINARY_DIR}/modules/openfast-registry/openfast_registry ${input} "-O" "${outdir}" ${OPENFAST_REGISTRY_INCLUDES} ${ARGN} ) - set_source_files_properties(${output} PROPERTIES GENERATED TRUE) + set_source_files_properties(${outfile} PROPERTIES GENERATED TRUE) endfunction(generate_f90_types) # diff --git a/modules/inflowwind/src/FlowField.f90 b/modules/inflowwind/src/FlowField.f90 index 01638a2d5f..bbf8079ecf 100644 --- a/modules/inflowwind/src/FlowField.f90 +++ b/modules/inflowwind/src/FlowField.f90 @@ -25,7 +25,7 @@ module FlowField implicit none public FlowField_GetVelAcc -public UniformField_CalcAccel, GridField_CalcAccel +public UniformField_CalcAccel, Grid3DField_CalcAccel integer(IntKi), parameter :: WindProfileType_None = -1 !< don't add wind profile; already included in input integer(IntKi), parameter :: WindProfileType_Constant = 0 !< constant wind @@ -39,22 +39,29 @@ module FlowField !> FlowField_GetVelAcc gets the velocities (and accelerations) at the given point positions. !! Accelerations are only calculated if the AccelUVW array is allocated. subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, AccelUVW, ErrStat, ErrMsg) - type(FlowFieldType), intent(in) :: FF !< FlowField data structure - integer(IntKi), intent(in) :: IStart !< Start index for returning velocities for external field - real(DbKi), intent(in) :: Time !< Time to evaluate velocities/accelerations - real(ReKi), dimension(:, :), intent(in) :: PositionXYZ !< Array of positions to evaluate velocites/accelerations - real(ReKi), dimension(:, :), intent(inout) :: VelocityUVW !< Array of velocity outputs - real(ReKi), dimension(:, :), allocatable, intent(inout) :: AccelUVW !< Array of acceleration outputs - integer(IntKi), intent(out) :: ErrStat !< Error status - character(*), intent(out) :: ErrMsg !< Error message - - character(*), parameter :: RoutineName = "FlowField_GetVelAcc" - integer(IntKi) :: i - integer(IntKi) :: NumPoints - real(ReKi), dimension(:, :), allocatable :: Position - type(UniformField_Interp) :: UFop - integer(IntKi) :: TmpErrStat - character(ErrMsgLen) :: TmpErrMsg + + type(FlowFieldType), intent(in) :: FF !< FlowField data structure + integer(IntKi), intent(in) :: IStart !< Start index for returning velocities for external field + real(DbKi), intent(in) :: Time !< Time to evaluate velocities/accelerations + real(ReKi), intent(in) :: PositionXYZ(:, :) !< Array of positions to evaluate velocites/accelerations + real(ReKi), intent(inout) :: VelocityUVW(:, :) !< Array of velocity outputs + real(ReKi), allocatable, intent(inout) :: AccelUVW(:, :) !< Array of acceleration outputs + integer(IntKi), intent(out) :: ErrStat !< Error status + character(*), intent(out) :: ErrMsg !< Error message + + character(*), parameter :: RoutineName = "FlowField_GetVelAcc" + integer(IntKi) :: i + integer(IntKi) :: NumPoints + logical :: CalcAccel + real(ReKi), allocatable :: Position(:, :) + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + ! Uniform Field + type(UniformField_Interp) :: UFopVel, UFopAcc + ! Grid3D Field + real(ReKi) :: Xi(3) + real(ReKi) :: VelCell(8, 3), AccCell(8, 3) + logical :: Is3D ErrStat = ErrID_None ErrMsg = "" @@ -62,6 +69,14 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel ! Get number of points to evaluate NumPoints = size(PositionXYZ, dim=2) + ! Determine if acceleration should be calculated and returned + CalcAccel = allocated(AccelUVW) + if (CalcAccel .and. .not. FF%AccFieldValid) then + call SetErrStat(ErrID_Fatal, "Accel output requested, but accel field is not valid", & + ErrStat, ErrMsg, RoutineName) + return + end if + ! Allocate position array call AllocAry(Position, 3, NumPoints, "Rotated position data", TmpErrStat, TmpErrMsg) if (TmpErrStat >= AbortErrLev) then @@ -70,16 +85,14 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel end if ! Copy positions or transform based on wind box rotation - if (.not. FF%RotateWindBox) then - Position = PositionXYZ - else + if (FF%RotateWindBox) then do i = 1, NumPoints Position(:, i) = GetPrimePosition(PositionXYZ(:, i)) end do + else + Position = PositionXYZ end if - !TODO: Check that position, velocity, and acceleration are all the same shape - !---------------------------------------------------------------------------- ! Wind speed coordinate transforms from Wind file coordinates to global !---------------------------------------------------------------------------- @@ -103,79 +116,132 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel ! Uniform Flow Field !------------------------------------------------------------------------- - ! If accel allocated - if (allocated(AccelUVW)) then - UFop = UniformField_GetSmoothOP(FF%Uniform, Time) + ! If cubic velocity interp requested, calculate operating point using + ! cubic interpolation. Otherwise, use linear interpolation + if (FF%VelInterpCubic) then + UFopVel = UniformField_IterpCubic(FF%Uniform, Time) else - UFop = UniformField_GetOP(FF%Uniform, Time) + UFopVel = UniformField_InterpLinear(FF%Uniform, Time) end if - ! Get velocity or velocity and acceleration - if (.not. allocated(AccelUVW)) then + ! If acceleration output is requested + if (CalcAccel) then + + ! If cubic interpolation was used for the velocity, use same for accel + ! otherwise, calculate operating point via cubic interpolation + if (FF%VelInterpCubic) then + UFopAcc = UFopVel + else + UFopAcc = UniformField_IterpCubic(FF%Uniform, Time) + end if + + ! Loop throuh points and calcualate velocity and acceleration do i = 1, NumPoints if (Position(3, i) > 0.0_ReKi) then - VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, Position(:, i)) + VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFopVel, Position(:, i)) + AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFopAcc, Position(:, i)) else VelocityUVW(:, i) = 0.0_ReKi + AccelUVW(:, i) = 0.0_ReKi end if end do - else + + else ! Otherwise, only velocity requested + + ! Loop throuh points and calcualate velocity do i = 1, NumPoints if (Position(3, i) > 0.0_ReKi) then - VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFop, Position(:, i)) - AccelUVW(:, i) = UniformField_GetAcc(FF%Uniform, UFop, Position(:, i)) + VelocityUVW(:, i) = UniformField_GetVel(FF%Uniform, UFopVel, Position(:, i)) else VelocityUVW(:, i) = 0.0_ReKi - AccelUVW(:, i) = 0.0_ReKi end if end do end if - case (Grid_FieldType) + case (Grid3D_FieldType) !------------------------------------------------------------------------- - ! Grid Flow Field + ! Grid3D Flow Field !------------------------------------------------------------------------- - ! Loop through points - do i = 1, NumPoints + if (CalcAccel) then - ! If height is less than zero, set velocity to zero - if (Position(3, i) <= 0.0_ReKi) then - VelocityUVW(:, i) = 0.0_ReKi - if (allocated(AccelUVW)) AccelUVW(:, i) = 0.0_ReKi - cycle - end if + ! Loop through points + do i = 1, NumPoints - ! Get velocity or velocity and acceleration - if (.not. allocated(AccelUVW)) then - call GridField_GetVel(FF%Grid, Time, Position(:, i), VelocityUVW(:, i), TmpErrStat, TmpErrMsg) - else - call GridField_GetVelAcc(FF%Grid, Time, Position(:, i), VelocityUVW(:, i), AccelUVW(:, i), TmpErrStat, TmpErrMsg) - end if - if (TmpErrStat >= AbortErrLev) then - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - return - end if + ! If height < zero, set velocity/acceleration to zero, continue + if (Position(3, i) <= 0.0_ReKi) then + VelocityUVW(:, i) = 0.0_ReKi + AccelUVW(:, i) = 0.0_ReKi + cycle + end if - end do + ! Calculate grid cells for interpolation + call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), CalcAccel, & + VelCell, AccCell, Xi, Is3D, TmpErrStat, TmpErrMsg) + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + + if (FF%VelInterpCubic) then + ! Cubic velocity and cubic acceleration + call Grid3DField_GetVelAccCubic(FF%Grid3D%DTime, VelCell, AccCell, Xi, Is3D, & + Velocity=VelocityUVW(:, i), Accel=AccelUVW(:, i)) + else + ! Linear velocity and cubic acceleration + VelocityUVW(:, i) = Grid3DField_GetVelLinear(VelCell, Xi, Is3D) + call Grid3DField_GetVelAccCubic(FF%Grid3D%DTime, VelCell, AccCell, Xi, Is3D, & + Accel=AccelUVW(:, i)) + end if + + end do + else + + ! Loop through points + do i = 1, NumPoints + + ! If height < zero, set velocity to zero, continue + if (Position(3, i) <= 0.0_ReKi) then + VelocityUVW(:, i) = 0.0_ReKi + cycle + end if + + ! Calculate grid cells for interpolation + call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), CalcAccel, & + VelCell, AccCell, Xi, Is3D, TmpErrStat, TmpErrMsg) + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + + ! Cubic or linear velocity interpolation + if (FF%VelInterpCubic) then + call Grid3DField_GetVelAccCubic(FF%Grid3D%DTime, VelCell, AccCell, Xi, Is3D, & + Velocity=VelocityUVW(:, i)) + else + VelocityUVW(:, i) = Grid3DField_GetVelLinear(VelCell, Xi, Is3D) + end if + + end do + end if ! Add mean wind speed after interpolation if flag is set - if (FF%Grid%AddMeanAfterInterp) then + if (FF%Grid3D%AddMeanAfterInterp) then do i = 1, NumPoints - VelocityUVW(1, i) = VelocityUVW(1, i) + GetMeanVelocity(FF%Grid, Position(3, i)) + VelocityUVW(1, i) = VelocityUVW(1, i) + GetMeanVelocity(FF%Grid3D, Position(3, i)) end do end if - case (ExtGrid_FieldType) + case (Grid4D_FieldType) !------------------------------------------------------------------------- - ! External Grid Flow Field + ! Grid4D Flow Field !------------------------------------------------------------------------- - ! If external field is not allocated, return error - if (.not. allocated(FF%ExtGrid%Vel)) then - call SetErrStat(ErrID_Fatal, "External Grid Field not allocated", ErrStat, ErrMsg, RoutineName) + ! If field is not allocated, return error + if (.not. allocated(FF%Grid4D%Vel)) then + call SetErrStat(ErrID_Fatal, "Grid4D Field not allocated", ErrStat, ErrMsg, RoutineName) return end if @@ -188,27 +254,27 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel cycle end if - call ExtGridField_GetVel(FF%ExtGrid, Time, Position(:, i), VelocityUVW(:, i), TmpErrStat, TmpErrMsg) + call Grid4DField_GetVel(FF%Grid4D, Time, Position(:, i), VelocityUVW(:, i), TmpErrStat, TmpErrMsg) if (TmpErrStat >= AbortErrLev) then call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) return end if end do - case (ExtPoint_FieldType) + case (Point_FieldType) !------------------------------------------------------------------------- - ! External Grid Flow Field + ! Point Flow Field !------------------------------------------------------------------------- - ! If external field is not allocated, return error - if (.not. allocated(FF%ExtPoint%Vel)) then - call SetErrStat(ErrID_Fatal, "External Point Field not allocated", ErrStat, ErrMsg, RoutineName) + ! If points field is not allocated, return error + if (.not. allocated(FF%Points%Vel)) then + call SetErrStat(ErrID_Fatal, "Points Point Field not allocated", ErrStat, ErrMsg, RoutineName) return end if ! Set velocities directly from velocity array - VelocityUVW = FF%ExtPoint%Vel(:, IStart:IStart + NumPoints - 1) + VelocityUVW = FF%Points%Vel(:, IStart:IStart + NumPoints - 1) case (User_FieldType) @@ -229,7 +295,7 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel !---------------------------------------------------------------------------- if (FF%RotateWindBox) then - if (.not. allocated(AccelUVW)) then + if (.not. CalcAccel) then do i = 1, NumPoints VelocityUVW(:, i) = matmul(FF%RotFromWind, VelocityUVW(:, i)) end do @@ -250,7 +316,7 @@ pure function GetPrimePosition(Pos) result(PrimePos) end function function GetMeanVelocity(GF, PosZ) result(U) - type(GridFieldType), intent(in) :: GF + type(Grid3DFieldType), intent(in) :: GF real(ReKi), intent(in) :: PosZ real(ReKi) :: U select case (GF%WindProfileType) @@ -340,7 +406,7 @@ function UniformField_GetAcc(UF, op, Position) result(Accel) end function -pure function UniformField_GetOP(UF, Time) result(op) +pure function UniformField_InterpLinear(UF, Time) result(op) type(UniformFieldType), intent(in) :: UF real(DbKi), intent(in) :: Time @@ -405,7 +471,7 @@ pure function UniformField_GetOP(UF, Time) result(op) end function -pure function UniformField_GetSmoothOP(UF, Time) result(op) +pure function UniformField_IterpCubic(UF, Time) result(op) type(UniformFieldType), intent(in) :: UF real(DbKi), intent(in) :: Time @@ -500,7 +566,7 @@ subroutine UniformField_CalcAccel(UF, ErrStat, ErrMsg) integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = "UniformField_CalcAccel" + character(*), parameter :: RoutineName = "Uniform_CalcAccel" integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg real(ReKi), allocatable :: b(:), u(:), dy2(:) @@ -635,27 +701,26 @@ subroutine CalcCubicSplineDeriv(x, y, dy) end subroutine -subroutine GridField_GetVel(GF, Time, Position, Velocity, ErrStat, ErrMsg) - type(GridFieldType), intent(in) :: GF !< Grid-Field data - real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value - real(DbKi), intent(in) :: Time !< Weights [-1,1] - real(ReKi), intent(out) :: Velocity(3) !< The U, V, W velocities - integer(IntKi), intent(out) :: ErrStat - character(*), intent(out) :: ErrMsg - - character(*), parameter :: RoutineName = "GridField_GetVel" - real(ReKi) :: DY, DZ, DT ! Weights [-1,1] - real(ReKi), dimension(8, 3) :: P ! Interp points - real(ReKi), dimension(8) :: N ! Shape function values - - integer(IntKi) :: IT_LO, IT_HI - integer(IntKi) :: IY_LO, IY_HI - integer(IntKi) :: IZ_LO, IZ_HI - integer(IntKi) :: ic +subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, VelCell, AccCell, Xi, Is3D, ErrStat, ErrMsg) - logical :: OnGrid - real(ReKi) :: TimeShifted - integer(IntKi) :: boundStat + type(Grid3DFieldType), intent(in) :: G3D !< 3D Grid-Field data + real(DbKi), intent(in) :: Time !< time (s) + real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value + logical, intent(in) :: CalcAccel !< flag to populat AccCell + real(ReKi), intent(out) :: VelCell(8, 3) !< + real(ReKi), intent(out) :: AccCell(8, 3) !< + real(ReKi), intent(out) :: Xi(3) !< isoparametric coord of position in cell (y,z,t) [-1, +1] + logical, intent(out) :: Is3D !< + integer(IntKi), intent(out) :: ErrStat !< error status + character(*), intent(out) :: ErrMsg !< error message + + character(*), parameter :: RoutineName = "Grid3DField_GetSmoothInterp" + integer(IntKi) :: IY_Lo, IY_Hi + integer(IntKi) :: IZ_Lo, IZ_Hi + integer(IntKi) :: IT_Lo, IT_Hi + logical :: OnGrid + real(ReKi) :: TimeShifted + integer(IntKi) :: boundStat ErrStat = ErrID_None ErrMsg = "" @@ -665,7 +730,7 @@ subroutine GridField_GetVel(GF, Time, Position, Velocity, ErrStat, ErrMsg) !---------------------------------------------------------------------------- ! Get grid time bounds - boundStat = GridField_GetBoundsT(GF, Time, Position(1), DT, IT_LO, IT_HI, TimeShifted) + boundStat = Grid3DField_GetBoundsT(G3D, Time, Position(1), Xi(3), IT_Lo, IT_Hi, TimeShifted) if (boundStat > 0) then ErrMsg = ' Error: GF wind array was exhausted at '//TRIM(Num2LStr(TIME))// & ' seconds (trying to access data at '//TRIM(Num2LStr(TimeShifted))//' seconds).' @@ -674,7 +739,7 @@ subroutine GridField_GetVel(GF, Time, Position, Velocity, ErrStat, ErrMsg) end if ! Get grid Z bounds - boundStat = GridField_GetBoundsZ(GF, Position(3), DZ, IZ_LO, IZ_HI, OnGrid) + boundStat = Grid3DField_GetBoundsZ(G3D, Position(3), Xi(2), IZ_Lo, IZ_Hi, OnGrid) if (boundStat < 0) then ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction '// & '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' @@ -688,325 +753,219 @@ subroutine GridField_GetVel(GF, Time, Position, Velocity, ErrStat, ErrMsg) end if !---------------------------------------------------------------------------- - ! Interpolate + ! Extract cells from grids !---------------------------------------------------------------------------- - if (OnGrid .or. GF%InterpTower) then + if (OnGrid .or. G3D%InterpTower) then ! Get grid Y bounds - boundStat = GridField_GetBoundsY(GF, Position(2), DY, IY_LO, IY_HI) + boundStat = Grid3DField_GetBoundsY(G3D, Position(2), Xi(1), IY_Lo, IY_Hi) if (boundStat /= 0) then ErrMsg = ' GF wind array boundaries violated: Grid too small in Y direction. Y='// & - TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*GF%YHWid))// & - ', '//TRIM(Num2LStr(GF%YHWid))//']' + TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*G3D%YHWid))// & + ', '//TRIM(Num2LStr(G3D%YHWid))//']' ErrStat = ErrID_Fatal return end if + Is3D = .true. + if (OnGrid) then - ! Get points from the grid - P(1, :) = GF%Vel(:, IY_LO, IZ_LO, IT_LO) - P(2, :) = GF%Vel(:, IY_HI, IZ_LO, IT_LO) - P(3, :) = GF%Vel(:, IY_LO, IZ_HI, IT_LO) - P(4, :) = GF%Vel(:, IY_HI, IZ_HI, IT_LO) - P(5, :) = GF%Vel(:, IY_LO, IZ_LO, IT_HI) - P(6, :) = GF%Vel(:, IY_HI, IZ_LO, IT_HI) - P(7, :) = GF%Vel(:, IY_LO, IZ_HI, IT_HI) - P(8, :) = GF%Vel(:, IY_HI, IZ_HI, IT_HI) - - else if (GF%InterpTower) then - - ! Get points from grid bottom and ground - P(1, :) = 0.0_ReKi !GF%Vel(:, IY_LO, IZ_LO, IT_LO) - P(2, :) = 0.0_ReKi !GF%Vel(:, IY_HI, IZ_LO, IT_LO) - P(3, :) = GF%Vel(:, IY_LO, IZ_HI, IT_LO) - P(4, :) = GF%Vel(:, IY_HI, IZ_HI, IT_LO) - P(5, :) = 0.0_ReKi !GF%Vel(:, IY_HI, IZ_LO, IT_HI) - P(6, :) = 0.0_ReKi !GF%Vel(:, IY_LO, IZ_LO, IT_HI) - P(7, :) = GF%Vel(:, IY_LO, IZ_HI, IT_HI) - P(8, :) = GF%Vel(:, IY_HI, IZ_HI, IT_HI) + ! Get velocities from the grid + VelCell(1, :) = G3D%Vel(:, IY_Lo, IZ_Lo, IT_Lo) + VelCell(2, :) = G3D%Vel(:, IY_Hi, IZ_Lo, IT_Lo) + VelCell(3, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Lo) + VelCell(4, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Lo) + VelCell(5, :) = G3D%Vel(:, IY_Lo, IZ_Lo, IT_Hi) + VelCell(6, :) = G3D%Vel(:, IY_Hi, IZ_Lo, IT_Hi) + VelCell(7, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Hi) + VelCell(8, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Hi) - end if + ! Get accelerations from the grid + if (CalcAccel) then + AccCell(1, :) = G3D%Acc(:, IY_Lo, IZ_Lo, IT_Lo) + AccCell(2, :) = G3D%Acc(:, IY_Hi, IZ_Lo, IT_Lo) + AccCell(3, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Lo) + AccCell(4, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Lo) + AccCell(5, :) = G3D%Acc(:, IY_Lo, IZ_Lo, IT_Hi) + AccCell(6, :) = G3D%Acc(:, IY_Hi, IZ_Lo, IT_Hi) + AccCell(7, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Hi) + AccCell(8, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Hi) + end if - ! Get 3D interpolation weights - N(1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) - N(2) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) - N(3) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) - N(4) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) - N(5) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) - N(6) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) - N(7) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) - N(8) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) - N(1:4) = N(1:4)*(1.0_ReKi - DT)/8.0_ReKi - N(5:8) = N(5:8)*(1.0_ReKi + DT)/8.0_ReKi + else if (G3D%InterpTower) then - ! Calculate velocity - do ic = 1, 3 - Velocity(ic) = dot_product(P(:, ic), N) - end do + ! Get velocities from the grid + VelCell(1, :) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Lo) + VelCell(2, :) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Lo) + VelCell(3, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Lo) + VelCell(4, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Lo) + VelCell(5, :) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Hi) + VelCell(6, :) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Hi) + VelCell(7, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Hi) + VelCell(8, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Hi) - else + ! Get accelerations from the grid + if (CalcAccel) then + AccCell(1, :) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Lo) + AccCell(2, :) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Lo) + AccCell(3, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Lo) + AccCell(4, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Lo) + AccCell(5, :) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Hi) + AccCell(6, :) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Hi) + AccCell(7, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Hi) + AccCell(8, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Hi) + end if - if (IZ_HI <= GF%NTGrids) then - ! In tower grid - P(1, :) = GF%VelTower(:, IZ_LO, IT_LO) - P(2, :) = GF%VelTower(:, IZ_HI, IT_LO) - P(3, :) = GF%VelTower(:, IZ_LO, IT_HI) - P(4, :) = GF%VelTower(:, IZ_HI, IT_HI) - else - ! Between tower grid and ground - P(1, :) = GF%VelTower(:, IZ_LO, IT_LO) - P(2, :) = 0.0_ReKi - P(3, :) = GF%VelTower(:, IZ_LO, IT_HI) - P(4, :) = 0.0_ReKi end if - ! Get 2D interpolation weights - N(1) = (1.0_ReKi - DZ)*(1.0_ReKi - DT)/4.0_ReKi - N(2) = (1.0_ReKi + DZ)*(1.0_ReKi - DT)/4.0_ReKi - N(3) = (1.0_ReKi - DZ)*(1.0_ReKi + DT)/4.0_ReKi - N(4) = (1.0_ReKi + DZ)*(1.0_ReKi + DT)/4.0_ReKi + else - ! Calculate velocity - do ic = 1, 3 - Velocity(ic) = dot_product(P(1:4, ic), N(1:4)) - end do + Is3D = .false. - end if + ! In tower grid + if (IZ_HI <= G3D%NTGrids) then + VelCell(1, :) = G3D%VelTower(:, IZ_LO, IT_LO) + VelCell(2, :) = G3D%VelTower(:, IZ_HI, IT_LO) + VelCell(3, :) = G3D%VelTower(:, IZ_LO, IT_HI) + VelCell(4, :) = G3D%VelTower(:, IZ_HI, IT_HI) -end subroutine + if (CalcAccel) then + AccCell(1, :) = G3D%AccTower(:, IZ_LO, IT_LO) + AccCell(2, :) = G3D%AccTower(:, IZ_HI, IT_LO) + AccCell(3, :) = G3D%AccTower(:, IZ_LO, IT_HI) + AccCell(4, :) = G3D%AccTower(:, IZ_HI, IT_HI) + end if -! function GridField_GetAcc(GF, Position, DY, DZ, DT, P, Interp3D) result(Accel) - -! type(GridFieldType), intent(in) :: GF -! real(ReKi), dimension(3), intent(in) :: Position -! real(ReKi), intent(in) :: DY, DZ, DT !< Weights [-1,1] -! real(ReKi), dimension(3, 8), intent(in) :: P !< Interp points -! logical, intent(in) :: Interp3D !< flag for 3D vs 2D interp -! real(ReKi), dimension(3) :: Accel - -! character(*), parameter :: RoutineName = "GridField_GetAcc" -! real(ReKi) :: N(8, 1) - -! if (Interp3D) then - -! ! Get 3D interpolation weights -! N(1, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) -! N(2, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) -! N(3, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) -! N(4, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) -! N(5, 1) = (1.0_ReKi - DY)*(1.0_ReKi - DZ) -! N(6, 1) = (1.0_ReKi + DY)*(1.0_ReKi - DZ) -! N(7, 1) = (1.0_ReKi - DY)*(1.0_ReKi + DZ) -! N(8, 1) = (1.0_ReKi + DY)*(1.0_ReKi + DZ) -! N(1:4, 1) = N(1:4, 1)/(-4.0_ReKi*GF%DTime) -! N(5:8, 1) = N(5:8, 1)/(4.0_ReKi*GF%DTime) - -! ! Calculate Accel via matrix multiplication -! Accel = pack(matmul(P, N), .true.) - -! else - -! ! Get 2D interpolation weights -! N(1, 1) = (1.0_ReKi - DZ)/(-2.0_ReKi*GF%DTime) -! N(2, 1) = (1.0_ReKi + DZ)/(-2.0_ReKi*GF%DTime) -! N(3, 1) = (1.0_ReKi - DZ)/(2.0_ReKi*GF%DTime) -! N(4, 1) = (1.0_ReKi + DZ)/(2.0_ReKi*GF%DTime) - -! ! Calculate Accel via matrix multiplication -! Accel = pack(matmul(P(:, 1:4), N(1:4, 1)), .true.) - -! end if - -! end function - -! subroutine GridField_GetInterp(GF, Time, Position, DY, DZ, DT, P, Interp3D, ErrStat, ErrMsg) - -! type(GridFieldType), intent(in) :: GF !< Grid-Field data -! real(DbKi), intent(in) :: Time !< time (s) -! real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value -! real(ReKi), intent(out) :: DY, DZ, DT !< -! real(ReKi), intent(out) :: P(3, 8) -! logical, intent(out) :: Interp3D -! integer(IntKi), intent(out) :: ErrStat !< error status -! character(*), intent(out) :: ErrMsg !< error message - -! character(*), parameter :: RoutineName = "GridField_GetInterp" - -! end subroutine - -subroutine GridField_GetVelAcc(GF, Time, Position, Velocity, Accel, ErrStat, ErrMsg) - - type(GridFieldType), intent(in) :: GF !< Grid-Field data - real(DbKi), intent(in) :: Time !< time (s) - real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value - real(ReKi), intent(out) :: Velocity(3) !< - real(ReKi), intent(out) :: Accel(3) !< - integer(IntKi), intent(out) :: ErrStat !< error status - character(*), intent(out) :: ErrMsg !< error message - - character(*), parameter :: RoutineName = "GridField_GetSmoothInterp" - real(ReKi) :: Xi_Y, Xi_Z, Xi_T ! isoparametric coordinates (Y,Z,T) - integer(IntKi) :: IY_Lo, IY_Hi - integer(IntKi) :: IZ_Lo, IZ_Hi - integer(IntKi) :: IT_Lo, IT_Hi - integer(IntKi) :: IT, IC - real(ReKi) :: V(4, 3, 2), A(4, 3, 2), N(4) - real(ReKi) :: P(3, 2), PP(3, 2) - real(ReKi) :: h, t, C1, C2, C3, C4 - logical :: OnGrid - real(ReKi) :: TimeShifted - integer(IntKi) :: boundStat + else ! Between tower grid and ground - ErrStat = ErrID_None - ErrMsg = "" + VelCell(1, :) = G3D%VelTower(:, IZ_LO, IT_LO) + VelCell(2, :) = 0.0_ReKi + VelCell(3, :) = G3D%VelTower(:, IZ_LO, IT_HI) + VelCell(4, :) = 0.0_ReKi - !---------------------------------------------------------------------------- - ! Find grid bounds in Time and Z - !---------------------------------------------------------------------------- + if (CalcAccel) then + AccCell(1, :) = G3D%AccTower(:, IZ_LO, IT_LO) + AccCell(2, :) = 0.0_ReKi + AccCell(3, :) = G3D%AccTower(:, IZ_LO, IT_HI) + AccCell(4, :) = 0.0_ReKi + end if - ! Get grid time bounds - boundStat = GridField_GetBoundsT(GF, Time, Position(1), Xi_T, IT_Lo, IT_Hi, TimeShifted) - if (boundStat > 0) then - ErrMsg = ' Error: GF wind array was exhausted at '//TRIM(Num2LStr(TIME))// & - ' seconds (trying to access data at '//TRIM(Num2LStr(TimeShifted))//' seconds).' - ErrStat = ErrID_Fatal - return - end if + end if - ! Get grid Z bounds - boundStat = GridField_GetBoundsZ(GF, Position(3), Xi_Z, IZ_Lo, IZ_Hi, OnGrid) - if (boundStat < 0) then - ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction '// & - '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' - ErrStat = ErrID_Fatal - return - else if (boundStat > 0) then - ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction (Z='// & - TRIM(Num2LStr(Position(3)))//' m is above the grid).' - ErrStat = ErrID_Fatal - return end if - !---------------------------------------------------------------------------- - ! Interpolate - !---------------------------------------------------------------------------- - - if (OnGrid .or. GF%InterpTower) then - - ! Get grid Y bounds - boundStat = GridField_GetBoundsY(GF, Position(2), Xi_Y, IY_Lo, IY_Hi) - if (boundStat /= 0) then - ErrMsg = ' GF wind array boundaries violated: Grid too small in Y direction. Y='// & - TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*GF%YHWid))// & - ', '//TRIM(Num2LStr(GF%YHWid))//']' - ErrStat = ErrID_Fatal - return - end if +end subroutine - if (OnGrid) then +pure function Grid3DField_GetVelLinear(VelCell, Xi, Is3D) result(Velocity) - ! Get velocities from the grid - V(1, :, 1) = GF%Vel(:, IY_Lo, IZ_Lo, IT_Lo) - V(2, :, 1) = GF%Vel(:, IY_Hi, IZ_Lo, IT_Lo) - V(3, :, 1) = GF%Vel(:, IY_Lo, IZ_Hi, IT_Lo) - V(4, :, 1) = GF%Vel(:, IY_Hi, IZ_Hi, IT_Lo) - V(1, :, 2) = GF%Vel(:, IY_Lo, IZ_Lo, IT_Hi) - V(2, :, 2) = GF%Vel(:, IY_Hi, IZ_Lo, IT_Hi) - V(3, :, 2) = GF%Vel(:, IY_Lo, IZ_Hi, IT_Hi) - V(4, :, 2) = GF%Vel(:, IY_Hi, IZ_Hi, IT_Hi) + real(ReKi), intent(in) :: VelCell(8, 3) !< velocities at corners of grid cell + real(ReKi), intent(in) :: Xi(3) !< isoparametric coordinates in cell (dy, dz, dt) [-1, +1] + logical, intent(in) :: Is3D !< flag for 3D or 2D grid + real(ReKi) :: Velocity(3) !< The U, V, W velocities - ! Get accelerations from the grid - A(1, :, 1) = GF%Acc(:, IY_Lo, IZ_Lo, IT_Lo) - A(2, :, 1) = GF%Acc(:, IY_Hi, IZ_Lo, IT_Lo) - A(3, :, 1) = GF%Acc(:, IY_Lo, IZ_Hi, IT_Lo) - A(4, :, 1) = GF%Acc(:, IY_Hi, IZ_Hi, IT_Lo) - A(1, :, 2) = GF%Acc(:, IY_Lo, IZ_Lo, IT_Hi) - A(2, :, 2) = GF%Acc(:, IY_Hi, IZ_Lo, IT_Hi) - A(3, :, 2) = GF%Acc(:, IY_Lo, IZ_Hi, IT_Hi) - A(4, :, 2) = GF%Acc(:, IY_Hi, IZ_Hi, IT_Hi) + real(ReKi) :: N(8) ! Shape function values + integer(IntKi) :: IC - else if (GF%InterpTower) then + if (Is3D) then - ! Get velocities from the grid - V(1, :, 1) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Lo) - V(2, :, 1) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Lo) - V(3, :, 1) = GF%Vel(:, IY_Lo, IZ_Hi, IT_Lo) - V(4, :, 1) = GF%Vel(:, IY_Hi, IZ_Hi, IT_Lo) - V(1, :, 2) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Hi) - V(2, :, 2) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Hi) - V(3, :, 2) = GF%Vel(:, IY_Lo, IZ_Hi, IT_Hi) - V(4, :, 2) = GF%Vel(:, IY_Hi, IZ_Hi, IT_Hi) + ! Get 3D interpolation weights + N(1) = (1.0_ReKi - Xi(1))*(1.0_ReKi - Xi(2)) + N(2) = (1.0_ReKi + Xi(1))*(1.0_ReKi - Xi(2)) + N(3) = (1.0_ReKi - Xi(1))*(1.0_ReKi + Xi(2)) + N(4) = (1.0_ReKi + Xi(1))*(1.0_ReKi + Xi(2)) + N(5) = (1.0_ReKi - Xi(1))*(1.0_ReKi - Xi(2)) + N(6) = (1.0_ReKi + Xi(1))*(1.0_ReKi - Xi(2)) + N(7) = (1.0_ReKi - Xi(1))*(1.0_ReKi + Xi(2)) + N(8) = (1.0_ReKi + Xi(1))*(1.0_ReKi + Xi(2)) + N(1:4) = N(1:4)*(1.0_ReKi - Xi(3))/8.0_ReKi + N(5:8) = N(5:8)*(1.0_ReKi + Xi(3))/8.0_ReKi - ! Get accelerations from the grid - A(1, :, 1) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Lo) - A(2, :, 1) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Lo) - A(3, :, 1) = GF%Acc(:, IY_Lo, IZ_Hi, IT_Lo) - A(4, :, 1) = GF%Acc(:, IY_Hi, IZ_Hi, IT_Lo) - A(1, :, 2) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Hi) - A(2, :, 2) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Hi) - A(3, :, 2) = GF%Acc(:, IY_Lo, IZ_Hi, IT_Hi) - A(4, :, 2) = GF%Acc(:, IY_Hi, IZ_Hi, IT_Hi) + ! Calculate velocity + do ic = 1, 3 + Velocity(ic) = dot_product(VelCell(:, ic), N) + end do - end if + else - ! Get interpolation weights - N(1) = (1.0_ReKi - Xi_Y)*(1.0_ReKi - Xi_Z)/4.0_ReKi - N(2) = (1.0_ReKi + Xi_Y)*(1.0_ReKi - Xi_Z)/4.0_ReKi - N(3) = (1.0_ReKi - Xi_Y)*(1.0_ReKi + Xi_Z)/4.0_ReKi - N(4) = (1.0_ReKi + Xi_Y)*(1.0_ReKi + Xi_Z)/4.0_ReKi + ! Get 2D interpolation weights + N(1) = (1.0_ReKi - Xi(2))*(1.0_ReKi - Xi(3))/4.0_ReKi + N(2) = (1.0_ReKi + Xi(2))*(1.0_ReKi - Xi(3))/4.0_ReKi + N(3) = (1.0_ReKi - Xi(2))*(1.0_ReKi + Xi(3))/4.0_ReKi + N(4) = (1.0_ReKi + Xi(2))*(1.0_ReKi + Xi(3))/4.0_ReKi - ! Calculate velocity and acceleration at lo and hi time - do IT = 1, 2 - do IC = 1, 3 - P(IC, IT) = dot_product(V(:, IC, IT), N) - PP(IC, IT) = dot_product(A(:, IC, IT), N) - end do + ! Calculate velocity + do ic = 1, 3 + Velocity(ic) = dot_product(VelCell(1:4, ic), N(1:4)) end do - else + end if - if (IZ_HI <= GF%NTGrids) then +end function - ! In tower grid - V(1, :, 1) = GF%VelTower(:, IZ_LO, IT_LO) - V(2, :, 1) = GF%VelTower(:, IZ_HI, IT_LO) - V(1, :, 2) = GF%VelTower(:, IZ_LO, IT_HI) - V(2, :, 2) = GF%VelTower(:, IZ_HI, IT_HI) +subroutine Grid3DField_GetVelAccCubic(DTime, VelCell, AccCell, Xi, Is3D, Velocity, Accel) - A(1, :, 1) = GF%AccTower(:, IZ_LO, IT_LO) - A(2, :, 1) = GF%AccTower(:, IZ_HI, IT_LO) - A(1, :, 2) = GF%AccTower(:, IZ_LO, IT_HI) - A(2, :, 2) = GF%AccTower(:, IZ_HI, IT_HI) + real(ReKi), intent(in) :: DTime !< cell delta time + real(ReKi), intent(in) :: VelCell(8, 3) !< + real(ReKi), intent(in) :: AccCell(8, 3) !< + real(ReKi), intent(in) :: Xi(3) !< cell distance (dy, dz, dt) [-1, +1] + logical, intent(in) :: Is3D !< + real(ReKi), intent(out), optional :: Velocity(3) !< + real(ReKi), intent(out), optional :: Accel(3) !< - else + character(*), parameter :: RoutineName = "Grid3DField_GetVelAccCubic" + integer(IntKi) :: IC + real(ReKi) :: N(4) + real(ReKi) :: P(3, 2), PP(3, 2) + real(ReKi) :: h, t, C1, C2, C3, C4 - ! Between tower grid and ground - V(1, :, 1) = GF%VelTower(:, IZ_LO, IT_LO) - V(2, :, 1) = 0.0_ReKi - V(1, :, 2) = GF%VelTower(:, IZ_LO, IT_HI) - V(2, :, 2) = 0.0_ReKi + ! If 3D interpolation + if (Is3D) then - ! Between tower grid and ground - A(1, :, 1) = GF%AccTower(:, IZ_LO, IT_LO) - A(2, :, 1) = 0.0_ReKi - A(1, :, 2) = GF%AccTower(:, IZ_LO, IT_HI) - A(2, :, 2) = 0.0_ReKi + ! Get interpolation weights + N(1) = (1.0_ReKi - Xi(1))*(1.0_ReKi - Xi(2))/4.0_ReKi + N(2) = (1.0_ReKi + Xi(1))*(1.0_ReKi - Xi(2))/4.0_ReKi + N(3) = (1.0_ReKi - Xi(1))*(1.0_ReKi + Xi(2))/4.0_ReKi + N(4) = (1.0_ReKi + Xi(1))*(1.0_ReKi + Xi(2))/4.0_ReKi + + ! Calculate velocity at lo and hi time + if (present(Velocity)) then + do IC = 1, 3 + P(IC, 1) = dot_product(VelCell(1:4, IC), N) ! low time + P(IC, 2) = dot_product(VelCell(5:8, IC), N) ! hi time + end do + end if + ! Calculate acceleration at lo and hi time + if (present(Accel)) then + do IC = 1, 3 + PP(IC, 1) = dot_product(AccCell(1:4, IC), N) ! low time + PP(IC, 2) = dot_product(AccCell(5:8, IC), N) ! hi time + end do end if + else ! 2D (Tower) + ! Get interpolation weights - N(1) = (1.0_ReKi - Xi_Z)/2.0_ReKi - N(2) = (1.0_ReKi + Xi_Z)/2.0_ReKi + N(1) = (1.0_ReKi - Xi(2))/2.0_ReKi + N(2) = (1.0_ReKi + Xi(2))/2.0_ReKi ! Calculate velocity and acceleration at lo and hi time - do IT = 1, 2 + if (present(Velocity)) then do IC = 1, 3 - P(IC, IT) = dot_product(V(1:2, IC, IT), N(1:2)) - PP(IC, IT) = dot_product(A(1:2, IC, IT), N(1:2)) + P(IC, 1) = dot_product(VelCell(1:2, IC), N(1:2)) ! low time + P(IC, 2) = dot_product(VelCell(3:4, IC), N(1:2)) ! hi time end do - end do + end if + + ! Calculate acceleration at lo and hi time + if (present(Accel)) then + do IC = 1, 3 + PP(IC, 1) = dot_product(AccCell(1:2, IC), N(1:2)) ! low time + PP(IC, 2) = dot_product(AccCell(3:4, IC), N(1:2)) ! hi time + end do + end if end if @@ -1014,28 +973,30 @@ subroutine GridField_GetVelAcc(GF, Time, Position, Velocity, Accel, ErrStat, Err ! Smooth velocity and acceleration using cubic hermite spline !---------------------------------------------------------------------------- - h = GF%DTime - t = (Xi_T + 1)/2.0_ReKi - - C1 = 2.0_ReKi*t*t*t - 3.0_ReKi*t*t + 1.0_ReKi - C2 = (t*t*t - 2.0_ReKi*t*t + t)*h - C3 = -2.0_ReKi*t*t*t + 3.0_ReKi*t*t - C4 = (t*t*t - t*t)*h + h = DTime + t = (Xi(3) + 1)/2.0_ReKi - Velocity = C1*P(:, 1) + C2*PP(:, 1) + C3*P(:, 2) + C4*PP(:, 2) - - C1 = (6.0_ReKi*t*t - 6.0_ReKi*t)/h - C2 = 3.0_ReKi*t*t - 4.0_ReKi*t + 1.0_ReKi - C3 = -C1 - C4 = 3.0_ReKi*t*t - 2.0_ReKi*t + if (present(Velocity)) then + C1 = 2.0_ReKi*t*t*t - 3.0_ReKi*t*t + 1.0_ReKi + C2 = (t*t*t - 2.0_ReKi*t*t + t)*h + C3 = -2.0_ReKi*t*t*t + 3.0_ReKi*t*t + C4 = (t*t*t - t*t)*h + Velocity = C1*P(:, 1) + C2*PP(:, 1) + C3*P(:, 2) + C4*PP(:, 2) + end if - Accel = C1*P(:, 1) + C2*PP(:, 1) + C3*P(:, 2) + C4*PP(:, 2) + if (present(Accel)) then + C1 = (6.0_ReKi*t*t - 6.0_ReKi*t)/h + C2 = 3.0_ReKi*t*t - 4.0_ReKi*t + 1.0_ReKi + C3 = -C1 + C4 = 3.0_ReKi*t*t - 2.0_ReKi*t + Accel = C1*P(:, 1) + C2*PP(:, 1) + C3*P(:, 2) + C4*PP(:, 2) + end if end subroutine -function GridField_GetBoundsY(GF, PosY, DY, IY_LO, IY_HI) result(stat) +function Grid3DField_GetBoundsY(G3D, PosY, DY, IY_LO, IY_HI) result(stat) - type(GridFieldType), intent(in) :: GF + type(Grid3DFieldType), intent(in) :: G3D real(ReKi), intent(in) :: PosY real(ReKi), intent(out) :: DY integer(IntKi), intent(out) :: IY_LO, IY_HI @@ -1044,7 +1005,7 @@ function GridField_GetBoundsY(GF, PosY, DY, IY_LO, IY_HI) result(stat) integer(IntKi) :: stat ! Calculate position on Y grid - Y_Grid = (PosY + GF%YHWid)*GF%InvDY + 1 + Y_Grid = (PosY + G3D%YHWid)*G3D%InvDY + 1 ! Calculate bounding grid indices IY_LO = floor(Y_Grid, IntKi) @@ -1056,15 +1017,15 @@ function GridField_GetBoundsY(GF, PosY, DY, IY_LO, IY_HI) result(stat) ! Initialize stat to zero to indicate position is in bounds stat = 0 - if (IY_LO >= 1 .and. IY_HI <= GF%NYGrids) then + if (IY_LO >= 1 .and. IY_HI <= G3D%NYGrids) then DY = 2.0_ReKi*DY - 1.0_ReKi else if (IY_LO == 0 .and. DY >= 1.0_ReKi - GridTol) then IY_LO = 1 IY_HI = 2 DY = -1.0_ReKi - else if (IY_LO == GF%NYGrids .and. DY <= GridTol) then - IY_LO = GF%NYGrids - 1 - IY_HI = GF%NYGrids + else if (IY_LO == G3D%NYGrids .and. DY <= GridTol) then + IY_LO = G3D%NYGrids - 1 + IY_HI = G3D%NYGrids DY = 1.0_ReKi else ! Position outside @@ -1073,9 +1034,9 @@ function GridField_GetBoundsY(GF, PosY, DY, IY_LO, IY_HI) result(stat) end function -function GridField_GetBoundsZ(GF, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) +function Grid3DField_GetBoundsZ(G3D, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) - type(GridFieldType), intent(in) :: GF + type(Grid3DFieldType), intent(in) :: G3D real(ReKi), intent(in) :: PosZ real(ReKi), intent(out) :: DZ integer(IntKi), intent(out) :: IZ_LO, IZ_HI @@ -1085,7 +1046,7 @@ function GridField_GetBoundsZ(GF, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) real(ReKi) :: Z_GRID ! Calculate position on Z grid - Z_GRID = (PosZ - GF%GridBase)*GF%InvDZ + 1 + Z_GRID = (PosZ - G3D%GridBase)*G3D%InvDZ + 1 ! Calculate bounding grid indices IZ_LO = floor(Z_GRID, IntKi) @@ -1098,7 +1059,7 @@ function GridField_GetBoundsZ(GF, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) stat = 0 ! If indices are within grid, set on grid to true - if (IZ_LO >= 1 .and. IZ_HI <= GF%NZGrids) then + if (IZ_LO >= 1 .and. IZ_HI <= G3D%NZGrids) then OnGrid = .true. DZ = 2.0_ReKi*DZ - 1.0_ReKi @@ -1110,21 +1071,21 @@ function GridField_GetBoundsZ(GF, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) IZ_LO = 1 IZ_HI = 2 DZ = -1.0_ReKi - else if (GF%InterpTower) then + else if (G3D%InterpTower) then ! Interp from bottom of grid to ground (zero velocity) OnGrid = .false. IZ_LO = 0 IZ_HI = 1 - DZ = 2.0_ReKi*(PosZ/GF%GridBase) - 1.0_ReKi - else if (GF%NTGrids > 0) then + DZ = 2.0_ReKi*(PosZ/G3D%GridBase) - 1.0_ReKi + else if (G3D%NTGrids > 0) then ! Interpolate with tower grid OnGrid = .false. ! Tower grid is reversed (lowest index is top of tower) IZ_LO = int(-(Z_GRID - 1)) + 1 - if (IZ_LO >= GF%NTGrids) then + if (IZ_LO >= G3D%NTGrids) then ! Between end of tower grid and ground (zero velocity) - IZ_LO = GF%NTGrids - DZ = 1.0_ReKi - 2.0_ReKi*(PosZ/(GF%GridBase - real(IZ_LO - 1, ReKi)/GF%InvDZ)) + IZ_LO = G3D%NTGrids + DZ = 1.0_ReKi - 2.0_ReKi*(PosZ/(G3D%GridBase - real(IZ_LO - 1, ReKi)/G3D%InvDZ)) else ! Within tower grid DZ = 2.0_ReKi*(real(2 - IZ_LO, ReKi) - Z_GRID) - 1.0_ReKi @@ -1135,12 +1096,12 @@ function GridField_GetBoundsZ(GF, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) stat = -1 end if - else if (IZ_HI > GF%NZGrids) then ! Above Grid + else if (IZ_HI > G3D%NZGrids) then ! Above Grid - if (IZ_HI == GF%NZGrids + 1 .and. DZ <= GridTol) then + if (IZ_HI == G3D%NZGrids + 1 .and. DZ <= GridTol) then OnGrid = .true. - IZ_LO = GF%NZGrids - 1 - IZ_HI = GF%NZGrids + IZ_LO = G3D%NZGrids - 1 + IZ_HI = G3D%NZGrids DZ = 1.0_ReKi else ! Position above grid @@ -1151,9 +1112,9 @@ function GridField_GetBoundsZ(GF, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) end function -function GridField_GetBoundsT(GF, Time, PosX, DT, IT_LO, IT_HI, TimeShifted) result(stat) +function Grid3DField_GetBoundsT(G3D, Time, PosX, DT, IT_LO, IT_HI, TimeShifted) result(stat) - type(GridFieldType), intent(in) :: GF + type(Grid3DFieldType), intent(in) :: G3D real(DbKi), intent(in) :: Time real(ReKi), intent(in) :: PosX real(ReKi), intent(out) :: DT @@ -1170,15 +1131,15 @@ function GridField_GetBoundsT(GF, Time, PosX, DT, IT_LO, IT_HI, TimeShifted) res ! large as the rotor. If it isn't, then the interpolation will not work. ! in distance, X: InputInfo%PosX - p%InitXPosition - TIME*p%MeanWS - TimeShifted = real(Time, ReKi) + (GF%InitXPosition - PosX)*GF%InvMWS + TimeShifted = real(Time, ReKi) + (G3D%InitXPosition - PosX)*G3D%InvMWS ! If field is periodic and time is after total time, remove total time - if (GF%Periodic .and. TimeShifted > GF%TotalTime) then - TimeShifted = TimeShifted - GF%TotalTime + if (G3D%Periodic .and. TimeShifted > G3D%TotalTime) then + TimeShifted = TimeShifted - G3D%TotalTime end if ! Get position on T grid - T_GRID = TimeShifted*GF%Rate + 1 + T_GRID = TimeShifted*G3D%Rate + 1 ! Calculate bounding grid indices IT_LO = floor(T_GRID, IntKi) @@ -1191,11 +1152,11 @@ function GridField_GetBoundsT(GF, Time, PosX, DT, IT_LO, IT_HI, TimeShifted) res stat = 0 ! Adjust indices and interpolant - if (IT_LO >= 1 .and. IT_HI <= GF%NSteps) then + if (IT_LO >= 1 .and. IT_HI <= G3D%NSteps) then ! Point is within grid DT = 2.0_ReKi*DT - 1.0_ReKi - else if (IT_LO == GF%NSteps) then - if (GF%Periodic) then + else if (IT_LO == G3D%NSteps) then + if (G3D%Periodic) then ! Time wraps back to beginning IT_HI = 1 DT = 2.0_ReKi*DT - 1.0_ReKi @@ -1205,8 +1166,8 @@ function GridField_GetBoundsT(GF, Time, PosX, DT, IT_LO, IT_HI, TimeShifted) res DT = -1.0_Reki else ! Extrapolate - IT_LO = GF%NSteps - 1 - IT_HI = GF%NSteps + IT_LO = G3D%NSteps - 1 + IT_HI = G3D%NSteps DT = DT + 1.0_ReKi end if else @@ -1216,65 +1177,65 @@ function GridField_GetBoundsT(GF, Time, PosX, DT, IT_LO, IT_HI, TimeShifted) res end function -subroutine GridField_CalcAccel(GF, ErrStat, ErrMsg) - type(GridFieldType), intent(inout) :: GF - integer(IntKi), intent(out) :: ErrStat - character(*), intent(out) :: ErrMsg +subroutine Grid3DField_CalcAccel(G3D, ErrStat, ErrMsg) + type(Grid3DFieldType), intent(inout) :: G3D + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = "GridField_CalcAccel" - integer(IntKi) :: TmpErrStat - character(ErrMsgLen) :: TmpErrMsg - integer(IntKi) :: ic, iy, iz - real(ReKi), allocatable :: b(:), u(:), dy2(:) + character(*), parameter :: RoutineName = "Grid3DField_CalcAccel" + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + integer(IntKi) :: ic, iy, iz + real(ReKi), allocatable :: b(:), u(:), dy2(:) ErrStat = ErrID_None ErrMsg = "" ! Allocate storage for acceleration grid - call AllocAry(GF%Acc, size(GF%Vel, dim=1), size(GF%Vel, dim=2), & - size(GF%Vel, dim=3), size(GF%Vel, dim=4), & + call AllocAry(G3D%Acc, size(G3D%Vel, dim=1), size(G3D%Vel, dim=2), & + size(G3D%Vel, dim=3), size(G3D%Vel, dim=4), & 'grid-field velocity data', TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! Allocate storage for B used in cubic spline derivative calc - call AllocAry(B, GF%NSteps, "storage for B", TmpErrStat, TmpErrMsg) + call AllocAry(B, G3D%NSteps, "storage for B", TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! Allocate storage for U used in cubic spline derivative calc - call AllocAry(U, GF%NSteps, "storage for U", TmpErrStat, TmpErrMsg) + call AllocAry(U, G3D%NSteps, "storage for U", TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! Allocate storage for V used in cubic spline derivative calc - call AllocAry(dy2, GF%NSteps, "storage for V", TmpErrStat, TmpErrMsg) + call AllocAry(dy2, G3D%NSteps, "storage for V", TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! Calculate acceleration at each grid point - do iz = 1, GF%NZGrids - do iy = 1, GF%NYGrids - do ic = 1, GF%NComp - call CalcCubicSplineDeriv(GF%DTime, GF%Vel(ic, iy, iz, :), GF%Acc(ic, iy, iz, :)) + do iz = 1, G3D%NZGrids + do iy = 1, G3D%NYGrids + do ic = 1, G3D%NComp + call CalcCubicSplineDeriv(G3D%DTime, G3D%Vel(ic, iy, iz, :), G3D%Acc(ic, iy, iz, :)) end do end do end do ! If grid field includes tower grids - if (GF%NTGrids > 0) then + if (G3D%NTGrids > 0) then ! Allocate storage for tower acceleration - call AllocAry(GF%AccTower, size(GF%VelTower, dim=1), & - size(GF%VelTower, dim=2), size(GF%VelTower, dim=3), & + call AllocAry(G3D%AccTower, size(G3D%VelTower, dim=1), & + size(G3D%VelTower, dim=2), size(G3D%VelTower, dim=3), & 'tower wind acceleration data.', TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! Loop through tower grid and calculate acceleration - do iz = 1, GF%NTGrids - do ic = 1, GF%NComp - call CalcCubicSplineDeriv(GF%DTime, GF%VelTower(ic, iz, :), GF%AccTower(ic, iz, :)) + do iz = 1, G3D%NTGrids + do ic = 1, G3D%NComp + call CalcCubicSplineDeriv(G3D%DTime, G3D%VelTower(ic, iz, :), G3D%AccTower(ic, iz, :)) end do end do end if @@ -1335,16 +1296,16 @@ subroutine CalcCubicSplineDeriv(h, y, dy) end subroutine -subroutine ExtGridField_GetVel(EGF, Time, Position, Velocity, ErrStat, ErrMsg) +subroutine Grid4DField_GetVel(G4D, Time, Position, Velocity, ErrStat, ErrMsg) - type(ExtGridFieldType), intent(in) :: EGF !< External grid-field data + type(Grid4DFieldType), intent(in) :: G4D !< 4D grid-field data real(DbKi), intent(in) :: Time !< time to get value real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value real(ReKi), intent(out) :: Velocity(3) !< The U, V, W velocities integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = "ExtGridField_GetVel" + character(*), parameter :: RoutineName = "Grid4DField_GetVel" integer(IntKi) :: Indx_Lo(4) ! index associated with lower bound of dimension 1-4 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) integer(IntKi) :: Indx_Hi(4) ! index associated with upper bound of dimension 1-4 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) @@ -1362,7 +1323,7 @@ subroutine ExtGridField_GetVel(EGF, Time, Position, Velocity, ErrStat, ErrMsg) !---------------------------------------------------------------------------- do i = 1, 3 - tmp = (Position(i) - EGF%pZero(i))/EGF%delta(i) + tmp = (Position(i) - G4D%pZero(i))/G4D%delta(i) Indx_Lo(i) = INT(tmp) + 1 ! convert REAL to INTEGER, then add one since our grid indices start at 1, not 0 xi(i) = 2.0_ReKi*(tmp - aint(tmp)) - 1.0_ReKi ! convert to value between -1 and 1 end do @@ -1372,10 +1333,10 @@ subroutine ExtGridField_GetVel(EGF, Time, Position, Velocity, ErrStat, ErrMsg) !---------------------------------------------------------------------------- i = 4 - tmp = real((Time - EGF%TimeStart)/EGF%delta(i), ReKi) + tmp = real((Time - G4D%TimeStart)/G4D%delta(i), ReKi) Indx_Lo(i) = INT(tmp) + 1 ! convert REAL to INTEGER, then add one since our grid indices start at 1, not 0 xi(i) = 2.0_ReKi*(tmp - aint(tmp)) - 1.0_ReKi ! convert to value between -1 and 1 - if ((Indx_Lo(i) == EGF%n(i))) then + if ((Indx_Lo(i) == G4D%n(i))) then if (abs(xi(i) + 1.0_SiKi) < 0.001_SiKi) then ! Allow for the special case where Time = TgridStart + deltat*( n_high_low - 1 ) Indx_Lo(i) = Indx_Lo(i) - 1 xi(i) = 1.0_SiKi @@ -1391,12 +1352,12 @@ subroutine ExtGridField_GetVel(EGF, Time, Position, Velocity, ErrStat, ErrMsg) Indx_Lo(i) = 1 call SetErrStat(ErrID_Fatal, 'Outside the grid bounds.', ErrStat, ErrMsg, RoutineName) return - elseif (Indx_Lo(i) >= EGF%n(i)) then - Indx_Lo(i) = max(EGF%n(i) - 1, 1) ! make sure it's a valid index + 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) return end if - Indx_Hi(i) = min(Indx_Lo(i) + 1, EGF%n(i)) ! make sure it's a valid index + Indx_Hi(i) = min(Indx_Lo(i) + 1, G4D%n(i)) ! make sure it's a valid index end do !---------------------------------------------------------------------------- @@ -1431,22 +1392,22 @@ subroutine ExtGridField_GetVel(EGF, Time, Position, Velocity, ErrStat, ErrMsg) ! Get point values !---------------------------------------------------------------------------- - P(:, 1) = EGF%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4)) - P(:, 2) = EGF%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4)) - P(:, 3) = EGF%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4)) - P(:, 4) = EGF%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4)) - P(:, 5) = EGF%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4)) - P(:, 6) = EGF%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4)) - P(:, 7) = EGF%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4)) - P(:, 8) = EGF%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4)) - P(:, 9) = EGF%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4)) - P(:, 10) = EGF%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4)) - P(:, 11) = EGF%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4)) - P(:, 12) = EGF%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4)) - P(:, 13) = EGF%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4)) - P(:, 14) = EGF%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4)) - P(:, 15) = EGF%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4)) - P(:, 16) = EGF%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4)) + P(:, 1) = G4D%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4)) + P(:, 2) = G4D%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4)) + P(:, 3) = G4D%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4)) + P(:, 4) = G4D%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4)) + P(:, 5) = G4D%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4)) + P(:, 6) = G4D%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4)) + P(:, 7) = G4D%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4)) + P(:, 8) = G4D%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4)) + P(:, 9) = G4D%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4)) + P(:, 10) = G4D%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4)) + P(:, 11) = G4D%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4)) + P(:, 12) = G4D%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4)) + P(:, 13) = G4D%Vel(:, Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4)) + P(:, 14) = G4D%Vel(:, Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4)) + P(:, 15) = G4D%Vel(:, Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4)) + P(:, 16) = G4D%Vel(:, Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4)) !---------------------------------------------------------------------------- ! Interpolate @@ -1456,4 +1417,23 @@ subroutine ExtGridField_GetVel(EGF, Time, Position, Velocity, ErrStat, ErrMsg) end subroutine +subroutine UserField_GetVel(UF, Time, Position, Velocity, ErrStat, ErrMsg) + + type(UserFieldType), intent(in) :: UF !< user-field data + real(DbKi), intent(in) :: Time !< time to get value + real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value + real(ReKi), intent(out) :: Velocity(3) !< The U, V, W velocities + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = "UserField_GetVel" + + ErrStat = ErrID_None + ErrMsg = "" + + Velocity = 0.0_ReKi + call SetErrStat(ErrID_Fatal, "UserField_GetVel not implemented", ErrStat, ErrMsg, RoutineName) + +end subroutine + end module diff --git a/modules/inflowwind/src/FlowField.txt b/modules/inflowwind/src/FlowField.txt index 477ced3c74..0518bf963e 100644 --- a/modules/inflowwind/src/FlowField.txt +++ b/modules/inflowwind/src/FlowField.txt @@ -6,10 +6,10 @@ param FlowField - IntKi Undef_FieldType - 0 - "This is the code for an undefined FieldType" - param ^ - IntKi Uniform_FieldType - 1 - "Uniform FieldType from SteadyWind or Uniform Wind" - -param ^ - IntKi Grid_FieldType - 2 - "Grid-Field FieldType from TurbSim, Bladed, HAWC" - -param ^ - IntKi ExtGrid_FieldType - 3 - "External Grid FieldType from OpFM or similar" - -param ^ - IntKi ExtPoint_FieldType - 4 - "External Point FieldType from OpFM or similar" - -param ^ - IntKi User_FieldType - 5 - "User FieldType configured by the user" - +param ^ - IntKi Grid3D_FieldType - 2 - "3D Grid FieldType from TurbSim, Bladed, HAWC" - +param ^ - IntKi Grid4D_FieldType - 3 - "4D Grid FieldType from FAST.Farm" - +param ^ - IntKi Point_FieldType - 4 - "Points FieldType from ExtInflow" - +param ^ - IntKi User_FieldType - 5 - "User FieldType configured by the user" - #---------------------------------------------------------------------------------------------------------------------------------- typedef ^ UniformFieldType ReKi RefHeight - - - "reference height; used to center the wind" meters @@ -55,7 +55,7 @@ typedef ^ ^ ReKi CosAngleV typedef ^ ^ ReKi SinAngleV - - - "Vertical angle components" - #---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ GridFieldType IntKi WindFileFormat - - - "Binary file format description number" - +typedef ^ Grid3DFieldType IntKi WindFileFormat - - - "Binary file format description number" - typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - typedef ^ ^ Logical Periodic - .false. - "Flag to indicate if the wind file is periodic" - typedef ^ ^ Logical InterpTower - .false. - "Flag to indicate if we should interpolate wind speeds below the tower" - @@ -88,26 +88,27 @@ typedef ^ ^ ReKi Z0 typedef ^ UserFieldType SiKi Dummy - - - "" - #---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ ExtGridFieldType IntKi n 4 - - "number of evenly-spaced grid points in the x, y, z, and t directions" - +typedef ^ Grid4DFieldType IntKi n 4 - - "number of evenly-spaced grid points in the x, y, z, and t directions" - typedef ^ ^ ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" typedef ^ ^ SiKi Vel ::::: - - "this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt]" - typedef ^ ^ ReKi TimeStart - - - "this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1))" s #---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ ExtPointFieldType ReKi Vel :: - - "Point velocities populated by external driver [uvw,point]" - +typedef ^ PointsFieldType ReKi Vel :: - - "Point velocities populated by external driver [uvw,point]" - #---------------------------------------------------------------------------------------------------------------------------------- typedef ^ FlowFieldType IntKi FieldType - 0 - "Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External}" - typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" radians -typedef ^ ^ IntKi VelInterpOrder - 0 - "Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7]" - +typedef ^ ^ logical VelInterpCubic - .false. - "Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7]" - typedef ^ ^ logical RotateWindBox - .false. - "flag indicating if the wind will be rotated" - +typedef ^ ^ logical AccFieldValid - .false. - "flag indicating that acceleration field has been calculated" - typedef ^ ^ ReKi RotToWind {3}{3} - - "Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X')" - typedef ^ ^ ReKi RotFromWind {3}{3} - - "Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind)" - typedef ^ ^ UniformFieldType Uniform - - - "Uniform Flow Data" -typedef ^ ^ GridFieldType Grid - - - "Grid Field Wind Data" +typedef ^ ^ PointsFieldType Points - - - "External Point Flow Data" +typedef ^ ^ Grid3DFieldType Grid3D - - - "Grid Field Wind Data" +typedef ^ ^ Grid4DFieldType Grid4D - - - "External Grid Flow Data" typedef ^ ^ UserFieldType User - - - "User Field Wind Data" -typedef ^ ^ ExtGridFieldType ExtGrid - - - "External Grid Flow Data" -typedef ^ ^ ExtPointFieldType ExtPoint - - - "External Point Flow Data" diff --git a/modules/inflowwind/src/FlowField_IO.f90 b/modules/inflowwind/src/FlowField_IO.f90 index 71562f8ba8..ead54f170d 100644 --- a/modules/inflowwind/src/FlowField_IO.f90 +++ b/modules/inflowwind/src/FlowField_IO.f90 @@ -94,39 +94,39 @@ subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) call UniformWind_Init(InitInp%Uniform, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) case (3) ! Binary TurbSim FF - FF%FieldType = Grid_FieldType - call TurbSim_Init(InitInp%TurbSim, InitInp%SumFileUnit, FF%Grid, InitOut%FileDat, TmpErrStat, TmpErrMsg) + FF%FieldType = Grid3D_FieldType + call TurbSim_Init(InitInp%TurbSim, InitInp%SumFileUnit, FF%Grid3D, InitOut%FileDat, TmpErrStat, TmpErrMsg) case (4) ! Binary Bladed-Style FF - FF%FieldType = Grid_FieldType + FF%FieldType = Grid3D_FieldType ! call Read_Bladed_Binary(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) TmpErrStat = ErrID_Fatal TmpErrMsg = "Binary Bladed Wind is not implemented" case (5) ! HAWC - FF%FieldType = Grid_FieldType - call HAWC_Init(InitInp%HAWC, InitInp%SumFileUnit, FF%Grid, InitOut%FileDat, TmpErrStat, TmpErrMsg) + FF%FieldType = Grid3D_FieldType + call HAWC_Init(InitInp%HAWC, InitInp%SumFileUnit, FF%Grid3D, InitOut%FileDat, TmpErrStat, TmpErrMsg) case (6) ! User Defined - FF%FieldType = Grid_FieldType + FF%FieldType = Grid3D_FieldType TmpErrStat = ErrID_Fatal TmpErrMsg = "User Wind is not implemented" case (7) ! Native Bladed FF - FF%FieldType = Grid_FieldType + FF%FieldType = Grid3D_FieldType ! call Read_Bladed_Native(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) TmpErrStat = ErrID_Fatal TmpErrMsg = "Native Bladed Wind is not implemented" case (8) ! External Grid - FF%FieldType = ExtGrid_FieldType + FF%FieldType = Grid4D_FieldType TmpErrStat = ErrID_Fatal - TmpErrMsg = "ExtGrid Wind is not implemented" + TmpErrMsg = "Grid4D Wind is not implemented" case (9) ! External Point - FF%FieldType = ExtPoint_FieldType + FF%FieldType = Point_FieldType TmpErrStat = ErrID_Fatal - TmpErrMsg = "ExtPoint Wind is not implemented" + TmpErrMsg = "Points Wind is not implemented" case default ! Others TmpErrStat = ErrID_Fatal @@ -140,19 +140,24 @@ subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) ! Field Type Initialization !---------------------------------------------------------------------------- + ! Reset flag indicating that acceleration field is valid + FF%AccFieldValid = .false. + select case (FF%FieldType) case (Uniform_FieldType) - if (InitInp%CalcAccel .or. (InitInp%VelInterpOrder == 3)) then + if (InitInp%CalcAccel .or. (InitInp%VelInterpCubic)) then call UniformField_CalcAccel(FF%Uniform, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return + FF%AccFieldValid = .true. end if - case (Grid_FieldType) - if (InitInp%CalcAccel .or. (InitInp%VelInterpOrder == 3)) then - call GridField_CalcAccel(FF%Grid, TmpErrStat, TmpErrMsg) + case (Grid3D_FieldType) + if (InitInp%CalcAccel .or. (InitInp%VelInterpCubic)) then + call Grid3DField_CalcAccel(FF%Grid3D, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return + FF%AccFieldValid = .true. end if case default @@ -563,7 +568,7 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) type(TurbSimInitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit - type(GridFieldType), intent(out) :: GF + type(Grid3DFieldType), intent(out) :: GF type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg @@ -784,7 +789,7 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) ! Store wind file metadata !---------------------------------------------------------------------------- - call PopulateWindFileDatFromGridField(GF, InitInp%WindFileName, 3, GF%NTGrids > 0, FileDat) + call PopulateWindFileDatFromGrid3DField(GF, InitInp%WindFileName, 3, GF%NTGrids > 0, FileDat) !---------------------------------------------------------------------------- ! Write the summary file @@ -838,7 +843,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) type(HAWCInitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit - type(GridFieldType), intent(out) :: GF + type(Grid3DFieldType), intent(out) :: GF type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg @@ -1065,7 +1070,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) ! Store wind file metadata !---------------------------------------------------------------------------- - call PopulateWindFileDatFromGridField(GF, InitInp%WindFileName(1), 5, .false., FileDat) + call PopulateWindFileDatFromGrid3DField(GF, InitInp%WindFileName(1), 5, .false., FileDat) !---------------------------------------------------------------------------- ! Write the summary file @@ -1119,17 +1124,17 @@ subroutine User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) end subroutine -!> ExtGrid_Init initializes a wind field defined by a 4D grid. -subroutine ExtGrid_Init(InitInp, SumFileUnit, EGF, FileDat, ErrStat, ErrMsg) +!> Grid4D_Init initializes a wind field defined by a 4D grid. +subroutine Grid4D_Init(InitInp, SumFileUnit, EGF, FileDat, ErrStat, ErrMsg) - type(ExtGridInitInputType), intent(in) :: InitInp + type(Grid4DInitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit - type(ExtGridFieldType), intent(out) :: EGF + type(Grid4DFieldType), intent(out) :: EGF type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = "ExtGrid_Init" + character(*), parameter :: RoutineName = "Grid4D_Init" integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg @@ -1157,9 +1162,9 @@ subroutine ExtGrid_Init(InitInp, SumFileUnit, EGF, FileDat, ErrStat, ErrMsg) end subroutine -subroutine PopulateWindFileDatFromGridField(GridField, FileName, WindType, HasTower, FileDat) +subroutine PopulateWindFileDatFromGrid3DField(Grid3DField, FileName, WindType, HasTower, FileDat) - type(GridFieldType), intent(in) :: GridField + type(Grid3DFieldType), intent(in) :: Grid3DField character(*), intent(in) :: FileName integer(IntKi), intent(in) :: WindType logical, intent(in) :: HasTower @@ -1167,34 +1172,34 @@ subroutine PopulateWindFileDatFromGridField(GridField, FileName, WindType, HasTo FileDat%FileName = FileName FileDat%WindType = WindType - FileDat%RefHt = GridField%RefHeight + FileDat%RefHt = Grid3DField%RefHeight FileDat%RefHt_Set = .true. - FileDat%DT = GridField%DTime - FileDat%NumTSteps = GridField%NSteps + FileDat%DT = Grid3DField%DTime + FileDat%NumTSteps = Grid3DField%NSteps FileDat%ConstantDT = .true. - if (GridField%Periodic) then - FileDat%TRange = [0.0_ReKi, GridField%TotalTime] + if (Grid3DField%Periodic) then + FileDat%TRange = [0.0_ReKi, Grid3DField%TotalTime] FileDat%TRange_Limited = .false. else ! Shift the time range to compensate for the shifting of the wind grid - FileDat%TRange = [0.0_ReKi, GridField%TotalTime] - GridField%InitXPosition*GridField%InvMWS + FileDat%TRange = [0.0_ReKi, Grid3DField%TotalTime] - Grid3DField%InitXPosition*Grid3DField%InvMWS FileDat%TRange_Limited = .true. end if - FileDat%YRange = [-GridField%YHWid, GridField%YHWid] + FileDat%YRange = [-Grid3DField%YHWid, Grid3DField%YHWid] FileDat%YRange_Limited = .true. ! Hard boundaries enforced in y-direction ! If has tower data if (HasTower) then - FileDat%ZRange = [0.0_Reki, GridField%RefHeight + GridField%ZHWid] + FileDat%ZRange = [0.0_Reki, Grid3DField%RefHeight + Grid3DField%ZHWid] else - FileDat%ZRange = [GridField%GridBase, GridField%GridBase + GridField%ZHWid*2.0] + FileDat%ZRange = [Grid3DField%GridBase, Grid3DField%GridBase + Grid3DField%ZHWid*2.0] end if FileDat%ZRange_Limited = .true. - FileDat%BinaryFormat = GridField%WindFileFormat + FileDat%BinaryFormat = Grid3DField%WindFileFormat FileDat%IsBinary = .true. - FileDat%MWS = GridField%MeanWS + FileDat%MWS = Grid3DField%MeanWS FileDat%TI = 0.0_ReKi FileDat%TI_listed = .false. diff --git a/modules/inflowwind/src/FlowField_IO.txt b/modules/inflowwind/src/FlowField_IO.txt index 4e84545480..5988f428a9 100644 --- a/modules/inflowwind/src/FlowField_IO.txt +++ b/modules/inflowwind/src/FlowField_IO.txt @@ -57,17 +57,17 @@ typedef ^ ^ ReKi XOffset typedef ^ UserInitInputType SiKi Dummy - - - "User field initialization input dummy value" - -typedef ^ ExtGridInitInputType IntKi n 4 - - "number of grid points in the x, y, z, and t directions" - +typedef ^ Grid4DInitInputType IntKi n 4 - - "number of grid points in the x, y, z, and t directions" - typedef ^ ^ ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" -typedef ^ ExtPointInitInputType IntKi Dummy - - - "External Point field initialization input dummy value" - +typedef ^ PointsInitInputType IntKi Dummy - - - "Point field initialization input dummy value" - typedef ^ InitInputType IntKi WindType - 0 - "Type of the windfile" - typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" - -typedef ^ ^ IntKi VelInterpOrder - 0 - "Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7]" - +typedef ^ ^ logical VelInterpCubic - .false. - "Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7]" - typedef ^ ^ logical CalcAccel - .false. - "Flag to calculate acceleration data" - typedef ^ ^ SteadyInitInputType Steady - - - "" - typedef ^ ^ UniformInitInputType Uniform - - - "" - @@ -75,8 +75,8 @@ typedef ^ ^ TurbSimInitInputType TurbSim typedef ^ ^ BladedInitInputType Bladed - - - "" - typedef ^ ^ HAWCInitInputType HAWC - - - "" - typedef ^ ^ UserInitInputType User - - - "" - -typedef ^ ^ ExtGridInitInputType ExtGrid - - - "" - -typedef ^ ^ ExtPointInitInputType ExtPoint - - - "" - +typedef ^ ^ Grid4DInitInputType Grid4D - - - "" - +typedef ^ ^ PointsInitInputType Points - - - "" - typedef ^ WindFileDat character(1024) FileName - - - "Name of the windfile retrieved" - typedef ^ ^ IntKi WindType - 0 - "Type of the windfile" - diff --git a/modules/inflowwind/src/FlowField_IO_Types.f90 b/modules/inflowwind/src/FlowField_IO_Types.f90 index 667b4c3c45..b72058398f 100644 --- a/modules/inflowwind/src/FlowField_IO_Types.f90 +++ b/modules/inflowwind/src/FlowField_IO_Types.f90 @@ -126,17 +126,17 @@ MODULE FlowField_IO_Types REAL(SiKi) :: Dummy !< User field initialization input dummy value [-] END TYPE UserInitInputType ! ======================= -! ========= ExtGridInitInputType ======= - TYPE, PUBLIC :: ExtGridInitInputType +! ========= Grid4DInitInputType ======= + TYPE, PUBLIC :: Grid4DInitInputType INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of grid points in the x, y, z, and t directions [-] REAL(ReKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s] REAL(ReKi) , DIMENSION(1:3) :: pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:)) [m] - END TYPE ExtGridInitInputType + END TYPE Grid4DInitInputType ! ======================= -! ========= ExtPointInitInputType ======= - TYPE, PUBLIC :: ExtPointInitInputType - INTEGER(IntKi) :: Dummy !< External Point field initialization input dummy value [-] - END TYPE ExtPointInitInputType +! ========= PointsInitInputType ======= + TYPE, PUBLIC :: PointsInitInputType + INTEGER(IntKi) :: Dummy !< Point field initialization input dummy value [-] + END TYPE PointsInitInputType ! ======================= ! ========= FlowField_IO_InitInputType ======= TYPE, PUBLIC :: FlowField_IO_InitInputType @@ -144,7 +144,7 @@ MODULE FlowField_IO_Types INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file (-1 for none). Provided by IfW. [-] REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [-] - INTEGER(IntKi) :: VelInterpOrder = 0 !< Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] [-] + LOGICAL :: VelInterpCubic = .false. !< Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7] [-] LOGICAL :: CalcAccel = .false. !< Flag to calculate acceleration data [-] TYPE(SteadyInitInputType) :: Steady !< [-] TYPE(UniformInitInputType) :: Uniform !< [-] @@ -152,8 +152,8 @@ MODULE FlowField_IO_Types TYPE(BladedInitInputType) :: Bladed !< [-] TYPE(HAWCInitInputType) :: HAWC !< [-] TYPE(UserInitInputType) :: User !< [-] - TYPE(ExtGridInitInputType) :: ExtGrid !< [-] - TYPE(ExtPointInitInputType) :: ExtPoint !< [-] + TYPE(Grid4DInitInputType) :: Grid4D !< [-] + TYPE(PointsInitInputType) :: Points !< [-] END TYPE FlowField_IO_InitInputType ! ======================= ! ========= WindFileDat ======= @@ -2325,9 +2325,9 @@ SUBROUTINE FlowField_IO_UnPackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Out Re_Xferred = Re_Xferred + 1 END SUBROUTINE FlowField_IO_UnPackUserInitInputType - SUBROUTINE FlowField_IO_CopyExtGridInitInputType( SrcExtGridInitInputTypeData, DstExtGridInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(ExtGridInitInputType), INTENT(IN) :: SrcExtGridInitInputTypeData - TYPE(ExtGridInitInputType), INTENT(INOUT) :: DstExtGridInitInputTypeData + SUBROUTINE FlowField_IO_CopyGrid4DInitInputType( SrcGrid4DInitInputTypeData, DstGrid4DInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Grid4DInitInputType), INTENT(IN) :: SrcGrid4DInitInputTypeData + TYPE(Grid4DInitInputType), INTENT(INOUT) :: DstGrid4DInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2336,17 +2336,17 @@ SUBROUTINE FlowField_IO_CopyExtGridInitInputType( SrcExtGridInitInputTypeData, D INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyExtGridInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyGrid4DInitInputType' ! ErrStat = ErrID_None ErrMsg = "" - DstExtGridInitInputTypeData%n = SrcExtGridInitInputTypeData%n - DstExtGridInitInputTypeData%delta = SrcExtGridInitInputTypeData%delta - DstExtGridInitInputTypeData%pZero = SrcExtGridInitInputTypeData%pZero - END SUBROUTINE FlowField_IO_CopyExtGridInitInputType + DstGrid4DInitInputTypeData%n = SrcGrid4DInitInputTypeData%n + DstGrid4DInitInputTypeData%delta = SrcGrid4DInitInputTypeData%delta + DstGrid4DInitInputTypeData%pZero = SrcGrid4DInitInputTypeData%pZero + END SUBROUTINE FlowField_IO_CopyGrid4DInitInputType - SUBROUTINE FlowField_IO_DestroyExtGridInitInputType( ExtGridInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(ExtGridInitInputType), INTENT(INOUT) :: ExtGridInitInputTypeData + SUBROUTINE FlowField_IO_DestroyGrid4DInitInputType( Grid4DInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Grid4DInitInputType), INTENT(INOUT) :: Grid4DInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -2355,7 +2355,7 @@ SUBROUTINE FlowField_IO_DestroyExtGridInitInputType( ExtGridInitInputTypeData, E LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyExtGridInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyGrid4DInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -2366,13 +2366,13 @@ SUBROUTINE FlowField_IO_DestroyExtGridInitInputType( ExtGridInitInputTypeData, E DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE FlowField_IO_DestroyExtGridInitInputType + END SUBROUTINE FlowField_IO_DestroyGrid4DInitInputType - SUBROUTINE FlowField_IO_PackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackGrid4DInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(ExtGridInitInputType), INTENT(IN) :: InData + TYPE(Grid4DInitInputType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -2387,7 +2387,7 @@ SUBROUTINE FlowField_IO_PackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, In LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackExtGridInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackGrid4DInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2445,13 +2445,13 @@ SUBROUTINE FlowField_IO_PackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, In ReKiBuf(Re_Xferred) = InData%pZero(i1) Re_Xferred = Re_Xferred + 1 END DO - END SUBROUTINE FlowField_IO_PackExtGridInitInputType + END SUBROUTINE FlowField_IO_PackGrid4DInitInputType - SUBROUTINE FlowField_IO_UnPackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackGrid4DInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(ExtGridInitInputType), INTENT(INOUT) :: OutData + TYPE(Grid4DInitInputType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -2463,7 +2463,7 @@ SUBROUTINE FlowField_IO_UnPackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackExtGridInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackGrid4DInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2492,11 +2492,11 @@ SUBROUTINE FlowField_IO_UnPackExtGridInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, OutData%pZero(i1) = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 END DO - END SUBROUTINE FlowField_IO_UnPackExtGridInitInputType + END SUBROUTINE FlowField_IO_UnPackGrid4DInitInputType - SUBROUTINE FlowField_IO_CopyExtPointInitInputType( SrcExtPointInitInputTypeData, DstExtPointInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(ExtPointInitInputType), INTENT(IN) :: SrcExtPointInitInputTypeData - TYPE(ExtPointInitInputType), INTENT(INOUT) :: DstExtPointInitInputTypeData + SUBROUTINE FlowField_IO_CopyPointsInitInputType( SrcPointsInitInputTypeData, DstPointsInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(PointsInitInputType), INTENT(IN) :: SrcPointsInitInputTypeData + TYPE(PointsInitInputType), INTENT(INOUT) :: DstPointsInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2504,15 +2504,15 @@ SUBROUTINE FlowField_IO_CopyExtPointInitInputType( SrcExtPointInitInputTypeData, INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyExtPointInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyPointsInitInputType' ! ErrStat = ErrID_None ErrMsg = "" - DstExtPointInitInputTypeData%Dummy = SrcExtPointInitInputTypeData%Dummy - END SUBROUTINE FlowField_IO_CopyExtPointInitInputType + DstPointsInitInputTypeData%Dummy = SrcPointsInitInputTypeData%Dummy + END SUBROUTINE FlowField_IO_CopyPointsInitInputType - SUBROUTINE FlowField_IO_DestroyExtPointInitInputType( ExtPointInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(ExtPointInitInputType), INTENT(INOUT) :: ExtPointInitInputTypeData + SUBROUTINE FlowField_IO_DestroyPointsInitInputType( PointsInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(PointsInitInputType), INTENT(INOUT) :: PointsInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -2521,7 +2521,7 @@ SUBROUTINE FlowField_IO_DestroyExtPointInitInputType( ExtPointInitInputTypeData, LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyExtPointInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyPointsInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -2532,13 +2532,13 @@ SUBROUTINE FlowField_IO_DestroyExtPointInitInputType( ExtPointInitInputTypeData, DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE FlowField_IO_DestroyExtPointInitInputType + END SUBROUTINE FlowField_IO_DestroyPointsInitInputType - SUBROUTINE FlowField_IO_PackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackPointsInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(ExtPointInitInputType), INTENT(IN) :: InData + TYPE(PointsInitInputType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -2553,7 +2553,7 @@ SUBROUTINE FlowField_IO_PackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackExtPointInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackPointsInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2599,13 +2599,13 @@ SUBROUTINE FlowField_IO_PackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I IntKiBuf(Int_Xferred) = InData%Dummy Int_Xferred = Int_Xferred + 1 - END SUBROUTINE FlowField_IO_PackExtPointInitInputType + END SUBROUTINE FlowField_IO_PackPointsInitInputType - SUBROUTINE FlowField_IO_UnPackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackPointsInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(ExtPointInitInputType), INTENT(INOUT) :: OutData + TYPE(PointsInitInputType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -2616,7 +2616,7 @@ SUBROUTINE FlowField_IO_UnPackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackExtPointInitInputType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackPointsInitInputType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2629,7 +2629,7 @@ SUBROUTINE FlowField_IO_UnPackExtPointInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Int_Xferred = 1 OutData%Dummy = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackExtPointInitInputType + END SUBROUTINE FlowField_IO_UnPackPointsInitInputType SUBROUTINE FlowField_IO_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) TYPE(FlowField_IO_InitInputType), INTENT(IN) :: SrcInitInputData @@ -2649,7 +2649,7 @@ SUBROUTINE FlowField_IO_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlC DstInitInputData%SumFileUnit = SrcInitInputData%SumFileUnit DstInitInputData%PropagationDir = SrcInitInputData%PropagationDir DstInitInputData%VFlowAngle = SrcInitInputData%VFlowAngle - DstInitInputData%VelInterpOrder = SrcInitInputData%VelInterpOrder + DstInitInputData%VelInterpCubic = SrcInitInputData%VelInterpCubic DstInitInputData%CalcAccel = SrcInitInputData%CalcAccel CALL FlowField_IO_Copysteadyinitinputtype( SrcInitInputData%Steady, DstInitInputData%Steady, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) @@ -2669,10 +2669,10 @@ SUBROUTINE FlowField_IO_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlC CALL FlowField_IO_Copyuserinitinputtype( SrcInitInputData%User, DstInitInputData%User, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copyextgridinitinputtype( SrcInitInputData%ExtGrid, DstInitInputData%ExtGrid, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copygrid4dinitinputtype( SrcInitInputData%Grid4D, DstInitInputData%Grid4D, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copyextpointinitinputtype( SrcInitInputData%ExtPoint, DstInitInputData%ExtPoint, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_IO_Copypointsinitinputtype( SrcInitInputData%Points, DstInitInputData%Points, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE FlowField_IO_CopyInitInput @@ -2710,9 +2710,9 @@ SUBROUTINE FlowField_IO_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLO CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL FlowField_IO_Destroyuserinitinputtype( InitInputData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroyextgridinitinputtype( InitInputData%ExtGrid, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroygrid4dinitinputtype( InitInputData%Grid4D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroyextpointinitinputtype( InitInputData%ExtPoint, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_IO_Destroypointsinitinputtype( InitInputData%Points, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE FlowField_IO_DestroyInitInput @@ -2755,7 +2755,7 @@ SUBROUTINE FlowField_IO_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt Int_BufSz = Int_BufSz + 1 ! SumFileUnit Re_BufSz = Re_BufSz + 1 ! PropagationDir Re_BufSz = Re_BufSz + 1 ! VFlowAngle - Int_BufSz = Int_BufSz + 1 ! VelInterpOrder + Int_BufSz = Int_BufSz + 1 ! VelInterpCubic Int_BufSz = Int_BufSz + 1 ! CalcAccel ! Allocate buffers for subtypes, if any (we'll get sizes from these) Int_BufSz = Int_BufSz + 3 ! Steady: size of buffers for each call to pack subtype @@ -2860,37 +2860,37 @@ SUBROUTINE FlowField_IO_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! ExtGrid: size of buffers for each call to pack subtype - CALL FlowField_IO_Packextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, .TRUE. ) ! ExtGrid + Int_BufSz = Int_BufSz + 3 ! Grid4D: size of buffers for each call to pack subtype + CALL FlowField_IO_Packgrid4dinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! ExtGrid + IF(ALLOCATED(Re_Buf)) THEN ! Grid4D Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! ExtGrid + IF(ALLOCATED(Db_Buf)) THEN ! Grid4D Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! ExtGrid + IF(ALLOCATED(Int_Buf)) THEN ! Grid4D Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! ExtPoint: size of buffers for each call to pack subtype - CALL FlowField_IO_Packextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, .TRUE. ) ! ExtPoint + Int_BufSz = Int_BufSz + 3 ! Points: size of buffers for each call to pack subtype + CALL FlowField_IO_Packpointsinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, .TRUE. ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! ExtPoint + IF(ALLOCATED(Re_Buf)) THEN ! Points Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! ExtPoint + IF(ALLOCATED(Db_Buf)) THEN ! Points Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! ExtPoint + IF(ALLOCATED(Int_Buf)) THEN ! Points Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -2929,7 +2929,7 @@ SUBROUTINE FlowField_IO_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VFlowAngle Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%VelInterpOrder + IntKiBuf(Int_Xferred) = TRANSFER(InData%VelInterpCubic, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%CalcAccel, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 @@ -3101,7 +3101,7 @@ SUBROUTINE FlowField_IO_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_IO_Packextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, OnlySize ) ! ExtGrid + CALL FlowField_IO_Packgrid4dinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, OnlySize ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3129,7 +3129,7 @@ SUBROUTINE FlowField_IO_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_IO_Packextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, OnlySize ) ! ExtPoint + CALL FlowField_IO_Packpointsinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, OnlySize ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3193,7 +3193,7 @@ SUBROUTINE FlowField_IO_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Er Re_Xferred = Re_Xferred + 1 OutData%VFlowAngle = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%VelInterpOrder = IntKiBuf(Int_Xferred) + OutData%VelInterpCubic = TRANSFER(IntKiBuf(Int_Xferred), OutData%VelInterpCubic) Int_Xferred = Int_Xferred + 1 OutData%CalcAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%CalcAccel) Int_Xferred = Int_Xferred + 1 @@ -3470,7 +3470,7 @@ SUBROUTINE FlowField_IO_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Er Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_IO_Unpackextgridinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtGrid, ErrStat2, ErrMsg2 ) ! ExtGrid + CALL FlowField_IO_Unpackgrid4dinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid4D, ErrStat2, ErrMsg2 ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3510,7 +3510,7 @@ SUBROUTINE FlowField_IO_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Er Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_IO_Unpackextpointinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtPoint, ErrStat2, ErrMsg2 ) ! ExtPoint + CALL FlowField_IO_Unpackpointsinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Points, ErrStat2, ErrMsg2 ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN diff --git a/modules/inflowwind/src/FlowField_Types.f90 b/modules/inflowwind/src/FlowField_Types.f90 index fd6cb9975b..6b568a86da 100644 --- a/modules/inflowwind/src/FlowField_Types.f90 +++ b/modules/inflowwind/src/FlowField_Types.f90 @@ -35,9 +35,9 @@ MODULE FlowField_Types IMPLICIT NONE INTEGER(IntKi), PUBLIC, PARAMETER :: Undef_FieldType = 0 ! This is the code for an undefined FieldType [-] INTEGER(IntKi), PUBLIC, PARAMETER :: Uniform_FieldType = 1 ! Uniform FieldType from SteadyWind or Uniform Wind [-] - INTEGER(IntKi), PUBLIC, PARAMETER :: Grid_FieldType = 2 ! Grid-Field FieldType from TurbSim, Bladed, HAWC [-] - INTEGER(IntKi), PUBLIC, PARAMETER :: ExtGrid_FieldType = 3 ! External Grid FieldType from OpFM or similar [-] - INTEGER(IntKi), PUBLIC, PARAMETER :: ExtPoint_FieldType = 4 ! External Point FieldType from OpFM or similar [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Grid3D_FieldType = 2 ! 3D Grid FieldType from TurbSim, Bladed, HAWC [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Grid4D_FieldType = 3 ! 4D Grid FieldType from FAST.Farm [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Point_FieldType = 4 ! Points FieldType from ExtInflow [-] INTEGER(IntKi), PUBLIC, PARAMETER :: User_FieldType = 5 ! User FieldType configured by the user [-] ! ========= UniformFieldType ======= TYPE, PUBLIC :: UniformFieldType @@ -87,8 +87,8 @@ MODULE FlowField_Types REAL(ReKi) :: SinAngleV !< Vertical angle components [-] END TYPE UniformField_Interp ! ======================= -! ========= GridFieldType ======= - TYPE, PUBLIC :: GridFieldType +! ========= Grid3DFieldType ======= + TYPE, PUBLIC :: Grid3DFieldType INTEGER(IntKi) :: WindFileFormat !< Binary file format description number [-] INTEGER(IntKi) :: WindProfileType = -1 !< Wind profile type (0=constant;1=logarithmic;2=power law) [-] LOGICAL :: Periodic = .false. !< Flag to indicate if the wind file is periodic [-] @@ -117,26 +117,26 @@ MODULE FlowField_Types INTEGER(IntKi) :: NSteps = 0 !< Number of time steps in the FF array [-] REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] - END TYPE GridFieldType + END TYPE Grid3DFieldType ! ======================= ! ========= UserFieldType ======= TYPE, PUBLIC :: UserFieldType REAL(SiKi) :: Dummy !< [-] END TYPE UserFieldType ! ======================= -! ========= ExtGridFieldType ======= - TYPE, PUBLIC :: ExtGridFieldType +! ========= Grid4DFieldType ======= + TYPE, PUBLIC :: Grid4DFieldType INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of evenly-spaced grid points in the x, y, z, and t directions [-] REAL(ReKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s] REAL(ReKi) , DIMENSION(1:3) :: pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:)) [m] REAL(SiKi) , DIMENSION(:,:,:,:,:), ALLOCATABLE :: Vel !< this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt] [-] REAL(ReKi) :: TimeStart !< this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1)) [s] - END TYPE ExtGridFieldType + END TYPE Grid4DFieldType ! ======================= -! ========= ExtPointFieldType ======= - TYPE, PUBLIC :: ExtPointFieldType +! ========= PointsFieldType ======= + TYPE, PUBLIC :: PointsFieldType REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vel !< Point velocities populated by external driver [uvw,point] [-] - END TYPE ExtPointFieldType + END TYPE PointsFieldType ! ======================= ! ========= FlowFieldType ======= TYPE, PUBLIC :: FlowFieldType @@ -144,15 +144,16 @@ MODULE FlowField_Types REAL(ReKi) , DIMENSION(1:3) :: RefPosition !< Reference position (point where box is rotated) [meters] REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [radians] - INTEGER(IntKi) :: VelInterpOrder = 0 !< Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] [-] + LOGICAL :: VelInterpCubic = .false. !< Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] [-] LOGICAL :: RotateWindBox = .false. !< flag indicating if the wind will be rotated [-] + LOGICAL :: AccFieldValid = .false. !< flag indicating that acceleration field has been calculated [-] REAL(ReKi) , DIMENSION(1:3,1:3) :: RotToWind !< Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X') [-] REAL(ReKi) , DIMENSION(1:3,1:3) :: RotFromWind !< Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind) [-] TYPE(UniformFieldType) :: Uniform !< Uniform Flow Data [-] - TYPE(GridFieldType) :: Grid !< Grid Field Wind Data [-] + TYPE(PointsFieldType) :: Points !< External Point Flow Data [-] + TYPE(Grid3DFieldType) :: Grid3D !< Grid Field Wind Data [-] + TYPE(Grid4DFieldType) :: Grid4D !< External Grid Flow Data [-] TYPE(UserFieldType) :: User !< User Field Wind Data [-] - TYPE(ExtGridFieldType) :: ExtGrid !< External Grid Flow Data [-] - TYPE(ExtPointFieldType) :: ExtPoint !< External Point Flow Data [-] END TYPE FlowFieldType ! ======================= CONTAINS @@ -1467,9 +1468,9 @@ SUBROUTINE FlowField_UnPackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Outd Re_Xferred = Re_Xferred + 1 END SUBROUTINE FlowField_UnPackUniformField_Interp - SUBROUTINE FlowField_CopyGridFieldType( SrcGridFieldTypeData, DstGridFieldTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(GridFieldType), INTENT(IN) :: SrcGridFieldTypeData - TYPE(GridFieldType), INTENT(INOUT) :: DstGridFieldTypeData + SUBROUTINE FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Grid3DFieldType), INTENT(IN) :: SrcGrid3DFieldTypeData + TYPE(Grid3DFieldType), INTENT(INOUT) :: DstGrid3DFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1481,106 +1482,106 @@ SUBROUTINE FlowField_CopyGridFieldType( SrcGridFieldTypeData, DstGridFieldTypeDa INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyGridFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyGrid3DFieldType' ! ErrStat = ErrID_None ErrMsg = "" - DstGridFieldTypeData%WindFileFormat = SrcGridFieldTypeData%WindFileFormat - DstGridFieldTypeData%WindProfileType = SrcGridFieldTypeData%WindProfileType - DstGridFieldTypeData%Periodic = SrcGridFieldTypeData%Periodic - DstGridFieldTypeData%InterpTower = SrcGridFieldTypeData%InterpTower - DstGridFieldTypeData%AddMeanAfterInterp = SrcGridFieldTypeData%AddMeanAfterInterp - DstGridFieldTypeData%RefHeight = SrcGridFieldTypeData%RefHeight -IF (ALLOCATED(SrcGridFieldTypeData%Vel)) THEN - i1_l = LBOUND(SrcGridFieldTypeData%Vel,1) - i1_u = UBOUND(SrcGridFieldTypeData%Vel,1) - i2_l = LBOUND(SrcGridFieldTypeData%Vel,2) - i2_u = UBOUND(SrcGridFieldTypeData%Vel,2) - i3_l = LBOUND(SrcGridFieldTypeData%Vel,3) - i3_u = UBOUND(SrcGridFieldTypeData%Vel,3) - i4_l = LBOUND(SrcGridFieldTypeData%Vel,4) - i4_u = UBOUND(SrcGridFieldTypeData%Vel,4) - IF (.NOT. ALLOCATED(DstGridFieldTypeData%Vel)) THEN - ALLOCATE(DstGridFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) + DstGrid3DFieldTypeData%WindFileFormat = SrcGrid3DFieldTypeData%WindFileFormat + DstGrid3DFieldTypeData%WindProfileType = SrcGrid3DFieldTypeData%WindProfileType + DstGrid3DFieldTypeData%Periodic = SrcGrid3DFieldTypeData%Periodic + DstGrid3DFieldTypeData%InterpTower = SrcGrid3DFieldTypeData%InterpTower + DstGrid3DFieldTypeData%AddMeanAfterInterp = SrcGrid3DFieldTypeData%AddMeanAfterInterp + DstGrid3DFieldTypeData%RefHeight = SrcGrid3DFieldTypeData%RefHeight +IF (ALLOCATED(SrcGrid3DFieldTypeData%Vel)) THEN + i1_l = LBOUND(SrcGrid3DFieldTypeData%Vel,1) + i1_u = UBOUND(SrcGrid3DFieldTypeData%Vel,1) + i2_l = LBOUND(SrcGrid3DFieldTypeData%Vel,2) + i2_u = UBOUND(SrcGrid3DFieldTypeData%Vel,2) + i3_l = LBOUND(SrcGrid3DFieldTypeData%Vel,3) + i3_u = UBOUND(SrcGrid3DFieldTypeData%Vel,3) + i4_l = LBOUND(SrcGrid3DFieldTypeData%Vel,4) + i4_u = UBOUND(SrcGrid3DFieldTypeData%Vel,4) + IF (.NOT. ALLOCATED(DstGrid3DFieldTypeData%Vel)) THEN + ALLOCATE(DstGrid3DFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGridFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGrid3DFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstGridFieldTypeData%Vel = SrcGridFieldTypeData%Vel + DstGrid3DFieldTypeData%Vel = SrcGrid3DFieldTypeData%Vel ENDIF -IF (ALLOCATED(SrcGridFieldTypeData%Acc)) THEN - i1_l = LBOUND(SrcGridFieldTypeData%Acc,1) - i1_u = UBOUND(SrcGridFieldTypeData%Acc,1) - i2_l = LBOUND(SrcGridFieldTypeData%Acc,2) - i2_u = UBOUND(SrcGridFieldTypeData%Acc,2) - i3_l = LBOUND(SrcGridFieldTypeData%Acc,3) - i3_u = UBOUND(SrcGridFieldTypeData%Acc,3) - i4_l = LBOUND(SrcGridFieldTypeData%Acc,4) - i4_u = UBOUND(SrcGridFieldTypeData%Acc,4) - IF (.NOT. ALLOCATED(DstGridFieldTypeData%Acc)) THEN - ALLOCATE(DstGridFieldTypeData%Acc(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) +IF (ALLOCATED(SrcGrid3DFieldTypeData%Acc)) THEN + i1_l = LBOUND(SrcGrid3DFieldTypeData%Acc,1) + i1_u = UBOUND(SrcGrid3DFieldTypeData%Acc,1) + i2_l = LBOUND(SrcGrid3DFieldTypeData%Acc,2) + i2_u = UBOUND(SrcGrid3DFieldTypeData%Acc,2) + i3_l = LBOUND(SrcGrid3DFieldTypeData%Acc,3) + i3_u = UBOUND(SrcGrid3DFieldTypeData%Acc,3) + i4_l = LBOUND(SrcGrid3DFieldTypeData%Acc,4) + i4_u = UBOUND(SrcGrid3DFieldTypeData%Acc,4) + IF (.NOT. ALLOCATED(DstGrid3DFieldTypeData%Acc)) THEN + ALLOCATE(DstGrid3DFieldTypeData%Acc(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGridFieldTypeData%Acc.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGrid3DFieldTypeData%Acc.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstGridFieldTypeData%Acc = SrcGridFieldTypeData%Acc + DstGrid3DFieldTypeData%Acc = SrcGrid3DFieldTypeData%Acc ENDIF -IF (ALLOCATED(SrcGridFieldTypeData%VelTower)) THEN - i1_l = LBOUND(SrcGridFieldTypeData%VelTower,1) - i1_u = UBOUND(SrcGridFieldTypeData%VelTower,1) - i2_l = LBOUND(SrcGridFieldTypeData%VelTower,2) - i2_u = UBOUND(SrcGridFieldTypeData%VelTower,2) - i3_l = LBOUND(SrcGridFieldTypeData%VelTower,3) - i3_u = UBOUND(SrcGridFieldTypeData%VelTower,3) - IF (.NOT. ALLOCATED(DstGridFieldTypeData%VelTower)) THEN - ALLOCATE(DstGridFieldTypeData%VelTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) +IF (ALLOCATED(SrcGrid3DFieldTypeData%VelTower)) THEN + i1_l = LBOUND(SrcGrid3DFieldTypeData%VelTower,1) + i1_u = UBOUND(SrcGrid3DFieldTypeData%VelTower,1) + i2_l = LBOUND(SrcGrid3DFieldTypeData%VelTower,2) + i2_u = UBOUND(SrcGrid3DFieldTypeData%VelTower,2) + i3_l = LBOUND(SrcGrid3DFieldTypeData%VelTower,3) + i3_u = UBOUND(SrcGrid3DFieldTypeData%VelTower,3) + IF (.NOT. ALLOCATED(DstGrid3DFieldTypeData%VelTower)) THEN + ALLOCATE(DstGrid3DFieldTypeData%VelTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGridFieldTypeData%VelTower.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGrid3DFieldTypeData%VelTower.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstGridFieldTypeData%VelTower = SrcGridFieldTypeData%VelTower + DstGrid3DFieldTypeData%VelTower = SrcGrid3DFieldTypeData%VelTower ENDIF -IF (ALLOCATED(SrcGridFieldTypeData%AccTower)) THEN - i1_l = LBOUND(SrcGridFieldTypeData%AccTower,1) - i1_u = UBOUND(SrcGridFieldTypeData%AccTower,1) - i2_l = LBOUND(SrcGridFieldTypeData%AccTower,2) - i2_u = UBOUND(SrcGridFieldTypeData%AccTower,2) - i3_l = LBOUND(SrcGridFieldTypeData%AccTower,3) - i3_u = UBOUND(SrcGridFieldTypeData%AccTower,3) - IF (.NOT. ALLOCATED(DstGridFieldTypeData%AccTower)) THEN - ALLOCATE(DstGridFieldTypeData%AccTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) +IF (ALLOCATED(SrcGrid3DFieldTypeData%AccTower)) THEN + i1_l = LBOUND(SrcGrid3DFieldTypeData%AccTower,1) + i1_u = UBOUND(SrcGrid3DFieldTypeData%AccTower,1) + i2_l = LBOUND(SrcGrid3DFieldTypeData%AccTower,2) + i2_u = UBOUND(SrcGrid3DFieldTypeData%AccTower,2) + i3_l = LBOUND(SrcGrid3DFieldTypeData%AccTower,3) + i3_u = UBOUND(SrcGrid3DFieldTypeData%AccTower,3) + IF (.NOT. ALLOCATED(DstGrid3DFieldTypeData%AccTower)) THEN + ALLOCATE(DstGrid3DFieldTypeData%AccTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGridFieldTypeData%AccTower.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGrid3DFieldTypeData%AccTower.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstGridFieldTypeData%AccTower = SrcGridFieldTypeData%AccTower + DstGrid3DFieldTypeData%AccTower = SrcGrid3DFieldTypeData%AccTower ENDIF - DstGridFieldTypeData%DTime = SrcGridFieldTypeData%DTime - DstGridFieldTypeData%Rate = SrcGridFieldTypeData%Rate - DstGridFieldTypeData%YHWid = SrcGridFieldTypeData%YHWid - DstGridFieldTypeData%ZHWid = SrcGridFieldTypeData%ZHWid - DstGridFieldTypeData%GridBase = SrcGridFieldTypeData%GridBase - DstGridFieldTypeData%InitXPosition = SrcGridFieldTypeData%InitXPosition - DstGridFieldTypeData%InvDY = SrcGridFieldTypeData%InvDY - DstGridFieldTypeData%InvDZ = SrcGridFieldTypeData%InvDZ - DstGridFieldTypeData%MeanWS = SrcGridFieldTypeData%MeanWS - DstGridFieldTypeData%InvMWS = SrcGridFieldTypeData%InvMWS - DstGridFieldTypeData%TotalTime = SrcGridFieldTypeData%TotalTime - DstGridFieldTypeData%NComp = SrcGridFieldTypeData%NComp - DstGridFieldTypeData%NYGrids = SrcGridFieldTypeData%NYGrids - DstGridFieldTypeData%NZGrids = SrcGridFieldTypeData%NZGrids - DstGridFieldTypeData%NTGrids = SrcGridFieldTypeData%NTGrids - DstGridFieldTypeData%NSteps = SrcGridFieldTypeData%NSteps - DstGridFieldTypeData%PLExp = SrcGridFieldTypeData%PLExp - DstGridFieldTypeData%Z0 = SrcGridFieldTypeData%Z0 - END SUBROUTINE FlowField_CopyGridFieldType - - SUBROUTINE FlowField_DestroyGridFieldType( GridFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(GridFieldType), INTENT(INOUT) :: GridFieldTypeData + DstGrid3DFieldTypeData%DTime = SrcGrid3DFieldTypeData%DTime + DstGrid3DFieldTypeData%Rate = SrcGrid3DFieldTypeData%Rate + DstGrid3DFieldTypeData%YHWid = SrcGrid3DFieldTypeData%YHWid + DstGrid3DFieldTypeData%ZHWid = SrcGrid3DFieldTypeData%ZHWid + DstGrid3DFieldTypeData%GridBase = SrcGrid3DFieldTypeData%GridBase + DstGrid3DFieldTypeData%InitXPosition = SrcGrid3DFieldTypeData%InitXPosition + DstGrid3DFieldTypeData%InvDY = SrcGrid3DFieldTypeData%InvDY + DstGrid3DFieldTypeData%InvDZ = SrcGrid3DFieldTypeData%InvDZ + DstGrid3DFieldTypeData%MeanWS = SrcGrid3DFieldTypeData%MeanWS + DstGrid3DFieldTypeData%InvMWS = SrcGrid3DFieldTypeData%InvMWS + DstGrid3DFieldTypeData%TotalTime = SrcGrid3DFieldTypeData%TotalTime + DstGrid3DFieldTypeData%NComp = SrcGrid3DFieldTypeData%NComp + DstGrid3DFieldTypeData%NYGrids = SrcGrid3DFieldTypeData%NYGrids + DstGrid3DFieldTypeData%NZGrids = SrcGrid3DFieldTypeData%NZGrids + DstGrid3DFieldTypeData%NTGrids = SrcGrid3DFieldTypeData%NTGrids + DstGrid3DFieldTypeData%NSteps = SrcGrid3DFieldTypeData%NSteps + DstGrid3DFieldTypeData%PLExp = SrcGrid3DFieldTypeData%PLExp + DstGrid3DFieldTypeData%Z0 = SrcGrid3DFieldTypeData%Z0 + END SUBROUTINE FlowField_CopyGrid3DFieldType + + SUBROUTINE FlowField_DestroyGrid3DFieldType( Grid3DFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Grid3DFieldType), INTENT(INOUT) :: Grid3DFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -1589,7 +1590,7 @@ SUBROUTINE FlowField_DestroyGridFieldType( GridFieldTypeData, ErrStat, ErrMsg, D LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyGridFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyGrid3DFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -1600,25 +1601,25 @@ SUBROUTINE FlowField_DestroyGridFieldType( GridFieldTypeData, ErrStat, ErrMsg, D DEALLOCATEpointers_local = .true. END IF -IF (ALLOCATED(GridFieldTypeData%Vel)) THEN - DEALLOCATE(GridFieldTypeData%Vel) +IF (ALLOCATED(Grid3DFieldTypeData%Vel)) THEN + DEALLOCATE(Grid3DFieldTypeData%Vel) ENDIF -IF (ALLOCATED(GridFieldTypeData%Acc)) THEN - DEALLOCATE(GridFieldTypeData%Acc) +IF (ALLOCATED(Grid3DFieldTypeData%Acc)) THEN + DEALLOCATE(Grid3DFieldTypeData%Acc) ENDIF -IF (ALLOCATED(GridFieldTypeData%VelTower)) THEN - DEALLOCATE(GridFieldTypeData%VelTower) +IF (ALLOCATED(Grid3DFieldTypeData%VelTower)) THEN + DEALLOCATE(Grid3DFieldTypeData%VelTower) ENDIF -IF (ALLOCATED(GridFieldTypeData%AccTower)) THEN - DEALLOCATE(GridFieldTypeData%AccTower) +IF (ALLOCATED(Grid3DFieldTypeData%AccTower)) THEN + DEALLOCATE(Grid3DFieldTypeData%AccTower) ENDIF - END SUBROUTINE FlowField_DestroyGridFieldType + END SUBROUTINE FlowField_DestroyGrid3DFieldType - SUBROUTINE FlowField_PackGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(GridFieldType), INTENT(IN) :: InData + TYPE(Grid3DFieldType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -1633,7 +1634,7 @@ SUBROUTINE FlowField_PackGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackGridFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackGrid3DFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1878,13 +1879,13 @@ SUBROUTINE FlowField_PackGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%Z0 Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_PackGridFieldType + END SUBROUTINE FlowField_PackGrid3DFieldType - SUBROUTINE FlowField_UnPackGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(GridFieldType), INTENT(INOUT) :: OutData + TYPE(Grid3DFieldType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -1899,7 +1900,7 @@ SUBROUTINE FlowField_UnPackGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackGridFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackGrid3DFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2080,7 +2081,7 @@ SUBROUTINE FlowField_UnPackGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Re_Xferred = Re_Xferred + 1 OutData%Z0 = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_UnPackGridFieldType + END SUBROUTINE FlowField_UnPackGrid3DFieldType SUBROUTINE FlowField_CopyUserFieldType( SrcUserFieldTypeData, DstUserFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(UserFieldType), INTENT(IN) :: SrcUserFieldTypeData @@ -2219,9 +2220,9 @@ SUBROUTINE FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Re_Xferred = Re_Xferred + 1 END SUBROUTINE FlowField_UnPackUserFieldType - SUBROUTINE FlowField_CopyExtGridFieldType( SrcExtGridFieldTypeData, DstExtGridFieldTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(ExtGridFieldType), INTENT(IN) :: SrcExtGridFieldTypeData - TYPE(ExtGridFieldType), INTENT(INOUT) :: DstExtGridFieldTypeData + SUBROUTINE FlowField_CopyGrid4DFieldType( SrcGrid4DFieldTypeData, DstGrid4DFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Grid4DFieldType), INTENT(IN) :: SrcGrid4DFieldTypeData + TYPE(Grid4DFieldType), INTENT(INOUT) :: DstGrid4DFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2234,38 +2235,38 @@ SUBROUTINE FlowField_CopyExtGridFieldType( SrcExtGridFieldTypeData, DstExtGridFi INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyExtGridFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyGrid4DFieldType' ! ErrStat = ErrID_None ErrMsg = "" - DstExtGridFieldTypeData%n = SrcExtGridFieldTypeData%n - DstExtGridFieldTypeData%delta = SrcExtGridFieldTypeData%delta - DstExtGridFieldTypeData%pZero = SrcExtGridFieldTypeData%pZero -IF (ALLOCATED(SrcExtGridFieldTypeData%Vel)) THEN - i1_l = LBOUND(SrcExtGridFieldTypeData%Vel,1) - i1_u = UBOUND(SrcExtGridFieldTypeData%Vel,1) - i2_l = LBOUND(SrcExtGridFieldTypeData%Vel,2) - i2_u = UBOUND(SrcExtGridFieldTypeData%Vel,2) - i3_l = LBOUND(SrcExtGridFieldTypeData%Vel,3) - i3_u = UBOUND(SrcExtGridFieldTypeData%Vel,3) - i4_l = LBOUND(SrcExtGridFieldTypeData%Vel,4) - i4_u = UBOUND(SrcExtGridFieldTypeData%Vel,4) - i5_l = LBOUND(SrcExtGridFieldTypeData%Vel,5) - i5_u = UBOUND(SrcExtGridFieldTypeData%Vel,5) - IF (.NOT. ALLOCATED(DstExtGridFieldTypeData%Vel)) THEN - ALLOCATE(DstExtGridFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u,i5_l:i5_u),STAT=ErrStat2) + DstGrid4DFieldTypeData%n = SrcGrid4DFieldTypeData%n + DstGrid4DFieldTypeData%delta = SrcGrid4DFieldTypeData%delta + DstGrid4DFieldTypeData%pZero = SrcGrid4DFieldTypeData%pZero +IF (ALLOCATED(SrcGrid4DFieldTypeData%Vel)) THEN + i1_l = LBOUND(SrcGrid4DFieldTypeData%Vel,1) + i1_u = UBOUND(SrcGrid4DFieldTypeData%Vel,1) + i2_l = LBOUND(SrcGrid4DFieldTypeData%Vel,2) + i2_u = UBOUND(SrcGrid4DFieldTypeData%Vel,2) + i3_l = LBOUND(SrcGrid4DFieldTypeData%Vel,3) + i3_u = UBOUND(SrcGrid4DFieldTypeData%Vel,3) + i4_l = LBOUND(SrcGrid4DFieldTypeData%Vel,4) + i4_u = UBOUND(SrcGrid4DFieldTypeData%Vel,4) + i5_l = LBOUND(SrcGrid4DFieldTypeData%Vel,5) + i5_u = UBOUND(SrcGrid4DFieldTypeData%Vel,5) + IF (.NOT. ALLOCATED(DstGrid4DFieldTypeData%Vel)) THEN + ALLOCATE(DstGrid4DFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u,i5_l:i5_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstExtGridFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGrid4DFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstExtGridFieldTypeData%Vel = SrcExtGridFieldTypeData%Vel + DstGrid4DFieldTypeData%Vel = SrcGrid4DFieldTypeData%Vel ENDIF - DstExtGridFieldTypeData%TimeStart = SrcExtGridFieldTypeData%TimeStart - END SUBROUTINE FlowField_CopyExtGridFieldType + DstGrid4DFieldTypeData%TimeStart = SrcGrid4DFieldTypeData%TimeStart + END SUBROUTINE FlowField_CopyGrid4DFieldType - SUBROUTINE FlowField_DestroyExtGridFieldType( ExtGridFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(ExtGridFieldType), INTENT(INOUT) :: ExtGridFieldTypeData + SUBROUTINE FlowField_DestroyGrid4DFieldType( Grid4DFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Grid4DFieldType), INTENT(INOUT) :: Grid4DFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -2274,7 +2275,7 @@ SUBROUTINE FlowField_DestroyExtGridFieldType( ExtGridFieldTypeData, ErrStat, Err LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyExtGridFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyGrid4DFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -2285,16 +2286,16 @@ SUBROUTINE FlowField_DestroyExtGridFieldType( ExtGridFieldTypeData, ErrStat, Err DEALLOCATEpointers_local = .true. END IF -IF (ALLOCATED(ExtGridFieldTypeData%Vel)) THEN - DEALLOCATE(ExtGridFieldTypeData%Vel) +IF (ALLOCATED(Grid4DFieldTypeData%Vel)) THEN + DEALLOCATE(Grid4DFieldTypeData%Vel) ENDIF - END SUBROUTINE FlowField_DestroyExtGridFieldType + END SUBROUTINE FlowField_DestroyGrid4DFieldType - SUBROUTINE FlowField_PackExtGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_PackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(ExtGridFieldType), INTENT(IN) :: InData + TYPE(Grid4DFieldType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -2309,7 +2310,7 @@ SUBROUTINE FlowField_PackExtGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackExtGridFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackGrid4DFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2410,13 +2411,13 @@ SUBROUTINE FlowField_PackExtGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E END IF ReKiBuf(Re_Xferred) = InData%TimeStart Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_PackExtGridFieldType + END SUBROUTINE FlowField_PackGrid4DFieldType - SUBROUTINE FlowField_UnPackExtGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_UnPackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(ExtGridFieldType), INTENT(INOUT) :: OutData + TYPE(Grid4DFieldType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -2432,7 +2433,7 @@ SUBROUTINE FlowField_UnPackExtGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackExtGridFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackGrid4DFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2501,11 +2502,11 @@ SUBROUTINE FlowField_UnPackExtGridFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata END IF OutData%TimeStart = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_UnPackExtGridFieldType + END SUBROUTINE FlowField_UnPackGrid4DFieldType - SUBROUTINE FlowField_CopyExtPointFieldType( SrcExtPointFieldTypeData, DstExtPointFieldTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(ExtPointFieldType), INTENT(IN) :: SrcExtPointFieldTypeData - TYPE(ExtPointFieldType), INTENT(INOUT) :: DstExtPointFieldTypeData + SUBROUTINE FlowField_CopyPointsFieldType( SrcPointsFieldTypeData, DstPointsFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(PointsFieldType), INTENT(IN) :: SrcPointsFieldTypeData + TYPE(PointsFieldType), INTENT(INOUT) :: DstPointsFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2515,28 +2516,28 @@ SUBROUTINE FlowField_CopyExtPointFieldType( SrcExtPointFieldTypeData, DstExtPoin INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyExtPointFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyPointsFieldType' ! ErrStat = ErrID_None ErrMsg = "" -IF (ALLOCATED(SrcExtPointFieldTypeData%Vel)) THEN - i1_l = LBOUND(SrcExtPointFieldTypeData%Vel,1) - i1_u = UBOUND(SrcExtPointFieldTypeData%Vel,1) - i2_l = LBOUND(SrcExtPointFieldTypeData%Vel,2) - i2_u = UBOUND(SrcExtPointFieldTypeData%Vel,2) - IF (.NOT. ALLOCATED(DstExtPointFieldTypeData%Vel)) THEN - ALLOCATE(DstExtPointFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) +IF (ALLOCATED(SrcPointsFieldTypeData%Vel)) THEN + i1_l = LBOUND(SrcPointsFieldTypeData%Vel,1) + i1_u = UBOUND(SrcPointsFieldTypeData%Vel,1) + i2_l = LBOUND(SrcPointsFieldTypeData%Vel,2) + i2_u = UBOUND(SrcPointsFieldTypeData%Vel,2) + IF (.NOT. ALLOCATED(DstPointsFieldTypeData%Vel)) THEN + ALLOCATE(DstPointsFieldTypeData%Vel(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstExtPointFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstPointsFieldTypeData%Vel.', ErrStat, ErrMsg,RoutineName) RETURN END IF END IF - DstExtPointFieldTypeData%Vel = SrcExtPointFieldTypeData%Vel + DstPointsFieldTypeData%Vel = SrcPointsFieldTypeData%Vel ENDIF - END SUBROUTINE FlowField_CopyExtPointFieldType + END SUBROUTINE FlowField_CopyPointsFieldType - SUBROUTINE FlowField_DestroyExtPointFieldType( ExtPointFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(ExtPointFieldType), INTENT(INOUT) :: ExtPointFieldTypeData + SUBROUTINE FlowField_DestroyPointsFieldType( PointsFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(PointsFieldType), INTENT(INOUT) :: PointsFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -2545,7 +2546,7 @@ SUBROUTINE FlowField_DestroyExtPointFieldType( ExtPointFieldTypeData, ErrStat, E LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyExtPointFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyPointsFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -2556,16 +2557,16 @@ SUBROUTINE FlowField_DestroyExtPointFieldType( ExtPointFieldTypeData, ErrStat, E DEALLOCATEpointers_local = .true. END IF -IF (ALLOCATED(ExtPointFieldTypeData%Vel)) THEN - DEALLOCATE(ExtPointFieldTypeData%Vel) +IF (ALLOCATED(PointsFieldTypeData%Vel)) THEN + DEALLOCATE(PointsFieldTypeData%Vel) ENDIF - END SUBROUTINE FlowField_DestroyExtPointFieldType + END SUBROUTINE FlowField_DestroyPointsFieldType - SUBROUTINE FlowField_PackExtPointFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_PackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(ExtPointFieldType), INTENT(IN) :: InData + TYPE(PointsFieldType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -2580,7 +2581,7 @@ SUBROUTINE FlowField_PackExtPointFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackExtPointFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackPointsFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2648,13 +2649,13 @@ SUBROUTINE FlowField_PackExtPointFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, END DO END DO END IF - END SUBROUTINE FlowField_PackExtPointFieldType + END SUBROUTINE FlowField_PackPointsFieldType - SUBROUTINE FlowField_UnPackExtPointFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_UnPackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(ExtPointFieldType), INTENT(INOUT) :: OutData + TYPE(PointsFieldType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -2667,7 +2668,7 @@ SUBROUTINE FlowField_UnPackExtPointFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdat INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackExtPointFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackPointsFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2701,7 +2702,7 @@ SUBROUTINE FlowField_UnPackExtPointFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdat END DO END DO END IF - END SUBROUTINE FlowField_UnPackExtPointFieldType + END SUBROUTINE FlowField_UnPackPointsFieldType SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(FlowFieldType), INTENT(IN) :: SrcFlowFieldTypeData @@ -2723,23 +2724,24 @@ SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeDa DstFlowFieldTypeData%RefPosition = SrcFlowFieldTypeData%RefPosition DstFlowFieldTypeData%PropagationDir = SrcFlowFieldTypeData%PropagationDir DstFlowFieldTypeData%VFlowAngle = SrcFlowFieldTypeData%VFlowAngle - DstFlowFieldTypeData%VelInterpOrder = SrcFlowFieldTypeData%VelInterpOrder + DstFlowFieldTypeData%VelInterpCubic = SrcFlowFieldTypeData%VelInterpCubic DstFlowFieldTypeData%RotateWindBox = SrcFlowFieldTypeData%RotateWindBox + DstFlowFieldTypeData%AccFieldValid = SrcFlowFieldTypeData%AccFieldValid DstFlowFieldTypeData%RotToWind = SrcFlowFieldTypeData%RotToWind DstFlowFieldTypeData%RotFromWind = SrcFlowFieldTypeData%RotFromWind CALL FlowField_Copyuniformfieldtype( SrcFlowFieldTypeData%Uniform, DstFlowFieldTypeData%Uniform, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_Copygridfieldtype( SrcFlowFieldTypeData%Grid, DstFlowFieldTypeData%Grid, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_Copypointsfieldtype( SrcFlowFieldTypeData%Points, DstFlowFieldTypeData%Points, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_Copyuserfieldtype( SrcFlowFieldTypeData%User, DstFlowFieldTypeData%User, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_Copygrid3dfieldtype( SrcFlowFieldTypeData%Grid3D, DstFlowFieldTypeData%Grid3D, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_Copyextgridfieldtype( SrcFlowFieldTypeData%ExtGrid, DstFlowFieldTypeData%ExtGrid, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_Copygrid4dfieldtype( SrcFlowFieldTypeData%Grid4D, DstFlowFieldTypeData%Grid4D, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_Copyextpointfieldtype( SrcFlowFieldTypeData%ExtPoint, DstFlowFieldTypeData%ExtPoint, CtrlCode, ErrStat2, ErrMsg2 ) + CALL FlowField_Copyuserfieldtype( SrcFlowFieldTypeData%User, DstFlowFieldTypeData%User, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE FlowField_CopyFlowFieldType @@ -2767,13 +2769,13 @@ SUBROUTINE FlowField_DestroyFlowFieldType( FlowFieldTypeData, ErrStat, ErrMsg, D CALL FlowField_Destroyuniformfieldtype( FlowFieldTypeData%Uniform, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_Destroygridfieldtype( FlowFieldTypeData%Grid, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_Destroypointsfieldtype( FlowFieldTypeData%Points, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_Destroyuserfieldtype( FlowFieldTypeData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_Destroygrid3dfieldtype( FlowFieldTypeData%Grid3D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_Destroyextgridfieldtype( FlowFieldTypeData%ExtGrid, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_Destroygrid4dfieldtype( FlowFieldTypeData%Grid4D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_Destroyextpointfieldtype( FlowFieldTypeData%ExtPoint, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL FlowField_Destroyuserfieldtype( FlowFieldTypeData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE FlowField_DestroyFlowFieldType @@ -2816,8 +2818,9 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Re_BufSz = Re_BufSz + SIZE(InData%RefPosition) ! RefPosition Re_BufSz = Re_BufSz + 1 ! PropagationDir Re_BufSz = Re_BufSz + 1 ! VFlowAngle - Int_BufSz = Int_BufSz + 1 ! VelInterpOrder + Int_BufSz = Int_BufSz + 1 ! VelInterpCubic Int_BufSz = Int_BufSz + 1 ! RotateWindBox + Int_BufSz = Int_BufSz + 1 ! AccFieldValid Re_BufSz = Re_BufSz + SIZE(InData%RotToWind) ! RotToWind Re_BufSz = Re_BufSz + SIZE(InData%RotFromWind) ! RotFromWind ! Allocate buffers for subtypes, if any (we'll get sizes from these) @@ -2838,71 +2841,71 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! Grid: size of buffers for each call to pack subtype - CALL FlowField_Packgridfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid, ErrStat2, ErrMsg2, .TRUE. ) ! Grid + Int_BufSz = Int_BufSz + 3 ! Points: size of buffers for each call to pack subtype + CALL FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, .TRUE. ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! Grid + IF(ALLOCATED(Re_Buf)) THEN ! Points Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! Grid + IF(ALLOCATED(Db_Buf)) THEN ! Points Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! Grid + IF(ALLOCATED(Int_Buf)) THEN ! Points Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! User: size of buffers for each call to pack subtype - CALL FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, .TRUE. ) ! User + Int_BufSz = Int_BufSz + 3 ! Grid3D: size of buffers for each call to pack subtype + CALL FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid3D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! User + IF(ALLOCATED(Re_Buf)) THEN ! Grid3D Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! User + IF(ALLOCATED(Db_Buf)) THEN ! Grid3D Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! User + IF(ALLOCATED(Int_Buf)) THEN ! Grid3D Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! ExtGrid: size of buffers for each call to pack subtype - CALL FlowField_Packextgridfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, .TRUE. ) ! ExtGrid + Int_BufSz = Int_BufSz + 3 ! Grid4D: size of buffers for each call to pack subtype + CALL FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! ExtGrid + IF(ALLOCATED(Re_Buf)) THEN ! Grid4D Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! ExtGrid + IF(ALLOCATED(Db_Buf)) THEN ! Grid4D Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! ExtGrid + IF(ALLOCATED(Int_Buf)) THEN ! Grid4D Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! ExtPoint: size of buffers for each call to pack subtype - CALL FlowField_Packextpointfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, .TRUE. ) ! ExtPoint + Int_BufSz = Int_BufSz + 3 ! User: size of buffers for each call to pack subtype + CALL FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, .TRUE. ) ! User CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! ExtPoint + IF(ALLOCATED(Re_Buf)) THEN ! User Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! ExtPoint + IF(ALLOCATED(Db_Buf)) THEN ! User Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! ExtPoint + IF(ALLOCATED(Int_Buf)) THEN ! User Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -2943,10 +2946,12 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VFlowAngle Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%VelInterpOrder + IntKiBuf(Int_Xferred) = TRANSFER(InData%VelInterpCubic, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%RotateWindBox, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%AccFieldValid, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 DO i2 = LBOUND(InData%RotToWind,2), UBOUND(InData%RotToWind,2) DO i1 = LBOUND(InData%RotToWind,1), UBOUND(InData%RotToWind,1) ReKiBuf(Re_Xferred) = InData%RotToWind(i1,i2) @@ -2987,7 +2992,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_Packgridfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid, ErrStat2, ErrMsg2, OnlySize ) ! Grid + CALL FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, OnlySize ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3015,7 +3020,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, OnlySize ) ! User + CALL FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, OnlySize ) ! Grid3D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3043,7 +3048,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_Packextgridfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtGrid, ErrStat2, ErrMsg2, OnlySize ) ! ExtGrid + CALL FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, OnlySize ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3071,7 +3076,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_Packextpointfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%ExtPoint, ErrStat2, ErrMsg2, OnlySize ) ! ExtPoint + CALL FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, OnlySize ) ! User CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3141,10 +3146,12 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Re_Xferred = Re_Xferred + 1 OutData%VFlowAngle = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%VelInterpOrder = IntKiBuf(Int_Xferred) + OutData%VelInterpCubic = TRANSFER(IntKiBuf(Int_Xferred), OutData%VelInterpCubic) Int_Xferred = Int_Xferred + 1 OutData%RotateWindBox = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotateWindBox) Int_Xferred = Int_Xferred + 1 + OutData%AccFieldValid = TRANSFER(IntKiBuf(Int_Xferred), OutData%AccFieldValid) + Int_Xferred = Int_Xferred + 1 i1_l = LBOUND(OutData%RotToWind,1) i1_u = UBOUND(OutData%RotToWind,1) i2_l = LBOUND(OutData%RotToWind,2) @@ -3238,7 +3245,7 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackgridfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid, ErrStat2, ErrMsg2 ) ! Grid + CALL FlowField_Unpackpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Points, ErrStat2, ErrMsg2 ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3278,7 +3285,7 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackuserfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%User, ErrStat2, ErrMsg2 ) ! User + CALL FlowField_Unpackgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid3D, ErrStat2, ErrMsg2 ) ! Grid3D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3318,7 +3325,7 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackextgridfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtGrid, ErrStat2, ErrMsg2 ) ! ExtGrid + CALL FlowField_Unpackgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid4D, ErrStat2, ErrMsg2 ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3358,7 +3365,7 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackextpointfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%ExtPoint, ErrStat2, ErrMsg2 ) ! ExtPoint + CALL FlowField_Unpackuserfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%User, ErrStat2, ErrMsg2 ) ! User CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 15f4fd1e40..a08a45423f 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -46,6 +46,7 @@ MODULE InflowWind USE InflowWind_Subs USE FlowField_IO_Types USE FlowField_IO + USE FlowField USE Lidar ! module for obtaining sensor data @@ -306,7 +307,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, FlowField_InitData%SumFileUnit = SumFileUnit FlowField_InitData%PropagationDir = InputFileData%PropagationDir FlowField_InitData%VFlowAngle = InputFileData%VFlowAngle - FlowField_InitData%VelInterpOrder = InputFileData%VelInterpOrder + FlowField_InitData%VelInterpCubic = InputFileData%VelInterpCubic FlowField_InitData%CalcAccel = InitInp%CalcAccel select case(FlowField_InitData%WindType) @@ -974,8 +975,10 @@ SUBROUTINE InflowWind_CalcOutput( Time, InputData, p, & !----------------------------- ! Outputs: OutputData%VelocityUVW !----------------------------- - CALL CalculateOutput( Time, InputData, p, ContStates, DiscStates, ConstrStates, & - OtherStates, OutputData, m, .TRUE., TmpErrStat, TmpErrMsg ) + ! CALL CalculateOutput( Time, InputData, p, ContStates, DiscStates, ConstrStates, & + ! OtherStates, OutputData, m, .TRUE., TmpErrStat, TmpErrMsg ) + call FlowField_GetVelAcc(p%FlowField, 0, Time, InputData%PositionXYZ, & + OutputData%VelocityUVW, OutputData%AccelUVW, TmpErrStat, TmpErrMsg) CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) !----------------------------- diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 7035d856aa..d076d2e227 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -65,7 +65,7 @@ typedef InflowWind/InflowWind InflowWind_InputFile LOGICAL EchoFlag typedef ^ ^ IntKi WindType - 0 - "Type of windfile" - typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation (meteorological direction)" (degrees) typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" degrees -typedef ^ ^ IntKi VelInterpOrder - 0 - "Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7]" - +typedef ^ ^ LOGICAL VelInterpCubic - .FALSE. - "Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7]" - typedef ^ ^ IntKi NWindVel - - - "Number of points to output the wind velocity (0 to 9)" typedef ^ ^ ReKi WindVxiList : - - "List of X coordinates for wind velocity measurements" meters typedef ^ ^ ReKi WindVyiList : - - "List of Y coordinates for wind velocity measurements" meters diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index f0cdee3c09..50739215bd 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -240,8 +240,8 @@ SUBROUTINE InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, In CALL ParseVarWDefault( InFileInfo, CurLine, "VFlowAng", InputFileData%VFlowAngle, 0.0_ReKi, TmpErrStat, TmpErrMsg, UnEc ) if (Failed()) return - ! VelInterpOrder: Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] - CALL ParseVar( InFileInfo, CurLine, "VelInterpOrder", InputFileData%VelInterpOrder, TmpErrStat, TmpErrMsg, UnEc ) + ! VelInterpCubic: Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] + CALL ParseVar( InFileInfo, CurLine, "VelInterpCubic", InputFileData%VelInterpCubic, TmpErrStat, TmpErrMsg, UnEc ) if (Failed()) return ! NWindVel: Number of points to output the wind velocity (0 to 9) diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index 1baa33147e..4aea0a45ad 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -80,7 +80,7 @@ MODULE InflowWind_Types INTEGER(IntKi) :: WindType = 0 !< Type of windfile [-] REAL(ReKi) :: PropagationDir !< Direction of wind propagation (meteorological direction) [(degrees)] REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [degrees] - INTEGER(IntKi) :: VelInterpOrder = 0 !< Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7] [-] + LOGICAL :: VelInterpCubic = .FALSE. !< Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7] [-] INTEGER(IntKi) :: NWindVel !< Number of points to output the wind velocity (0 to 9) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WindVxiList !< List of X coordinates for wind velocity measurements [meters] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WindVyiList !< List of Y coordinates for wind velocity measurements [meters] @@ -524,7 +524,7 @@ SUBROUTINE InflowWind_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCod DstInputFileData%WindType = SrcInputFileData%WindType DstInputFileData%PropagationDir = SrcInputFileData%PropagationDir DstInputFileData%VFlowAngle = SrcInputFileData%VFlowAngle - DstInputFileData%VelInterpOrder = SrcInputFileData%VelInterpOrder + DstInputFileData%VelInterpCubic = SrcInputFileData%VelInterpCubic DstInputFileData%NWindVel = SrcInputFileData%NWindVel IF (ALLOCATED(SrcInputFileData%WindVxiList)) THEN i1_l = LBOUND(SrcInputFileData%WindVxiList,1) @@ -682,7 +682,7 @@ SUBROUTINE InflowWind_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Int_BufSz = Int_BufSz + 1 ! WindType Re_BufSz = Re_BufSz + 1 ! PropagationDir Re_BufSz = Re_BufSz + 1 ! VFlowAngle - Int_BufSz = Int_BufSz + 1 ! VelInterpOrder + Int_BufSz = Int_BufSz + 1 ! VelInterpCubic Int_BufSz = Int_BufSz + 1 ! NWindVel Int_BufSz = Int_BufSz + 1 ! WindVxiList allocated yes/no IF ( ALLOCATED(InData%WindVxiList) ) THEN @@ -784,7 +784,7 @@ SUBROUTINE InflowWind_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%VFlowAngle Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%VelInterpOrder + IntKiBuf(Int_Xferred) = TRANSFER(InData%VelInterpCubic, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%NWindVel Int_Xferred = Int_Xferred + 1 @@ -987,7 +987,7 @@ SUBROUTINE InflowWind_UnPackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS Re_Xferred = Re_Xferred + 1 OutData%VFlowAngle = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%VelInterpOrder = IntKiBuf(Int_Xferred) + OutData%VelInterpCubic = TRANSFER(IntKiBuf(Int_Xferred), OutData%VelInterpCubic) Int_Xferred = Int_Xferred + 1 OutData%NWindVel = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 From 1baa7f5798b864a754cdc924186cf11372edc98d Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Mon, 20 Feb 2023 22:42:06 +0000 Subject: [PATCH 12/51] Updating to ifw-mod branch of r-test --- 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 7e5eba5bb1..b8cb84ed21 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 7e5eba5bb17229e0fa00d0c2f7cb0b9c65a668d4 +Subproject commit b8cb84ed2154d1c4f89fa06a1d4be89c5749c12c From af3fcb27a7f07375524a39179bf524100ee2474c Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 21 Feb 2023 16:55:45 +0000 Subject: [PATCH 13/51] FlowField integration and testing with driver --- cmake/OpenfastCmakeUtils.cmake | 4 +- modules/inflowwind/src/FlowField.f90 | 558 +++++----- modules/inflowwind/src/FlowField.txt | 1 + modules/inflowwind/src/FlowField_IO.f90 | 15 +- modules/inflowwind/src/FlowField_IO.txt | 11 +- modules/inflowwind/src/FlowField_IO_Types.f90 | 975 +----------------- modules/inflowwind/src/FlowField_Types.f90 | 7 + modules/inflowwind/src/InflowWind.f90 | 29 +- modules/inflowwind/src/InflowWind.txt | 3 +- modules/inflowwind/src/InflowWind_Driver.f90 | 345 +++---- .../inflowwind/src/InflowWind_Driver_Subs.f90 | 127 ++- .../src/InflowWind_Driver_Types.f90 | 76 +- modules/inflowwind/src/InflowWind_Subs.f90 | 28 +- modules/inflowwind/src/InflowWind_Types.f90 | 76 +- modules/openfast-library/src/FAST_Subs.f90 | 1 + 15 files changed, 685 insertions(+), 1571 deletions(-) diff --git a/cmake/OpenfastCmakeUtils.cmake b/cmake/OpenfastCmakeUtils.cmake index 44ec6c2acc..1a490e7453 100644 --- a/cmake/OpenfastCmakeUtils.cmake +++ b/cmake/OpenfastCmakeUtils.cmake @@ -42,13 +42,11 @@ function(generate_f90_types regfile outfile) get_filename_component(input ${regfile} ABSOLUTE) get_filename_component(outdir ${outfile} DIRECTORY) - add_custom_command( OUTPUT ${outfile} DEPENDS openfast_registry ${input} - COMMAND ${CMAKE_BINARY_DIR}/modules/openfast-registry/openfast_registry ${input} "-O" "${outdir}" ${OPENFAST_REGISTRY_INCLUDES} ${ARGN} + COMMAND ${CMAKE_BINARY_DIR}/modules/openfast-registry/openfast_registry ${input} "-O" ${outdir} ${OPENFAST_REGISTRY_INCLUDES} ${ARGN} ) - set_source_files_properties(${outfile} PROPERTIES GENERATED TRUE) endfunction(generate_f90_types) # diff --git a/modules/inflowwind/src/FlowField.f90 b/modules/inflowwind/src/FlowField.f90 index bbf8079ecf..5cc2c6b95f 100644 --- a/modules/inflowwind/src/FlowField.f90 +++ b/modules/inflowwind/src/FlowField.f90 @@ -52,7 +52,7 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel character(*), parameter :: RoutineName = "FlowField_GetVelAcc" integer(IntKi) :: i integer(IntKi) :: NumPoints - logical :: CalcAccel + logical :: OutputAccel real(ReKi), allocatable :: Position(:, :) integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg @@ -70,8 +70,8 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel NumPoints = size(PositionXYZ, dim=2) ! Determine if acceleration should be calculated and returned - CalcAccel = allocated(AccelUVW) - if (CalcAccel .and. .not. FF%AccFieldValid) then + OutputAccel = allocated(AccelUVW) + if (OutputAccel .and. .not. FF%AccFieldValid) then call SetErrStat(ErrID_Fatal, "Accel output requested, but accel field is not valid", & ErrStat, ErrMsg, RoutineName) return @@ -124,8 +124,8 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel UFopVel = UniformField_InterpLinear(FF%Uniform, Time) end if - ! If acceleration output is requested - if (CalcAccel) then + ! If velocity and acceleration output is requested + if (OutputAccel) then ! If cubic interpolation was used for the velocity, use same for accel ! otherwise, calculate operating point via cubic interpolation @@ -164,7 +164,7 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel ! Grid3D Flow Field !------------------------------------------------------------------------- - if (CalcAccel) then + if (OutputAccel) then ! Loop through points do i = 1, NumPoints @@ -177,7 +177,7 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel end if ! Calculate grid cells for interpolation - call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), CalcAccel, & + call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), .true., & VelCell, AccCell, Xi, Is3D, TmpErrStat, TmpErrMsg) if (TmpErrStat >= AbortErrLev) then call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) @@ -208,18 +208,19 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel end if ! Calculate grid cells for interpolation - call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), CalcAccel, & + call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), FF%VelInterpCubic, & VelCell, AccCell, Xi, Is3D, TmpErrStat, TmpErrMsg) if (TmpErrStat >= AbortErrLev) then call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) return end if - ! Cubic or linear velocity interpolation if (FF%VelInterpCubic) then + ! Cubic velocity call Grid3DField_GetVelAccCubic(FF%Grid3D%DTime, VelCell, AccCell, Xi, Is3D, & Velocity=VelocityUVW(:, i)) else + ! Linear velocity VelocityUVW(:, i) = Grid3DField_GetVelLinear(VelCell, Xi, Is3D) end if @@ -295,7 +296,7 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel !---------------------------------------------------------------------------- if (FF%RotateWindBox) then - if (.not. CalcAccel) then + if (.not. OutputAccel) then do i = 1, NumPoints VelocityUVW(:, i) = matmul(FF%RotFromWind, VelocityUVW(:, i)) end do @@ -730,94 +731,75 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, VelCell, AccCell, !---------------------------------------------------------------------------- ! Get grid time bounds - boundStat = Grid3DField_GetBoundsT(G3D, Time, Position(1), Xi(3), IT_Lo, IT_Hi, TimeShifted) - if (boundStat > 0) then - ErrMsg = ' Error: GF wind array was exhausted at '//TRIM(Num2LStr(TIME))// & - ' seconds (trying to access data at '//TRIM(Num2LStr(TimeShifted))//' seconds).' - ErrStat = ErrID_Fatal - return - end if + call Grid3DField_GetBoundsT(Position(1), Xi(3)) + if (ErrStat >= AbortErrLev) return ! Get grid Z bounds - boundStat = Grid3DField_GetBoundsZ(G3D, Position(3), Xi(2), IZ_Lo, IZ_Hi, OnGrid) - if (boundStat < 0) then - ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction '// & - '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' - ErrStat = ErrID_Fatal - return - else if (boundStat > 0) then - ErrMsg = ' GF wind array boundaries violated. Grid too small in Z direction (Z='// & - TRIM(Num2LStr(Position(3)))//' m is above the grid).' - ErrStat = ErrID_Fatal - return - end if + call Grid3DField_GetBoundsZ(Position(3), Xi(2)) + if (ErrStat >= AbortErrLev) return !---------------------------------------------------------------------------- ! Extract cells from grids !---------------------------------------------------------------------------- - if (OnGrid .or. G3D%InterpTower) then + if (OnGrid) then ! Get grid Y bounds - boundStat = Grid3DField_GetBoundsY(G3D, Position(2), Xi(1), IY_Lo, IY_Hi) - if (boundStat /= 0) then - ErrMsg = ' GF wind array boundaries violated: Grid too small in Y direction. Y='// & - TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*G3D%YHWid))// & - ', '//TRIM(Num2LStr(G3D%YHWid))//']' - ErrStat = ErrID_Fatal - return - end if + call Grid3DField_GetBoundsY(Position(2), Xi(1)) + if (ErrStat >= AbortErrLev) return Is3D = .true. - if (OnGrid) then - - ! Get velocities from the grid - VelCell(1, :) = G3D%Vel(:, IY_Lo, IZ_Lo, IT_Lo) - VelCell(2, :) = G3D%Vel(:, IY_Hi, IZ_Lo, IT_Lo) - VelCell(3, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Lo) - VelCell(4, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Lo) - VelCell(5, :) = G3D%Vel(:, IY_Lo, IZ_Lo, IT_Hi) - VelCell(6, :) = G3D%Vel(:, IY_Hi, IZ_Lo, IT_Hi) - VelCell(7, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Hi) - VelCell(8, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Hi) - - ! Get accelerations from the grid - if (CalcAccel) then - AccCell(1, :) = G3D%Acc(:, IY_Lo, IZ_Lo, IT_Lo) - AccCell(2, :) = G3D%Acc(:, IY_Hi, IZ_Lo, IT_Lo) - AccCell(3, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Lo) - AccCell(4, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Lo) - AccCell(5, :) = G3D%Acc(:, IY_Lo, IZ_Lo, IT_Hi) - AccCell(6, :) = G3D%Acc(:, IY_Hi, IZ_Lo, IT_Hi) - AccCell(7, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Hi) - AccCell(8, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Hi) - end if + ! Get velocities from the grid + VelCell(1, :) = G3D%Vel(:, IY_Lo, IZ_Lo, IT_Lo) + VelCell(2, :) = G3D%Vel(:, IY_Hi, IZ_Lo, IT_Lo) + VelCell(3, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Lo) + VelCell(4, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Lo) + VelCell(5, :) = G3D%Vel(:, IY_Lo, IZ_Lo, IT_Hi) + VelCell(6, :) = G3D%Vel(:, IY_Hi, IZ_Lo, IT_Hi) + VelCell(7, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Hi) + VelCell(8, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Hi) + + ! Get accelerations from the grid + if (CalcAccel) then + AccCell(1, :) = G3D%Acc(:, IY_Lo, IZ_Lo, IT_Lo) + AccCell(2, :) = G3D%Acc(:, IY_Hi, IZ_Lo, IT_Lo) + AccCell(3, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Lo) + AccCell(4, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Lo) + AccCell(5, :) = G3D%Acc(:, IY_Lo, IZ_Lo, IT_Hi) + AccCell(6, :) = G3D%Acc(:, IY_Hi, IZ_Lo, IT_Hi) + AccCell(7, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Hi) + AccCell(8, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Hi) + end if - else if (G3D%InterpTower) then + else if (G3D%InterpTower) then - ! Get velocities from the grid - VelCell(1, :) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Lo) - VelCell(2, :) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Lo) - VelCell(3, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Lo) - VelCell(4, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Lo) - VelCell(5, :) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Hi) - VelCell(6, :) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Hi) - VelCell(7, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Hi) - VelCell(8, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Hi) + ! Get grid Y bounds + call Grid3DField_GetBoundsY(Position(2), Xi(1)) + if (ErrStat >= AbortErrLev) return - ! Get accelerations from the grid - if (CalcAccel) then - AccCell(1, :) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Lo) - AccCell(2, :) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Lo) - AccCell(3, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Lo) - AccCell(4, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Lo) - AccCell(5, :) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Hi) - AccCell(6, :) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Hi) - AccCell(7, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Hi) - AccCell(8, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Hi) - end if + Is3D = .true. + ! Get velocities from the grid + VelCell(1, :) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Lo) + VelCell(2, :) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Lo) + VelCell(3, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Lo) + VelCell(4, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Lo) + VelCell(5, :) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Hi) + VelCell(6, :) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Hi) + VelCell(7, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Hi) + VelCell(8, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Hi) + + ! Get accelerations from the grid + if (CalcAccel) then + AccCell(1, :) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Lo) + AccCell(2, :) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Lo) + AccCell(3, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Lo) + AccCell(4, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Lo) + AccCell(5, :) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Hi) + AccCell(6, :) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Hi) + AccCell(7, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Hi) + AccCell(8, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Hi) end if else @@ -856,6 +838,177 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, VelCell, AccCell, end if +contains + + subroutine Grid3DField_GetBoundsY(PosY, DY) + + real(ReKi), intent(in) :: PosY + real(ReKi), intent(out) :: DY + + real(ReKi) :: Y_Grid + + ! Calculate position on Y grid + Y_Grid = (PosY + G3D%YHWid)*G3D%InvDY + 1 + + ! Calculate bounding grid indices + IY_LO = floor(Y_Grid, IntKi) + IY_HI = ceiling(Y_Grid, IntKi) + + ! Position location within interval [0,1] + DY = Y_Grid - aint(Y_Grid) + + if (IY_LO >= 1 .and. IY_HI <= G3D%NYGrids) then + DY = 2.0_ReKi*DY - 1.0_ReKi + else if (IY_LO == 0 .and. DY >= 1.0_ReKi - GridTol) then + IY_LO = 1 + IY_HI = 2 + DY = -1.0_ReKi + else if (IY_LO == G3D%NYGrids .and. DY <= GridTol) then + IY_LO = G3D%NYGrids - 1 + IY_HI = G3D%NYGrids + DY = 1.0_ReKi + else + ! Position outside + call SetErrStat(ErrID_Fatal, ' GF wind array boundaries violated: Grid too small in Y direction. Y='// & + TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*G3D%YHWid))// & + ', '//TRIM(Num2LStr(G3D%YHWid))//']', & + ErrStat, ErrMsg, RoutineName) + end if + + end subroutine + + subroutine Grid3DField_GetBoundsZ(PosZ, DZ) + + real(ReKi), intent(in) :: PosZ + real(ReKi), intent(out) :: DZ + + real(ReKi) :: Z_GRID + + ! Calculate position on Z grid + Z_GRID = (PosZ - G3D%GridBase)*G3D%InvDZ + 1 + + ! Calculate bounding grid indices + IZ_LO = floor(Z_GRID, IntKi) + IZ_HI = ceiling(Z_GRID, IntKi) + + ! Position location within interval [-1,1] + DZ = Z_GRID - aint(Z_GRID) + + ! If indices are within grid, set on grid to true + if (IZ_LO >= 1 .and. IZ_HI <= G3D%NZGrids) then + OnGrid = .true. + DZ = 2.0_ReKi*DZ - 1.0_ReKi + else if (IZ_LO < 1) then + if (IZ_LO == 0 .and. DZ >= 1.0_ReKi - GridTol) then + OnGrid = .true. + IZ_LO = 1 + IZ_HI = 2 + DZ = -1.0_ReKi + else if (G3D%InterpTower) then + ! Interp from bottom of grid to ground (zero velocity) + OnGrid = .false. + IZ_LO = 0 + IZ_HI = 1 + DZ = 2.0_ReKi*(PosZ/G3D%GridBase) - 1.0_ReKi + else if (G3D%NTGrids > 0) then + ! Interpolate with tower grid + OnGrid = .false. + ! Tower grid is reversed (lowest index is top of tower) + IZ_LO = int(-(Z_GRID - 1)) + 1 + if (IZ_LO >= G3D%NTGrids) then + ! Between end of tower grid and ground (zero velocity) + IZ_LO = G3D%NTGrids + DZ = 1.0_ReKi - 2.0_ReKi*(PosZ/(G3D%GridBase - real(IZ_LO - 1, ReKi)/G3D%InvDZ)) + else + ! Within tower grid + DZ = 2.0_ReKi*(real(2 - IZ_LO, ReKi) - Z_GRID) - 1.0_ReKi + end if + IZ_HI = IZ_LO + 1 + else + ! Position below grid + call SetErrStat(ErrID_Fatal, ' GF wind array boundaries violated. '// & + 'Grid too small in Z direction '// & + '(height (Z='//TRIM(Num2LStr(Position(3)))// & + ' m) is below the grid and no tower points are defined).', & + ErrStat, ErrMsg, RoutineName) + end if + else if (IZ_HI > G3D%NZGrids) then ! Above Grid + if (IZ_HI == G3D%NZGrids + 1 .and. DZ <= GridTol) then + OnGrid = .true. + IZ_LO = G3D%NZGrids - 1 + IZ_HI = G3D%NZGrids + DZ = 1.0_ReKi + else + ! Position above grid + call SetErrStat(ErrID_Fatal, ' GF wind array boundaries violated. '// & + 'Grid too small in Z direction '// & + '(Z='//TRIM(Num2LStr(Position(3)))//' m is above grid.)', & + ErrStat, ErrMsg, RoutineName) + end if + end if + + end subroutine + + subroutine Grid3DField_GetBoundsT(PosX, DT) + + real(ReKi), intent(in) :: PosX + real(ReKi), intent(out) :: DT + + real(ReKi) :: T_GRID + + ! Perform the time shift. At time=0, a point half the grid width downstream + ! (p%YHWid) will index into the zero time slice. If we did not do this, + ! any point downstream of the tower at the beginning of the run would + ! index outside of the array. This all assumes the grid width is at least as + ! large as the rotor. If it isn't, then the interpolation will not work. + + ! in distance, X: InputInfo%PosX - p%InitXPosition - TIME*p%MeanWS + TimeShifted = real(Time, ReKi) + (G3D%InitXPosition - PosX)*G3D%InvMWS + + ! If field is periodic and time is after total time, remove total time + if (G3D%Periodic .and. TimeShifted > G3D%TotalTime) then + TimeShifted = TimeShifted - G3D%TotalTime + end if + + ! Get position on T grid + T_GRID = TimeShifted*G3D%Rate + 1 + + ! Calculate bounding grid indices + IT_LO = floor(T_GRID, IntKi) + IT_HI = ceiling(T_GRID, IntKi) + + ! Position location within interval [0,1] + DT = T_GRID - aint(T_GRID) + + ! Adjust indices and interpolant + if (IT_LO >= 1 .and. IT_HI <= G3D%NSteps) then + ! Point is within grid + DT = 2.0_ReKi*DT - 1.0_ReKi + else if (IT_LO == G3D%NSteps) then + if (G3D%Periodic) then + ! Time wraps back to beginning + IT_HI = 1 + DT = 2.0_ReKi*DT - 1.0_ReKi + else if (DT <= GridTol) then + ! Within tolerance of last time + IT_HI = IT_LO + DT = -1.0_Reki + else + ! Extrapolate + IT_LO = G3D%NSteps - 1 + IT_HI = G3D%NSteps + DT = DT + 1.0_ReKi + end if + else + ! Time exceeds array bounds + call SetErrStat(ErrID_Fatal, ' Error: GF wind array was exhausted at '// & + TRIM(Num2LStr(TIME))//' seconds (trying to access data at '// & + TRIM(Num2LStr(TimeShifted))//' seconds).', & + ErrStat, ErrMsg, RoutineName) + end if + + end subroutine + end subroutine pure function Grid3DField_GetVelLinear(VelCell, Xi, Is3D) result(Velocity) @@ -918,7 +1071,7 @@ subroutine Grid3DField_GetVelAccCubic(DTime, VelCell, AccCell, Xi, Is3D, Velocit integer(IntKi) :: IC real(ReKi) :: N(4) real(ReKi) :: P(3, 2), PP(3, 2) - real(ReKi) :: h, t, C1, C2, C3, C4 + real(ReKi) :: t, C1, C2, C3, C4 ! If 3D interpolation if (Is3D) then @@ -929,21 +1082,13 @@ subroutine Grid3DField_GetVelAccCubic(DTime, VelCell, AccCell, Xi, Is3D, Velocit N(3) = (1.0_ReKi - Xi(1))*(1.0_ReKi + Xi(2))/4.0_ReKi N(4) = (1.0_ReKi + Xi(1))*(1.0_ReKi + Xi(2))/4.0_ReKi - ! Calculate velocity at lo and hi time - if (present(Velocity)) then - do IC = 1, 3 - P(IC, 1) = dot_product(VelCell(1:4, IC), N) ! low time - P(IC, 2) = dot_product(VelCell(5:8, IC), N) ! hi time - end do - end if - - ! Calculate acceleration at lo and hi time - if (present(Accel)) then - do IC = 1, 3 - PP(IC, 1) = dot_product(AccCell(1:4, IC), N) ! low time - PP(IC, 2) = dot_product(AccCell(5:8, IC), N) ! hi time - end do - end if + ! Calculate velocity and acceleration at lo and hi time + do IC = 1, 3 + P(IC, 1) = dot_product(VelCell(1:4, IC), N) ! lo time + P(IC, 2) = dot_product(VelCell(5:8, IC), N) ! hi time + PP(IC, 1) = dot_product(AccCell(1:4, IC), N) ! lo time + PP(IC, 2) = dot_product(AccCell(5:8, IC), N) ! hi time + end do else ! 2D (Tower) @@ -952,40 +1097,30 @@ subroutine Grid3DField_GetVelAccCubic(DTime, VelCell, AccCell, Xi, Is3D, Velocit N(2) = (1.0_ReKi + Xi(2))/2.0_ReKi ! Calculate velocity and acceleration at lo and hi time - if (present(Velocity)) then - do IC = 1, 3 - P(IC, 1) = dot_product(VelCell(1:2, IC), N(1:2)) ! low time - P(IC, 2) = dot_product(VelCell(3:4, IC), N(1:2)) ! hi time - end do - end if - - ! Calculate acceleration at lo and hi time - if (present(Accel)) then - do IC = 1, 3 - PP(IC, 1) = dot_product(AccCell(1:2, IC), N(1:2)) ! low time - PP(IC, 2) = dot_product(AccCell(3:4, IC), N(1:2)) ! hi time - end do - end if + do IC = 1, 3 + P(IC, 1) = dot_product(VelCell(1:2, IC), N(1:2)) ! lo time + P(IC, 2) = dot_product(VelCell(3:4, IC), N(1:2)) ! hi time + PP(IC, 1) = dot_product(AccCell(1:2, IC), N(1:2)) ! lo time + PP(IC, 2) = dot_product(AccCell(3:4, IC), N(1:2)) ! hi time + end do end if - !---------------------------------------------------------------------------- - ! Smooth velocity and acceleration using cubic hermite spline - !---------------------------------------------------------------------------- - - h = DTime + ! Calculate interval percent t = (Xi(3) + 1)/2.0_ReKi + ! If velocity requested if (present(Velocity)) then C1 = 2.0_ReKi*t*t*t - 3.0_ReKi*t*t + 1.0_ReKi - C2 = (t*t*t - 2.0_ReKi*t*t + t)*h + C2 = (t*t*t - 2.0_ReKi*t*t + t)*DTime C3 = -2.0_ReKi*t*t*t + 3.0_ReKi*t*t - C4 = (t*t*t - t*t)*h + C4 = (t*t*t - t*t)*DTime Velocity = C1*P(:, 1) + C2*PP(:, 1) + C3*P(:, 2) + C4*PP(:, 2) end if + ! If acceleration requested if (present(Accel)) then - C1 = (6.0_ReKi*t*t - 6.0_ReKi*t)/h + C1 = (6.0_ReKi*t*t - 6.0_ReKi*t)/DTime C2 = 3.0_ReKi*t*t - 4.0_ReKi*t + 1.0_ReKi C3 = -C1 C4 = 3.0_ReKi*t*t - 2.0_ReKi*t @@ -994,189 +1129,6 @@ subroutine Grid3DField_GetVelAccCubic(DTime, VelCell, AccCell, Xi, Is3D, Velocit end subroutine -function Grid3DField_GetBoundsY(G3D, PosY, DY, IY_LO, IY_HI) result(stat) - - type(Grid3DFieldType), intent(in) :: G3D - real(ReKi), intent(in) :: PosY - real(ReKi), intent(out) :: DY - integer(IntKi), intent(out) :: IY_LO, IY_HI - - real(ReKi) :: Y_Grid - integer(IntKi) :: stat - - ! Calculate position on Y grid - Y_Grid = (PosY + G3D%YHWid)*G3D%InvDY + 1 - - ! Calculate bounding grid indices - IY_LO = floor(Y_Grid, IntKi) - IY_HI = ceiling(Y_Grid, IntKi) - - ! Position location within interval [0,1] - DY = Y_Grid - aint(Y_Grid) - - ! Initialize stat to zero to indicate position is in bounds - stat = 0 - - if (IY_LO >= 1 .and. IY_HI <= G3D%NYGrids) then - DY = 2.0_ReKi*DY - 1.0_ReKi - else if (IY_LO == 0 .and. DY >= 1.0_ReKi - GridTol) then - IY_LO = 1 - IY_HI = 2 - DY = -1.0_ReKi - else if (IY_LO == G3D%NYGrids .and. DY <= GridTol) then - IY_LO = G3D%NYGrids - 1 - IY_HI = G3D%NYGrids - DY = 1.0_ReKi - else - ! Position outside - stat = -1 - end if - -end function - -function Grid3DField_GetBoundsZ(G3D, PosZ, DZ, IZ_LO, IZ_HI, OnGrid) result(stat) - - type(Grid3DFieldType), intent(in) :: G3D - real(ReKi), intent(in) :: PosZ - real(ReKi), intent(out) :: DZ - integer(IntKi), intent(out) :: IZ_LO, IZ_HI - logical, intent(out) :: OnGrid - - integer(IntKi) :: stat - real(ReKi) :: Z_GRID - - ! Calculate position on Z grid - Z_GRID = (PosZ - G3D%GridBase)*G3D%InvDZ + 1 - - ! Calculate bounding grid indices - IZ_LO = floor(Z_GRID, IntKi) - IZ_HI = ceiling(Z_GRID, IntKi) - - ! Position location within interval [-1,1] - DZ = Z_GRID - aint(Z_GRID) - - ! Initialize stat to zero to indicate position is in bounds - stat = 0 - - ! If indices are within grid, set on grid to true - if (IZ_LO >= 1 .and. IZ_HI <= G3D%NZGrids) then - - OnGrid = .true. - DZ = 2.0_ReKi*DZ - 1.0_ReKi - - else if (IZ_LO < 1) then - - if (IZ_LO == 0 .and. DZ >= 1.0_ReKi - GridTol) then - OnGrid = .true. - IZ_LO = 1 - IZ_HI = 2 - DZ = -1.0_ReKi - else if (G3D%InterpTower) then - ! Interp from bottom of grid to ground (zero velocity) - OnGrid = .false. - IZ_LO = 0 - IZ_HI = 1 - DZ = 2.0_ReKi*(PosZ/G3D%GridBase) - 1.0_ReKi - else if (G3D%NTGrids > 0) then - ! Interpolate with tower grid - OnGrid = .false. - ! Tower grid is reversed (lowest index is top of tower) - IZ_LO = int(-(Z_GRID - 1)) + 1 - if (IZ_LO >= G3D%NTGrids) then - ! Between end of tower grid and ground (zero velocity) - IZ_LO = G3D%NTGrids - DZ = 1.0_ReKi - 2.0_ReKi*(PosZ/(G3D%GridBase - real(IZ_LO - 1, ReKi)/G3D%InvDZ)) - else - ! Within tower grid - DZ = 2.0_ReKi*(real(2 - IZ_LO, ReKi) - Z_GRID) - 1.0_ReKi - end if - IZ_HI = IZ_LO + 1 - else - ! Position below grid - stat = -1 - end if - - else if (IZ_HI > G3D%NZGrids) then ! Above Grid - - if (IZ_HI == G3D%NZGrids + 1 .and. DZ <= GridTol) then - OnGrid = .true. - IZ_LO = G3D%NZGrids - 1 - IZ_HI = G3D%NZGrids - DZ = 1.0_ReKi - else - ! Position above grid - stat = 1 - end if - - end if - -end function - -function Grid3DField_GetBoundsT(G3D, Time, PosX, DT, IT_LO, IT_HI, TimeShifted) result(stat) - - type(Grid3DFieldType), intent(in) :: G3D - real(DbKi), intent(in) :: Time - real(ReKi), intent(in) :: PosX - real(ReKi), intent(out) :: DT - integer(IntKi), intent(out) :: IT_LO, IT_HI - real(ReKi), intent(out) :: TimeShifted - - real(ReKi) :: T_GRID - integer(IntKi) :: stat - - ! Perform the time shift. At time=0, a point half the grid width downstream - ! (p%YHWid) will index into the zero time slice. If we did not do this, - ! any point downstream of the tower at the beginning of the run would - ! index outside of the array. This all assumes the grid width is at least as - ! large as the rotor. If it isn't, then the interpolation will not work. - - ! in distance, X: InputInfo%PosX - p%InitXPosition - TIME*p%MeanWS - TimeShifted = real(Time, ReKi) + (G3D%InitXPosition - PosX)*G3D%InvMWS - - ! If field is periodic and time is after total time, remove total time - if (G3D%Periodic .and. TimeShifted > G3D%TotalTime) then - TimeShifted = TimeShifted - G3D%TotalTime - end if - - ! Get position on T grid - T_GRID = TimeShifted*G3D%Rate + 1 - - ! Calculate bounding grid indices - IT_LO = floor(T_GRID, IntKi) - IT_HI = ceiling(T_GRID, IntKi) - - ! Position location within interval [0,1] - DT = T_GRID - aint(T_GRID) - - ! Initialize stat to indicate position is within grid - stat = 0 - - ! Adjust indices and interpolant - if (IT_LO >= 1 .and. IT_HI <= G3D%NSteps) then - ! Point is within grid - DT = 2.0_ReKi*DT - 1.0_ReKi - else if (IT_LO == G3D%NSteps) then - if (G3D%Periodic) then - ! Time wraps back to beginning - IT_HI = 1 - DT = 2.0_ReKi*DT - 1.0_ReKi - else if (DT <= GridTol) then - ! Within tolerance of last time - IT_HI = IT_LO - DT = -1.0_Reki - else - ! Extrapolate - IT_LO = G3D%NSteps - 1 - IT_HI = G3D%NSteps - DT = DT + 1.0_ReKi - end if - else - ! Time exceeds array bounds - stat = 1 - end if - -end function - subroutine Grid3DField_CalcAccel(G3D, ErrStat, ErrMsg) type(Grid3DFieldType), intent(inout) :: G3D integer(IntKi), intent(out) :: ErrStat diff --git a/modules/inflowwind/src/FlowField.txt b/modules/inflowwind/src/FlowField.txt index 0518bf963e..3077e8ee7f 100644 --- a/modules/inflowwind/src/FlowField.txt +++ b/modules/inflowwind/src/FlowField.txt @@ -99,6 +99,7 @@ typedef ^ PointsFieldType ReKi Vel #---------------------------------------------------------------------------------------------------------------------------------- typedef ^ FlowFieldType IntKi FieldType - 0 - "Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External}" - +typedef ^ ^ logical Enabled - .true. - "" - typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" radians diff --git a/modules/inflowwind/src/FlowField_IO.f90 b/modules/inflowwind/src/FlowField_IO.f90 index ead54f170d..34adcf1b53 100644 --- a/modules/inflowwind/src/FlowField_IO.f90 +++ b/modules/inflowwind/src/FlowField_IO.f90 @@ -145,25 +145,34 @@ subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) select case (FF%FieldType) case (Uniform_FieldType) - if (InitInp%CalcAccel .or. (InitInp%VelInterpCubic)) then + + if (InitInp%OutputAccel .or. (InitInp%VelInterpCubic)) then call UniformField_CalcAccel(FF%Uniform, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return FF%AccFieldValid = .true. end if + FF%VelInterpCubic = InitInp%VelInterpCubic case (Grid3D_FieldType) - if (InitInp%CalcAccel .or. (InitInp%VelInterpCubic)) then + if (InitInp%OutputAccel .or. (InitInp%VelInterpCubic)) then call Grid3DField_CalcAccel(FF%Grid3D, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return FF%AccFieldValid = .true. end if + FF%VelInterpCubic = InitInp%VelInterpCubic case default - if (InitInp%CalcAccel) then + if (InitInp%OutputAccel) then call SetErrStat(ErrID_Fatal, "Acceleration not implemented for field type", & ErrStat, ErrMsg, RoutineName) + return + end if + if (InitInp%VelInterpCubic) then + CALL WrScr ( ' Cubic velocity interpolation not implemented for WindType '//& + num2LStr(InitInp%WindType)//', using linear interpolation' ) + FF%VelInterpCubic = .false. end if end select diff --git a/modules/inflowwind/src/FlowField_IO.txt b/modules/inflowwind/src/FlowField_IO.txt index 5988f428a9..ea4ed00715 100644 --- a/modules/inflowwind/src/FlowField_IO.txt +++ b/modules/inflowwind/src/FlowField_IO.txt @@ -9,14 +9,7 @@ include Registry_NWTC_Library.txt usefrom FlowField.txt -typedef FlowField_IO ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - -typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - -typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - -typedef ^ OtherStateType ReKi DummyOtherState - - - "Remove this variable if you have other states" - -typedef ^ MiscVarType ReKi DummyMiscVar - - - "Remove this variable if you have misc variables" - -typedef ^ InputType ReKi Position :: - - "Array holding the input positions at a given timestep" meters - -typedef ^ SteadyInitInputType ReKi HWindSpeed - - - "Horizontal wind speed" m/s +typedef FlowField_IO SteadyInitInputType ReKi HWindSpeed - - - "Horizontal wind speed" m/s typedef ^ ^ ReKi RefHt - - - "Reference height for horizontal wind speed" meters typedef ^ ^ ReKi PLExp - - - "Power law exponent" - @@ -68,7 +61,7 @@ typedef ^ ^ IntKi SumFileUni typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" - typedef ^ ^ logical VelInterpCubic - .false. - "Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7]" - -typedef ^ ^ logical CalcAccel - .false. - "Flag to calculate acceleration data" - +typedef ^ ^ logical OutputAccel - .false. - "Flag to indicate that wind acceleration should be output" - typedef ^ ^ SteadyInitInputType Steady - - - "" - typedef ^ ^ UniformInitInputType Uniform - - - "" - typedef ^ ^ TurbSimInitInputType TurbSim - - - "" - diff --git a/modules/inflowwind/src/FlowField_IO_Types.f90 b/modules/inflowwind/src/FlowField_IO_Types.f90 index b72058398f..f56f9d7a1d 100644 --- a/modules/inflowwind/src/FlowField_IO_Types.f90 +++ b/modules/inflowwind/src/FlowField_IO_Types.f90 @@ -34,36 +34,6 @@ MODULE FlowField_IO_Types USE FlowField_Types USE NWTC_Library IMPLICIT NONE -! ========= FlowField_IO_ContinuousStateType ======= - TYPE, PUBLIC :: FlowField_IO_ContinuousStateType - REAL(ReKi) :: DummyContState !< Remove this variable if you have continuous states [-] - END TYPE FlowField_IO_ContinuousStateType -! ======================= -! ========= FlowField_IO_DiscreteStateType ======= - TYPE, PUBLIC :: FlowField_IO_DiscreteStateType - REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] - END TYPE FlowField_IO_DiscreteStateType -! ======================= -! ========= FlowField_IO_ConstraintStateType ======= - TYPE, PUBLIC :: FlowField_IO_ConstraintStateType - REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] - END TYPE FlowField_IO_ConstraintStateType -! ======================= -! ========= FlowField_IO_OtherStateType ======= - TYPE, PUBLIC :: FlowField_IO_OtherStateType - REAL(ReKi) :: DummyOtherState !< Remove this variable if you have other states [-] - END TYPE FlowField_IO_OtherStateType -! ======================= -! ========= FlowField_IO_MiscVarType ======= - TYPE, PUBLIC :: FlowField_IO_MiscVarType - REAL(ReKi) :: DummyMiscVar !< Remove this variable if you have misc variables [-] - END TYPE FlowField_IO_MiscVarType -! ======================= -! ========= FlowField_IO_InputType ======= - TYPE, PUBLIC :: FlowField_IO_InputType - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Position !< Array holding the input positions at a given timestep [meters] - END TYPE FlowField_IO_InputType -! ======================= ! ========= SteadyInitInputType ======= TYPE, PUBLIC :: SteadyInitInputType REAL(ReKi) :: HWindSpeed !< Horizontal wind speed [m/s] @@ -145,7 +115,7 @@ MODULE FlowField_IO_Types REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [-] LOGICAL :: VelInterpCubic = .false. !< Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7] [-] - LOGICAL :: CalcAccel = .false. !< Flag to calculate acceleration data [-] + LOGICAL :: OutputAccel = .false. !< Flag to indicate that wind acceleration should be output [-] TYPE(SteadyInitInputType) :: Steady !< [-] TYPE(UniformInitInputType) :: Uniform !< [-] TYPE(TurbSimInitInputType) :: TurbSim !< [-] @@ -186,27 +156,28 @@ MODULE FlowField_IO_Types END TYPE FlowField_IO_InitOutputType ! ======================= CONTAINS - SUBROUTINE FlowField_IO_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FlowField_IO_ContinuousStateType), INTENT(IN) :: SrcContStateData - TYPE(FlowField_IO_ContinuousStateType), INTENT(INOUT) :: DstContStateData + SUBROUTINE FlowField_IO_CopySteadyInitInputType( SrcSteadyInitInputTypeData, DstSteadyInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(SteadyInitInputType), INTENT(IN) :: SrcSteadyInitInputTypeData + TYPE(SteadyInitInputType), INTENT(INOUT) :: DstSteadyInitInputTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyContState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopySteadyInitInputType' ! ErrStat = ErrID_None ErrMsg = "" - DstContStateData%DummyContState = SrcContStateData%DummyContState - END SUBROUTINE FlowField_IO_CopyContState + DstSteadyInitInputTypeData%HWindSpeed = SrcSteadyInitInputTypeData%HWindSpeed + DstSteadyInitInputTypeData%RefHt = SrcSteadyInitInputTypeData%RefHt + DstSteadyInitInputTypeData%PLExp = SrcSteadyInitInputTypeData%PLExp + END SUBROUTINE FlowField_IO_CopySteadyInitInputType - SUBROUTINE FlowField_IO_DestroyContState( ContStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(FlowField_IO_ContinuousStateType), INTENT(INOUT) :: ContStateData + SUBROUTINE FlowField_IO_DestroySteadyInitInputType( SteadyInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(SteadyInitInputType), INTENT(INOUT) :: SteadyInitInputTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers @@ -215,7 +186,7 @@ SUBROUTINE FlowField_IO_DestroyContState( ContStateData, ErrStat, ErrMsg, DEALLO LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyContState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroySteadyInitInputType' ErrStat = ErrID_None ErrMsg = "" @@ -226,13 +197,13 @@ SUBROUTINE FlowField_IO_DestroyContState( ContStateData, ErrStat, ErrMsg, DEALLO DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE FlowField_IO_DestroyContState + END SUBROUTINE FlowField_IO_DestroySteadyInitInputType - SUBROUTINE FlowField_IO_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE FlowField_IO_PackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(FlowField_IO_ContinuousStateType), INTENT(IN) :: InData + TYPE(SteadyInitInputType), INTENT(IN) :: InData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly @@ -247,7 +218,7 @@ SUBROUTINE FlowField_IO_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackContState' + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackSteadyInitInputType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -263,7 +234,9 @@ SUBROUTINE FlowField_IO_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyContState + Re_BufSz = Re_BufSz + 1 ! HWindSpeed + Re_BufSz = Re_BufSz + 1 ! RefHt + Re_BufSz = Re_BufSz + 1 ! PLExp IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -291,742 +264,19 @@ SUBROUTINE FlowField_IO_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt Db_Xferred = 1 Int_Xferred = 1 - ReKiBuf(Re_Xferred) = InData%DummyContState + ReKiBuf(Re_Xferred) = InData%HWindSpeed Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackContState - - SUBROUTINE FlowField_IO_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(FlowField_IO_ContinuousStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackContState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyContState = ReKiBuf(Re_Xferred) + ReKiBuf(Re_Xferred) = InData%RefHt Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackContState - - SUBROUTINE FlowField_IO_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FlowField_IO_DiscreteStateType), INTENT(IN) :: SrcDiscStateData - TYPE(FlowField_IO_DiscreteStateType), INTENT(INOUT) :: DstDiscStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyDiscState' -! - ErrStat = ErrID_None - ErrMsg = "" - DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState - END SUBROUTINE FlowField_IO_CopyDiscState - - SUBROUTINE FlowField_IO_DestroyDiscState( DiscStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(FlowField_IO_DiscreteStateType), INTENT(INOUT) :: DiscStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyDiscState' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyDiscState - - SUBROUTINE FlowField_IO_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(FlowField_IO_DiscreteStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackDiscState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyDiscState - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyDiscState + ReKiBuf(Re_Xferred) = InData%PLExp Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackDiscState + END SUBROUTINE FlowField_IO_PackSteadyInitInputType - SUBROUTINE FlowField_IO_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE FlowField_IO_UnPackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(FlowField_IO_DiscreteStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackDiscState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyDiscState = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackDiscState - - SUBROUTINE FlowField_IO_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FlowField_IO_ConstraintStateType), INTENT(IN) :: SrcConstrStateData - TYPE(FlowField_IO_ConstraintStateType), INTENT(INOUT) :: DstConstrStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyConstrState' -! - ErrStat = ErrID_None - ErrMsg = "" - DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState - END SUBROUTINE FlowField_IO_CopyConstrState - - SUBROUTINE FlowField_IO_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(FlowField_IO_ConstraintStateType), INTENT(INOUT) :: ConstrStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyConstrState' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyConstrState - - SUBROUTINE FlowField_IO_PackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(FlowField_IO_ConstraintStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackConstrState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyConstrState - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyConstrState - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackConstrState - - SUBROUTINE FlowField_IO_UnPackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(FlowField_IO_ConstraintStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackConstrState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyConstrState = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackConstrState - - SUBROUTINE FlowField_IO_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FlowField_IO_OtherStateType), INTENT(IN) :: SrcOtherStateData - TYPE(FlowField_IO_OtherStateType), INTENT(INOUT) :: DstOtherStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyOtherState' -! - ErrStat = ErrID_None - ErrMsg = "" - DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState - END SUBROUTINE FlowField_IO_CopyOtherState - - SUBROUTINE FlowField_IO_DestroyOtherState( OtherStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(FlowField_IO_OtherStateType), INTENT(INOUT) :: OtherStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyOtherState' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyOtherState - - SUBROUTINE FlowField_IO_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(FlowField_IO_OtherStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackOtherState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyOtherState - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyOtherState - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackOtherState - - SUBROUTINE FlowField_IO_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(FlowField_IO_OtherStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackOtherState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyOtherState = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackOtherState - - SUBROUTINE FlowField_IO_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FlowField_IO_MiscVarType), INTENT(IN) :: SrcMiscData - TYPE(FlowField_IO_MiscVarType), INTENT(INOUT) :: DstMiscData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyMisc' -! - ErrStat = ErrID_None - ErrMsg = "" - DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar - END SUBROUTINE FlowField_IO_CopyMisc - - SUBROUTINE FlowField_IO_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(FlowField_IO_MiscVarType), INTENT(INOUT) :: MiscData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyMisc' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyMisc - - SUBROUTINE FlowField_IO_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(FlowField_IO_MiscVarType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackMisc' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyMiscVar - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyMiscVar - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackMisc - - SUBROUTINE FlowField_IO_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(FlowField_IO_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyMiscVar = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackMisc - - SUBROUTINE FlowField_IO_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FlowField_IO_InputType), INTENT(IN) :: SrcInputData - TYPE(FlowField_IO_InputType), INTENT(INOUT) :: DstInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyInput' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcInputData%Position)) THEN - i1_l = LBOUND(SrcInputData%Position,1) - i1_u = UBOUND(SrcInputData%Position,1) - i2_l = LBOUND(SrcInputData%Position,2) - i2_u = UBOUND(SrcInputData%Position,2) - IF (.NOT. ALLOCATED(DstInputData%Position)) THEN - ALLOCATE(DstInputData%Position(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Position.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInputData%Position = SrcInputData%Position -ENDIF - END SUBROUTINE FlowField_IO_CopyInput - - SUBROUTINE FlowField_IO_DestroyInput( InputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(FlowField_IO_InputType), INTENT(INOUT) :: InputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - -IF (ALLOCATED(InputData%Position)) THEN - DEALLOCATE(InputData%Position) -ENDIF - END SUBROUTINE FlowField_IO_DestroyInput - - SUBROUTINE FlowField_IO_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(FlowField_IO_InputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! Position allocated yes/no - IF ( ALLOCATED(InData%Position) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Position upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Position) ! Position - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%Position) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Position,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Position,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Position,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Position,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%Position,2), UBOUND(InData%Position,2) - DO i1 = LBOUND(InData%Position,1), UBOUND(InData%Position,1) - ReKiBuf(Re_Xferred) = InData%Position(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - END SUBROUTINE FlowField_IO_PackInput - - SUBROUTINE FlowField_IO_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(FlowField_IO_InputType), INTENT(INOUT) :: OutData + TYPE(SteadyInitInputType), INTENT(INOUT) :: OutData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg ! Local variables @@ -1036,173 +286,6 @@ SUBROUTINE FlowField_IO_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Position not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Position)) DEALLOCATE(OutData%Position) - ALLOCATE(OutData%Position(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Position.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%Position,2), UBOUND(OutData%Position,2) - DO i1 = LBOUND(OutData%Position,1), UBOUND(OutData%Position,1) - OutData%Position(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - END SUBROUTINE FlowField_IO_UnPackInput - - SUBROUTINE FlowField_IO_CopySteadyInitInputType( SrcSteadyInitInputTypeData, DstSteadyInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SteadyInitInputType), INTENT(IN) :: SrcSteadyInitInputTypeData - TYPE(SteadyInitInputType), INTENT(INOUT) :: DstSteadyInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopySteadyInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstSteadyInitInputTypeData%HWindSpeed = SrcSteadyInitInputTypeData%HWindSpeed - DstSteadyInitInputTypeData%RefHt = SrcSteadyInitInputTypeData%RefHt - DstSteadyInitInputTypeData%PLExp = SrcSteadyInitInputTypeData%PLExp - END SUBROUTINE FlowField_IO_CopySteadyInitInputType - - SUBROUTINE FlowField_IO_DestroySteadyInitInputType( SteadyInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(SteadyInitInputType), INTENT(INOUT) :: SteadyInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroySteadyInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroySteadyInitInputType - - SUBROUTINE FlowField_IO_PackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SteadyInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackSteadyInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! HWindSpeed - Re_BufSz = Re_BufSz + 1 ! RefHt - Re_BufSz = Re_BufSz + 1 ! PLExp - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%HWindSpeed - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PLExp - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackSteadyInitInputType - - SUBROUTINE FlowField_IO_UnPackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SteadyInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackSteadyInitInputType' @@ -2650,7 +1733,7 @@ SUBROUTINE FlowField_IO_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlC DstInitInputData%PropagationDir = SrcInitInputData%PropagationDir DstInitInputData%VFlowAngle = SrcInitInputData%VFlowAngle DstInitInputData%VelInterpCubic = SrcInitInputData%VelInterpCubic - DstInitInputData%CalcAccel = SrcInitInputData%CalcAccel + DstInitInputData%OutputAccel = SrcInitInputData%OutputAccel CALL FlowField_IO_Copysteadyinitinputtype( SrcInitInputData%Steady, DstInitInputData%Steady, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -2756,7 +1839,7 @@ SUBROUTINE FlowField_IO_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt Re_BufSz = Re_BufSz + 1 ! PropagationDir Re_BufSz = Re_BufSz + 1 ! VFlowAngle Int_BufSz = Int_BufSz + 1 ! VelInterpCubic - Int_BufSz = Int_BufSz + 1 ! CalcAccel + Int_BufSz = Int_BufSz + 1 ! OutputAccel ! Allocate buffers for subtypes, if any (we'll get sizes from these) Int_BufSz = Int_BufSz + 3 ! Steady: size of buffers for each call to pack subtype CALL FlowField_IO_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, .TRUE. ) ! Steady @@ -2931,7 +2014,7 @@ SUBROUTINE FlowField_IO_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt Re_Xferred = Re_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%VelInterpCubic, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%CalcAccel, IntKiBuf(1)) + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutputAccel, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 CALL FlowField_IO_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, OnlySize ) ! Steady CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -3195,7 +2278,7 @@ SUBROUTINE FlowField_IO_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Er Re_Xferred = Re_Xferred + 1 OutData%VelInterpCubic = TRANSFER(IntKiBuf(Int_Xferred), OutData%VelInterpCubic) Int_Xferred = Int_Xferred + 1 - OutData%CalcAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%CalcAccel) + OutData%OutputAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutputAccel) Int_Xferred = Int_Xferred + 1 Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 diff --git a/modules/inflowwind/src/FlowField_Types.f90 b/modules/inflowwind/src/FlowField_Types.f90 index 6b568a86da..42eee1ec60 100644 --- a/modules/inflowwind/src/FlowField_Types.f90 +++ b/modules/inflowwind/src/FlowField_Types.f90 @@ -141,6 +141,7 @@ MODULE FlowField_Types ! ========= FlowFieldType ======= TYPE, PUBLIC :: FlowFieldType INTEGER(IntKi) :: FieldType = 0 !< Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External} [-] + LOGICAL :: Enabled = .true. !< [-] REAL(ReKi) , DIMENSION(1:3) :: RefPosition !< Reference position (point where box is rotated) [meters] REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [radians] @@ -2721,6 +2722,7 @@ SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeDa ErrStat = ErrID_None ErrMsg = "" DstFlowFieldTypeData%FieldType = SrcFlowFieldTypeData%FieldType + DstFlowFieldTypeData%Enabled = SrcFlowFieldTypeData%Enabled DstFlowFieldTypeData%RefPosition = SrcFlowFieldTypeData%RefPosition DstFlowFieldTypeData%PropagationDir = SrcFlowFieldTypeData%PropagationDir DstFlowFieldTypeData%VFlowAngle = SrcFlowFieldTypeData%VFlowAngle @@ -2815,6 +2817,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Db_BufSz = 0 Int_BufSz = 0 Int_BufSz = Int_BufSz + 1 ! FieldType + Int_BufSz = Int_BufSz + 1 ! Enabled Re_BufSz = Re_BufSz + SIZE(InData%RefPosition) ! RefPosition Re_BufSz = Re_BufSz + 1 ! PropagationDir Re_BufSz = Re_BufSz + 1 ! VFlowAngle @@ -2938,6 +2941,8 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS IntKiBuf(Int_Xferred) = InData%FieldType Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Enabled, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 DO i1 = LBOUND(InData%RefPosition,1), UBOUND(InData%RefPosition,1) ReKiBuf(Re_Xferred) = InData%RefPosition(i1) Re_Xferred = Re_Xferred + 1 @@ -3136,6 +3141,8 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Xferred = 1 OutData%FieldType = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + OutData%Enabled = TRANSFER(IntKiBuf(Int_Xferred), OutData%Enabled) + Int_Xferred = Int_Xferred + 1 i1_l = LBOUND(OutData%RefPosition,1) i1_u = UBOUND(OutData%RefPosition,1) DO i1 = LBOUND(OutData%RefPosition,1), UBOUND(OutData%RefPosition,1) diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index a08a45423f..6396722a4f 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -46,7 +46,6 @@ MODULE InflowWind USE InflowWind_Subs USE FlowField_IO_Types USE FlowField_IO - USE FlowField USE Lidar ! module for obtaining sensor data @@ -281,19 +280,28 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, ! Allocate the arrays for passing points in and velocities out CALL AllocAry( InputGuess%PositionXYZ, 3, InitInp%NumWindPoints, "Array of positions at which to find wind velocities", TmpErrStat, TmpErrMsg ) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - + InputGuess%PositionXYZ = 0.0_ReKi + InputGuess%HubPosition = 0.0_ReKi + CALL Eye(InputGuess%HubOrientation,TmpErrStat,TmpErrMsg) + CALL AllocAry( y%VelocityUVW, 3, InitInp%NumWindPoints, "Array of wind velocities returned by InflowWind", TmpErrStat, TmpErrMsg ) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) IF ( ErrStat>= AbortErrLev ) THEN CALL Cleanup() RETURN ENDIF - InputGuess%PositionXYZ = 0.0_ReKi - InputGuess%HubPosition = 0.0_ReKi - CALL Eye(InputGuess%HubOrientation,TmpErrStat,TmpErrMsg) - y%VelocityUVW = 0.0_ReKi + IF ( InitInp%OutputAccel ) THEN + CALL AllocAry( y%AccelUVW, 3, InitInp%NumWindPoints, "Array of wind accelerations returned by InflowWind", TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + y%AccelUVW = 0.0_ReKi + ENDIF + !----------------------------------------------------------------- ! Initialize the submodules based on the WindType @@ -308,7 +316,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, FlowField_InitData%PropagationDir = InputFileData%PropagationDir FlowField_InitData%VFlowAngle = InputFileData%VFlowAngle FlowField_InitData%VelInterpCubic = InputFileData%VelInterpCubic - FlowField_InitData%CalcAccel = InitInp%CalcAccel + FlowField_InitData%OutputAccel = InitInp%OutputAccel select case(FlowField_InitData%WindType) @@ -975,11 +983,8 @@ SUBROUTINE InflowWind_CalcOutput( Time, InputData, p, & !----------------------------- ! Outputs: OutputData%VelocityUVW !----------------------------- - ! CALL CalculateOutput( Time, InputData, p, ContStates, DiscStates, ConstrStates, & - ! OtherStates, OutputData, m, .TRUE., TmpErrStat, TmpErrMsg ) - call FlowField_GetVelAcc(p%FlowField, 0, Time, InputData%PositionXYZ, & - OutputData%VelocityUVW, OutputData%AccelUVW, TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + CALL CalculateOutput( Time, InputData, p, ContStates, DiscStates, ConstrStates, & + OtherStates, OutputData, m, .TRUE., TmpErrStat, TmpErrMsg ) !----------------------------- ! Output: OutputData%DiskVel diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index d076d2e227..955d0d14c6 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -113,7 +113,7 @@ typedef ^ ^ CHARACTER(1024) RootName typedef ^ ^ FileInfoType PassedFileData - - - "If we don't use the input file, pass everything through this" - typedef ^ ^ LOGICAL WindType2UseInputFile - .TRUE. - "Flag for toggling file based IO in wind type 2." - typedef ^ ^ FileInfoType WindType2Data - - - "Optional slot for wind type 2 data if file IO is not used." - -typedef ^ ^ LOGICAL CalcAccel - .FALSE. - "Flag to calculate acceleration." - +typedef ^ ^ LOGICAL OutputAccel - .FALSE. - "Flag to output wind acceleration" - typedef ^ ^ Lidar_InitInputType lidar - - - "InitInput for lidar data" - typedef ^ ^ IfW_4Dext_InitInputType FDext - - - "InitInput for 4D external wind data" - typedef ^ ^ ReKi RadAvg - - - "Radius (from hub) used for averaging wind speed" - @@ -203,6 +203,7 @@ typedef ^ ^ IfW_UserWind_MiscVarType UserWind typedef ^ ^ IfW_4Dext_MiscVarType FDext - - - "MiscVars from FDext" - typedef ^ ^ ReKi AllOuts : - - "An array holding the value of all of the calculated (not only selected) output channels" "see OutListParameters.xlsx spreadsheet" typedef ^ ^ ReKi WindViUVW :: - - "List of UVW velocities for wind velocity measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ" meters/second +typedef ^ ^ ReKi WindAiUVW :: - - "List of UVW accelerations for wind acceleration measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ" m/s^2 typedef ^ MiscVarType InflowWind_InputType u_Avg - - - "inputs for computing rotor-averaged values" - typedef ^ MiscVarType InflowWind_OutputType y_Avg - - - "outputs for computing rotor-averaged values" - typedef ^ MiscVarType InflowWind_InputType u_Hub - - - "inputs for computing hub values" - diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index 6b49036f4b..16c91a6c21 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -31,6 +31,7 @@ PROGRAM InflowWind_Driver USE InflowWind_Driver_Types ! Contains types and routines for handling the input arguments USE InflowWind_Driver_Subs ! Contains subroutines for the driver program USE FlowField + USE InflowWind_Subs, only: CalculateOutput IMPLICIT NONE @@ -61,21 +62,17 @@ PROGRAM InflowWind_Driver TYPE(IfWDriver_Flags) :: SettingsFlags ! Flags indicating which settings were specified (includes CL and ipt file) TYPE(IfWDriver_Settings) :: Settings ! Driver settings REAL(DbKi) :: Timer(1:2) ! Keep track of how long this takes to run - REAL(DbKi) :: Timer2(2) ! Keep track of how long this takes to run REAL(DbKi) :: TimeNow ! The current time - INTEGER(IntKi) :: NumTotalPoints ! Number of points for this iteration LOGICAL :: TempFileExist ! Flag for inquiring file existence - CHARACTER(11) :: TmpNumString ! Temporary string for holding a number INTEGER(IntKi) :: ITime ! Generic counter for keeping track of the timestep index - !FIXME: may want to borrow some of the type storage concepts from WAMIT2 !FIXME: look at Waves.f90 for ideas on other things needed for this ! Local variables for the FFT calculations - REAL(ReKi), ALLOCATABLE :: FFTDataSetVel(:,:) ! Velocity dataset for FFT calcs. Indices of (NumTimeSteps,3). Index 2 gives dimension U,V,W - COMPLEX(ReKi), ALLOCATABLE :: FFTDataSetFrq(:,:) ! Complex frequency information for the FFT (NumFreqs,3). Index 2 gives dimension X,Y,Z - REAL(ReKi), ALLOCATABLE :: TimeArray(:) ! Time array information. (NumTimeSteps) - REAL(ReKi), ALLOCATABLE :: FreqArray(:) ! Frequency array information (NumFreqs) + ! REAL(ReKi), ALLOCATABLE :: FFTDataSetVel(:,:) ! Velocity dataset for FFT calcs. Indices of (NumTimeSteps,3). Index 2 gives dimension U,V,W + ! COMPLEX(ReKi), ALLOCATABLE :: FFTDataSetFrq(:,:) ! Complex frequency information for the FFT (NumFreqs,3). Index 2 gives dimension X,Y,Z + ! REAL(ReKi), ALLOCATABLE :: TimeArray(:) ! Time array information. (NumTimeSteps) + ! REAL(ReKi), ALLOCATABLE :: FreqArray(:) ! Frequency array information (NumFreqs) @@ -111,10 +108,6 @@ PROGRAM InflowWind_Driver CALL NWTC_Init CALL DispNVD(ProgInfo) -! Beep = .FALSE. - - - !-------------------------------------------------------------------------------------------------------------------------------- !-=-=- Setup the program -=-=- !-------------------------------------------------------------------------------------------------------------------------------- @@ -122,62 +115,9 @@ PROGRAM InflowWind_Driver ! Start the timer CALL CPU_TIME( Timer(1) ) - ! Set some CLSettings to null/default values - CLSettings%DvrIptFileName = "" ! No input name name until set - CLSettings%IfWIptFileName = "" ! No IfW input file name until set - CLSettings%SummaryFileName = "" ! No summary file name until set - CLSettings%NumTimeSteps = 0_IntKi - CLSettings%DT = 0.0_DbKi - CLSettings%TStart = 0.0_ReKi - CLSettings%FFTcoord = 0.0_ReKi ! Set to origin - CLSettings%GridDelta = 0.0_ReKi ! No stepsize - CLSettings%GridN = 1_IntKi ! No grid points to calculate -- center of grid only - CLSettings%XRange = 0.0_ReKi ! No xrange points - CLSettings%YRange = 0.0_ReKi ! No Yrange points - CLSettings%ZRange = 0.0_ReKi ! No Zrange points - CLSettings%PointsFileName = "" ! No points file name until set - CLSettings%PointsOutputName = "" ! No points file name until set - CLSettings%FFTOutputName = "" ! No FFT output file name until set - CLSettings%WindGridOutputName = "" ! No WindGrid output file name until set - CLSettings%WindGridOutputUnit = -1_IntKi ! No WindGrid output unit set - CLSettings%FFTOutputUnit = -1_IntKi ! No FFT output unit set - CLSettings%PointsOutputUnit = -1_IntKi ! No Points file output unit set - CLSettings%ProgInfo = ProgInfo ! Driver info - - ! Set some CLSettingsFlags to null/default values - CLSettingsFlags%DvrIptFile = .FALSE. ! Driver input filename given as command line argument - CLSettingsFlags%IfWIptFile = .FALSE. ! InflowWind input filename given as command line argument - CLSettingsFlags%Summary = .FALSE. ! create a summary at command line? (data extents in the wind file) - CLSettingsFlags%SummaryFile = .FALSE. ! create a summary file of the output? - CLSettingsFlags%TStart = .FALSE. ! specified time to start at - CLSettingsFlags%NumTimeSteps = .FALSE. ! specified a number of timesteps - CLSettingsFlags%NumTimeStepsDefault = .FALSE. ! specified 'DEFAULT' for number of timesteps - CLSettingsFlags%DT = .FALSE. ! specified a resolution in time - CLSettingsFlags%DTDefault = .FALSE. ! specified 'DEFAULT' for resolution in time - CLSettingsFlags%FFTcalc = .FALSE. ! do an FFT - CLSettingsFlags%WindGrid = .FALSE. ! Requested output of wind data on a grid -- input file option only - CLSettingsFlags%XRange = .FALSE. ! specified a range of x -- command line option only -- stored as GridCtrCoord and GridDelta - CLSettingsFlags%YRange = .FALSE. ! specified a range of y -- command line option only -- stored as GridCtrCoord and GridDelta - CLSettingsFlags%ZRange = .FALSE. ! specified a range of z -- command line option only -- stored as GridCtrCoord and GridDelta - CLSettingsFlags%Dx = .FALSE. ! specified a resolution in x -- command line option only, 0.0 otherwise - CLSettingsFlags%Dy = .FALSE. ! speficied a resolution in y - CLSettingsFlags%Dz = .FALSE. ! specified a resolution in z - CLSettingsFlags%PointsFile = .FALSE. ! points filename to read in -- command line option only - CLSettingsFlags%WindGridOutputInit = .FALSE. ! Wind Grid output file not started - CLSettingsFlags%FFTOutputInit = .FALSE. ! FFT output file not started - CLSettingsFlags%PointsOutputInit = .FALSE. ! Points output file not started - CLSettingsFlags%Verbose = .FALSE. ! Turn on verbose error reporting? - CLSettingsFlags%VVerbose = .FALSE. ! Turn on very verbose error reporting? - CLSettingsFlags%WrHAWC = .FALSE. ! don't convert to HAWC format - CLSettingsFlags%WrBladed = .FALSE. ! don't convert to Bladed format - CLSettingsFlags%WrVTK = .FALSE. ! don't convert to VTK format - CLSettingsFlags%WrUniform = .FALSE. ! don't convert to UniformWind format - - ! Initialize the driver settings to their default values (same as the CL -- command line -- values) - Settings = CLSettings - SettingsFlags = CLSettingsFlags - + CLSettings%ProgInfo = ProgInfo + Settings%ProgInfo = ProgInfo !-------------------------------------------------------------------------------------------------------------------------------- !-=-=- Parse the command line inputs -=-=- @@ -309,13 +249,14 @@ PROGRAM InflowWind_Driver - ! Sanity check: if an input points file is specified, make sure it actually exists. Open it if specified - + ! If output based a points file was requested IF ( SettingsFlags%PointsFile ) THEN + + ! Check if the points file exists, abort if not found INQUIRE( file=TRIM(Settings%PointsFileName), exist=TempFileExist ) IF ( TempFileExist .eqv. .FALSE. ) CALL ProgAbort( "Cannot find the points file "//TRIM(Settings%PointsFileName)) - ! Now read the file in and save the points + ! Now read the file in and save the points CALL ReadPointsFile( Settings%PointsFileName, PointsXYZ, ErrStat,ErrMsg ) IF ( ErrStat >= AbortErrLev ) THEN CALL ProgAbort( ErrMsg ) @@ -324,24 +265,31 @@ PROGRAM InflowWind_Driver ErrStat = ErrID_None ENDIF + ! Display number of points read from file CALL WrScr(NewLine//"Read "//TRIM(Num2LStr(SIZE(PointsXYZ,DIM=2)))//" points from '"//TRIM(Settings%PointsFileName)//"'.") - ! Make name for output - CALL GetRoot( Settings%PointsFileName, Settings%PointsOutputName(1) ) - Settings%PointsOutputName(1) = TRIM(Settings%PointsOutputName(1))//'.Velocity.dat' - - CALL GetRoot( Settings%PointsFileName, Settings%PointsOutputName(2) ) - Settings%PointsOutputName(2) = TRIM(Settings%PointsOutputName(2))//'.Velocity.FF.dat' - - CALL GetRoot( Settings%PointsFileName, Settings%PointsOutputName(3) ) - Settings%PointsOutputName(3) = TRIM(Settings%PointsOutputName(3))//'.Accel.FF.dat' + ! Create velocity output file name from points input file name + ! Display that file will be created, output message if it will be overwritten + CALL GetRoot( Settings%PointsFileName, Settings%PointsVelOutput%Name ) + Settings%PointsVelOutput%Name = TRIM(Settings%PointsVelOutput%Name)//'.dat' + CALL WrScr(NewLine//"Results output to '"//TRIM(Settings%PointsVelOutput%Name)//"'.") + INQUIRE( file=TRIM(Settings%PointsVelOutput%Name), exist=TempFileExist ) + IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsVelOutput%Name)) + + ! If wind accelerations were requested, create/open file, print overwrite warning of applicable + IF (SettingsFlags%OutputAccel) then + CALL GetRoot( Settings%PointsFileName, Settings%PointsAccOutput%Name ) + Settings%PointsAccOutput%Name = TRIM(Settings%PointsAccOutput%Name)//'.Acc.dat' + CALL WrScr(NewLine//"Results output to '"//TRIM(Settings%PointsAccOutput%Name)//"'.") + INQUIRE( file=TRIM(Settings%PointsAccOutput%Name), exist=TempFileExist ) + IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsAccOutput%Name)) + END IF - ! Display that file will be created, output message if it will be overwritten - do i = 1, size(Settings%PointsOutputName) - CALL WrScr(NewLine//"Results output to '"//TRIM(Settings%PointsOutputName(i))//"'.") - INQUIRE( file=TRIM(Settings%PointsOutputName(i)), exist=TempFileExist ) - IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsOutputName(i))) - end do + CALL GetRoot( Settings%PointsFileName, Settings%PointsRefOutput%Name ) + Settings%PointsRefOutput%Name = TRIM(Settings%PointsRefOutput%Name)//'.Ref.dat' + CALL WrScr(NewLine//"Results output to '"//TRIM(Settings%PointsRefOutput%Name)//"'.") + INQUIRE( file=TRIM(Settings%PointsRefOutput%Name), exist=TempFileExist ) + IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsRefOutput%Name)) ENDIF @@ -350,24 +298,24 @@ PROGRAM InflowWind_Driver IF ( SettingsFlags%FFTcalc ) THEN ! Make name for output IF ( SettingsFlags%DvrIptFile ) THEN - CALL GetRoot( Settings%DvrIptFileName, Settings%FFTOutputName ) + CALL GetRoot( Settings%DvrIptFileName, Settings%FFTOutput%Name ) ELSE - CALL GetRoot( Settings%IfWIptFileName, Settings%FFTOutputName ) + CALL GetRoot( Settings%IfWIptFileName, Settings%FFTOutput%Name ) ENDIF - Settings%FFTOutputName = TRIM(Settings%FFTOutputName)//'_'// & + Settings%FFTOutput%Name = TRIM(Settings%FFTOutput%Name)//'_'// & TRIM(Num2LStr(Settings%FFTcoord(1)))//'x_'// & TRIM(Num2LStr(Settings%FFTcoord(2)))//'y_'// & TRIM(Num2LStr(Settings%FFTcoord(3)))//'z'//'.FFT' - CALL WrScr(NewLine//"Writing FFT results to '"//TRIM(Settings%FFTOutputName)//"' for coordinate ( "// & + CALL WrScr(NewLine//"Writing FFT results to '"//TRIM(Settings%FFTOutput%Name)//"' for coordinate ( "// & TRIM(Num2LStr(Settings%FFTcoord(1)))//", "// & TRIM(Num2LStr(Settings%FFTcoord(2)))//", "// & TRIM(Num2LStr(Settings%FFTcoord(3)))//" ).") ! If the output file already exists, warn that it will be overwritten - INQUIRE( file=TRIM(Settings%FFTOutputName), exist=TempFileExist ) - IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%FFTOutputName)) + INQUIRE( file=TRIM(Settings%FFTOutput%Name), exist=TempFileExist ) + IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%FFTOutput%Name)) ENDIF @@ -378,12 +326,12 @@ PROGRAM InflowWind_Driver ! Create WindGrid output name IF ( SettingsFlags%DvrIptFile ) THEN - CALL GetRoot( Settings%DvrIptFileName, Settings%WindGridOutputName ) + CALL GetRoot( Settings%DvrIptFileName, Settings%WindGridOutput%Name ) ELSE - CALL GetRoot( Settings%IfWIptFileName, Settings%WindGridOutputName ) + CALL GetRoot( Settings%IfWIptFileName, Settings%WindGridOutput%Name ) ENDIF - Settings%WindGridOutputName = TRIM(Settings%WindGridOutputName)//'.WindGrid.out' + Settings%WindGridOutput%Name = TRIM(Settings%WindGridOutput%Name)//'.WindGrid.out' ! Output message if some verbosity. IF ( IfWDriver_Verbose >= 5_IntKi ) THEN @@ -474,8 +422,8 @@ PROGRAM InflowWind_Driver IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr('Calling InflowWind_Init...') - ! Set flag to calculate acceleration - InflowWind_InitInp%CalcAccel = .TRUE. + ! Set flag to calculate accelerations if requested + InflowWind_InitInp%OutputAccel = SettingsFlags%OutputAccel CALL InflowWind_Init( InflowWind_InitInp, InflowWind_u1, InflowWind_p, & InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & @@ -641,9 +589,8 @@ PROGRAM InflowWind_Driver IF ( SettingsFlags%WindGrid ) THEN ! Write the header for the WindGrid output file - CALL WindGridVel_OutputWrite( Settings%WindGridOutputUnit, Settings%WindGridOutputName, SettingsFlags%WindGridOutputInit, & - Settings, InflowWind_u1%PositionXYZ, InflowWind_y1%VelocityUVW, & - TimeNow, ErrStat, ErrMsg ) + CALL WindGridVel_OutputWrite( Settings%WindGridOutput, Settings, InflowWind_u1%PositionXYZ, & + InflowWind_y1%VelocityUVW, TimeNow, ErrStat, ErrMsg ) ! Setup the actual grid points -- scan order, Y,Z,X @@ -692,11 +639,13 @@ PROGRAM InflowWind_Driver ENDIF ! Allocate the array for the acceleration results -- 3 x Npoints - CALL AllocAry( InflowWind_y2%AccelUVW, 3, SIZE(InflowWind_u2%PositionXYZ, DIM=2 ), & - "Array of accelerations corresponding to Points file", ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) THEN - CALL DriverCleanup() - CALL ProgAbort( ErrMsg ) + IF ( SettingsFlags%OutputAccel ) THEN + CALL AllocAry( InflowWind_y2%AccelUVW, 3, SIZE(InflowWind_u2%PositionXYZ, DIM=2 ), & + "Array of accelerations corresponding to Points file", ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + ENDIF ENDIF ! WriteOutput info @@ -709,20 +658,33 @@ PROGRAM InflowWind_Driver InflowWind_y2%WriteOutput = InflowWind_y1%WriteOutput ENDIF - ! Now create the output files. Write header information - do i = 1, size(Settings%PointsOutputUnit) - CALL PointsVel_OutputWrite( Settings%PointsOutputUnit(i), Settings%PointsOutputName(i), & - SettingsFlags%PointsOutputInit(i), Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%VelocityUVW, TimeNow, ErrStat, ErrMsg ) - end do - - ENDIF - - - + ! Now create the velocity output file. Write header information + CALL PointData_OutputWrite( Settings%PointsVelOutput, Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, TimeNow, .true., ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL DriverCleanup() + CALL ProgAbort( 'Error creating point data velocity output file: '//trim(Settings%PointsVelOutput%Name) ) + ENDIF + ! If point acceleration calculate was requested, create file and write header + IF ( SettingsFlags%OutputAccel ) THEN + CALL PointData_OutputWrite( Settings%PointsAccOutput, Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%AccelUVW, TimeNow, .false., ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL DriverCleanup() + CALL ProgAbort( 'Error creating point data acceleration output file: '//trim(Settings%PointsAccOutput%Name) ) + ENDIF + END IF + ! Now create the reference velocity output file. Write header information + CALL PointData_OutputWrite( Settings%PointsRefOutput, Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, TimeNow, .true., ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) THEN + CALL DriverCleanup() + CALL ProgAbort( 'Error creating point data velocity output file: '//trim(Settings%PointsRefOutput%Name) ) + ENDIF + ENDIF ! FFT setup IF ( SettingsFlags%FFTcalc ) THEN @@ -810,97 +772,91 @@ PROGRAM InflowWind_Driver TimeNow = Settings%TStart + Settings%DT*(ITime) - ! Get results for WindGrid data from IfW -- WindGrid may contain only a single point at the hub if the WindGrid flag isn't set. - CALL InflowWind_CalcOutput( TimeNow, InflowWind_u1, InflowWind_p, & - InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & - InflowWind_y1, InflowWind_MiscVars, ErrStat, ErrMsg) + IF ( SettingsFlags%WindGrid ) THEN + ! Get results for WindGrid data from IfW -- WindGrid may contain only a single point at the hub if the WindGrid flag isn't set. + CALL InflowWind_CalcOutput( TimeNow, InflowWind_u1, InflowWind_p, & + InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & + InflowWind_y1, InflowWind_MiscVars, ErrStat, ErrMsg) + ! Make sure no errors occured that give us reason to terminate now. + IF ( ErrStat >= AbortErrLev ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( IfWDriver_Verbose >= 10_IntKi ) ) THEN + CALL WrScr(NewLine//' Timestep '//TRIM(Num2LStr(ITime))// & + ' InflowWind_Calc returned: ErrStat: '//TRIM(Num2LStr(ErrStat))//NewLine// & + ' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ENDIF - ! Make sure no errors occured that give us reason to terminate now. - IF ( ErrStat >= AbortErrLev ) THEN - CALL DriverCleanup() - CALL ProgAbort( ErrMsg ) - ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( IfWDriver_Verbose >= 10_IntKi ) ) THEN - CALL WrScr(NewLine//' Timestep '//TRIM(Num2LStr(ITime))// & - ' InflowWind_Calc returned: ErrStat: '//TRIM(Num2LStr(ErrStat))// & - NewLine//' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ! Write the WindGrid results to a file for this timestep + CALL WindGridVel_OutputWrite( Settings%WindGridOutput, Settings, & + InflowWind_u1%PositionXYZ, InflowWind_y1%VelocityUVW, & + TimeNow, ErrStat, ErrMsg ) ENDIF + ! If point results were requested + IF ( SettingsFlags%PointsFile ) THEN + + ! Calculate velocity/acceleration at points + InflowWind_p%FlowField%Enabled = .true. + CALL InflowWind_CalcOutput( TimeNow, InflowWind_u2, InflowWind_p, & + InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & + InflowWind_y2, InflowWind_MiscVars, ErrStat, ErrMsg) + IF ( ErrStat >= AbortErrLev ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + ELSEIF ( ( ErrStat /= ErrID_None ) .AND. ( IfWDriver_Verbose >= 10_IntKi ) ) THEN + CALL WrScr(NewLine//' Timestep '//TRIM(Num2LStr(ITime))// & + ' InflowWind_Calc returned: ErrStat: '//TRIM(Num2LStr(ErrStat))//NewLine// & + ' ErrMsg: '//TRIM(ErrMsg)//NewLine) + ENDIF + + ! Output the Points results for this timestep + CALL PointData_OutputWrite( Settings%PointsVelOutput, Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, TimeNow, .true., ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + END IF - ! Write the WindGrid results to a file for this timestep - IF ( SettingsFlags%WindGrid ) THEN - - CALL WindGridVel_OutputWrite( Settings%WindGridOutputUnit, Settings%WindGridOutputName, SettingsFlags%WindGridOutputInit, & - Settings, InflowWind_u1%PositionXYZ, InflowWind_y1%VelocityUVW, & - TimeNow, ErrStat, ErrMsg ) + ! If acceleration at points was requested, output values + IF ( SettingsFlags%OutputAccel ) then + CALL PointData_OutputWrite( Settings%PointsAccOutput, Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%AccelUVW, TimeNow, .false., ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + END IF + END IF - ENDIF + ! Calculate reference velocity and output + InflowWind_p%FlowField%Enabled = .false. + CALL InflowWind_CalcOutput( TimeNow, InflowWind_u2, InflowWind_p, & + InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & + InflowWind_y2, InflowWind_MiscVars, ErrStat, ErrMsg) + CALL PointData_OutputWrite( Settings%PointsRefOutput, Settings, InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, TimeNow, .true., ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL DriverCleanup() + CALL ProgAbort( ErrMsg ) + END IF + + END IF ! Calculate results for FFT if we are performing one IF ( SettingsFlags%FFTcalc ) THEN - ! Get the results from IfW + ! Get the results from IfW ! CALL InflowWind_CalcOutput() - ! Copy results over to the array for storage + ! Copy results over to the array for storage ! FFTdata(ITime,:) = - - + ENDIF - ENDDO ! ITime loop - ! Calculate results for the Points and export them for this timestep - IF ( SettingsFlags%PointsFile ) THEN - - call CPU_TIME( Timer2(1) ) - - ! Get results for Points data from IfW - do ITime = 0, MAX( Settings%NumTimeSteps, 1_IntKi ) - TimeNow = Settings%TStart + Settings%DT*(ITime) - - call InflowWind_CalcOutput( TimeNow, InflowWind_u2, InflowWind_p, & - InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & - InflowWind_y2, InflowWind_MiscVars, ErrStat, ErrMsg) - - ! Output the Points results for this timestep - call PointsVel_OutputWrite( Settings%PointsOutputUnit(1), Settings%PointsOutputName(1), & - SettingsFlags%PointsOutputInit(1), Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%VelocityUVW, TimeNow, ErrStat, ErrMsg ) - end do - - call CPU_TIME(Timer2(2)) - call WrScr(NewLine//'Elapsed time IfW: '//TRIM(Num2LStr(Timer2(2)-Timer2(1)))//' seconds') - call CPU_TIME( Timer2(1) ) - - ! Get results for Points data from FlowField - do ITime = 0, MAX( Settings%NumTimeSteps, 1_IntKi ) - TimeNow = Settings%TStart + Settings%DT*(ITime) - - call FlowField_GetVelAcc(InflowWind_p%FlowField, 0, TimeNow, & - InflowWind_u2%PositionXYZ, & - InflowWind_y2%VelocityUVW, & - InflowWind_y2%AccelUVW, ErrStat, ErrMsg) - - ! Output the Points velocity results for this timestep - call PointsVel_OutputWrite( Settings%PointsOutputUnit(2), Settings%PointsOutputName(2), & - SettingsFlags%PointsOutputInit(2), Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%VelocityUVW, TimeNow, ErrStat, ErrMsg ) - - ! Output the Points acceleration results for this timestep - call PointsVel_OutputWrite( Settings%PointsOutputUnit(3), Settings%PointsOutputName(3), & - SettingsFlags%PointsOutputInit(3), Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%AccelUVW, TimeNow, ErrStat, ErrMsg ) - end do - - call CPU_TIME(Timer2(2)) - call WrScr(NewLine//'Elapsed time FF: '//TRIM(Num2LStr(Timer2(2)-Timer2(1)))//' seconds') - - end if - - ! output table of results for the outlist comparison and check if very verbose -- print statements are ! used because we don't want linewrapping. @@ -1031,13 +987,12 @@ PROGRAM InflowWind_Driver SUBROUTINE DriverCleanup() - - if (Settings%WindGridOutputUnit > -1_IntKi ) CLOSE( Settings%WindGridOutputUnit ) - do i = 1, size(Settings%PointsOutputUnit) - if (Settings%PointsOutputUnit(i) > -1_IntKi ) CLOSE( Settings%PointsOutputUnit(i) ) - end do - if (Settings%FFTOutputUnit > -1_IntKi ) CLOSE( Settings%FFTOutputUnit ) - + ! Close output files that may have been opened + if (Settings%WindGridOutput%Unit > -1_IntKi ) CLOSE( Settings%WindGridOutput%Unit ) + if (Settings%PointsVelOutput%Unit > -1_IntKi ) CLOSE( Settings%PointsVelOutput%Unit ) + if (Settings%PointsAccOutput%Unit > -1_IntKi ) CLOSE( Settings%PointsAccOutput%Unit ) + if (Settings%PointsRefOutput%Unit > -1_IntKi ) CLOSE( Settings%PointsRefOutput%Unit ) + if (Settings%FFTOutput%Unit > -1_IntKi ) CLOSE( Settings%FFTOutput%Unit ) ! Find out how long this actually took CALL CPU_TIME( Timer(2) ) diff --git a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 index 8a5083ef6d..34b6639794 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 @@ -77,6 +77,7 @@ SUBROUTINE DispHelpText( ErrStat, ErrMsg ) CALL WrScr(" "//SwChar//"HAWC -- convert contents of to HAWC format ") CALL WrScr(" "//SwChar//"Bladed -- convert contents of to Bladed format ") CALL WrScr(" "//SwChar//"vtk -- convert contents of to vtk format ") + CALL WrScr(" "//SwChar//"accel -- calculate wind acceleration in addition to velocity") CALL WrScr(" "//SwChar//"help -- print this help menu and exit") CALL WrScr("") CALL WrScr(" Notes:") @@ -327,6 +328,9 @@ SUBROUTINE ParseArg( CLSettings, CLFlags, ThisArgUC, ThisArg, ifwFlagSet, ErrSta ELSEIF ( TRIM(ThisArgUC) == "UNIFORM" ) THEN CLFlags%WrUniform = .TRUE. RETURN + ELSEIF ( TRIM(ThisArgUC) == "ACCEL" ) THEN + CLFlags%OutputAccel = .TRUE. + RETURN ELSE CALL SetErrStat( ErrID_Warn," Unrecognized option '"//SwChar//TRIM(ThisArg)//"'. Ignoring. Use option "//SwChar//"help for list of options.", & ErrStat,ErrMsg,'ParseArg') @@ -1073,7 +1077,15 @@ SUBROUTINE ReadDvrIptFile( DvrFileName, DvrFlags, DvrSettings, ProgInfo, ErrStat IF ( PathIsRelative( DvrSettings%PointsFileName ) ) DvrSettings%PointsFileName = TRIM(PriPath)//TRIM(DvrSettings%PointsFileName) - + ! CalcAccel - calculate wind acceleration (unused if .not. DvrFlags%PointsFile) + CALL ReadVar( UnIn, FileName,DvrFlags%OutputAccel, 'CalcAccel', ' Calc and output wind acceleration', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF !------------------------------------------------------------------------------------------------- ! gridded data output @@ -1341,6 +1353,8 @@ SUBROUTINE UpdateSettingsWithCL( DvrFlags, DvrSettings, CLFlags, CLSettings, DVR DvrFlags%WrVTK = DvrFlags%WrVTK .or. CLFlags%WrVTK ! create file if specified in either place DvrFlags%WrUniform = DvrFlags%WrUniform .or. CLFlags%WrUniform ! create file if specified in either place + DvrFlags%OutputAccel = DvrFlags%OutputAccel .or. CLFlags%OutputAccel ! calculate acceleration if specified in either place + ! ! Due to the complexity, we are handling overwriting driver input file settings with ! ! command line settings and the instance where no driver input file is read separately. ! IF ( DVRIPT .AND. DvrFlags%WindGrid ) THEN @@ -2153,7 +2167,7 @@ SUBROUTINE WindGridMessage( Settings, ToFile, Msg, MsgLen ) IF ( ToFile ) THEN Msg='# ' ELSE - Msg="Requested wind grid data will be written to "//TRIM(Settings%WindGridOutputName)//'.' + Msg="Requested wind grid data will be written to "//TRIM(Settings%WindGridOutput%Name)//'.' ENDIF Msg = TRIM(Msg)//" Requested data:"//NewLine @@ -2262,11 +2276,8 @@ SUBROUTINE WindGridMessage( Settings, ToFile, Msg, MsgLen ) !> This subroutine outputs the results of the WindGrid calculations information at each timestep. -SUBROUTINE WindGridVel_OutputWrite (FileUnit, FileName, Initialized, Settings, GridXYZ, GridVel, TIME, ErrStat, ErrMsg) - - INTEGER(IntKi), INTENT(INOUT) :: FileUnit !< Unit number for the output file - CHARACTER(*), INTENT(IN ) :: FileName !< Name of the current unit number - LOGICAL, INTENT(INOUT) :: Initialized !< Was this file started before? +SUBROUTINE WindGridVel_OutputWrite (OutFile, Settings, GridXYZ, GridVel, TIME, ErrStat, ErrMsg) + TYPE(OutputFile), INTENT(INOUT) :: OutFile TYPE(IfWDriver_Settings), INTENT(IN ) :: Settings !< Settings for IfW driver REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: GridXYZ(:,:) !< The position grid passed in REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: GridVel(:,:) !< The velocity grid passed in @@ -2292,39 +2303,39 @@ SUBROUTINE WindGridVel_OutputWrite (FileUnit, FileName, Initialized, Settings, G ! If it hasn't been initially written to, do this then exit. Otherwise set a few things and continue. - IF ( .NOT. Initialized ) THEN + IF ( .NOT. OutFile%Initialized ) THEN - CALL GetNewUnit( FileUnit ) - CALL OpenFOutFile( FileUnit, TRIM(FileName), ErrStatTmp, ErrMsgTmp ) + CALL GetNewUnit( OutFile%Unit ) + CALL OpenFOutFile( OutFile%Unit, TRIM(OutFile%Name), ErrStatTmp, ErrMsgTmp ) CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'WindGridVel_OutputWrite' ) IF ( ErrStat >= AbortErrLev ) RETURN - Initialized = .TRUE. + OutFile%Initialized = .TRUE. ! Write header section - WRITE( FileUnit,'(A)', IOSTAT=ErrStatTmp ) '## This file was generated by '//TRIM(GetNVD(Settings%ProgInfo))// & + WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file was generated by '//TRIM(GetNVD(Settings%ProgInfo))// & ' on '//CurDate()//' at '//CurTime()//'.' - WRITE( FileUnit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wind velocity at a grid of points at each '// & + WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wind velocity at a grid of points at each '// & 'requested timestep' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '## It is arranged as blocks of X,Y,Z,U,V,W at each timestep' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '## Each block is separated by two blank lines for use in gnuplot' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# ' + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## It is arranged as blocks of X,Y,Z,U,V,W at each timestep' + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## Each block is separated by two blank lines for use in gnuplot' + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' CALL WindGridMessage( Settings, .TRUE., ErrMsgTmp, LenErrMsgTmp ) - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) ErrMsgTmp(1:LenErrMsgTmp) - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# ' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# ' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# X Y Z '// & + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) ErrMsgTmp(1:LenErrMsgTmp) + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# X Y Z '// & ' U V W' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# (m) (m) (m) '// & + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# (m) (m) (m) '// & ' (m/s) (m/s) (m/s)' ELSE - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) NewLine//NewLine - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# Time: '//TRIM(Num2LStr(TIME)) + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) NewLine//NewLine + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# Time: '//TRIM(Num2LStr(TIME)) DO I = 1,SIZE(GridXYZ,DIM=2) - WRITE (FileUnit,WindVelFmt, IOSTAT=ErrStatTmp ) GridXYZ(1,I),GridXYZ(2,I),GridXYZ(3,I),GridVel(1,I),GridVel(2,I),GridVel(3,I) + WRITE (OutFile%Unit,WindVelFmt, IOSTAT=ErrStatTmp ) GridXYZ(1,I),GridXYZ(2,I),GridXYZ(3,I),GridVel(1,I),GridVel(2,I),GridVel(3,I) ENDDO @@ -2333,22 +2344,20 @@ SUBROUTINE WindGridVel_OutputWrite (FileUnit, FileName, Initialized, Settings, G END SUBROUTINE WindGridVel_OutputWrite -SUBROUTINE PointsVel_OutputWrite (FileUnit, FileName, Initialized, Settings, GridXYZ, GridVel, TIME, ErrStat, ErrMsg) +SUBROUTINE PointData_OutputWrite (OutFile, Settings, GridXYZ, GridDat, TIME, IsVel, ErrStat, ErrMsg) - INTEGER(IntKi), INTENT(INOUT) :: FileUnit !< Unit number for the output file - CHARACTER(*), INTENT(IN ) :: FileName !< Name of the current unit number - LOGICAL, INTENT(INOUT) :: Initialized !< Was this file started before? + TYPE(OutputFile), INTENT(INOUT) :: OutFile TYPE(IfWDriver_Settings), INTENT(IN ) :: Settings !< Settings for IfW driver REAL(ReKi), INTENT(IN ) :: GridXYZ(:,:) !< The position grid passed in - REAL(ReKi), INTENT(IN ) :: GridVel(:,:) !< The velocity grid passed in + REAL(ReKi), INTENT(IN ) :: GridDat(:,:) !< The velocity grid passed in REAL(DbKi), INTENT(IN ) :: TIME !< The current time + LOGICAL, INTENT(IN ) :: IsVel !< Is this velocity output INTEGER(IntKi), INTENT( OUT) :: ErrStat !< returns a non-zero value when an error occurs CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! Temporary local variables INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for the status of error message CHARACTER(2048) :: ErrMsgTmp !< Temporary variable for the error message - INTEGER(IntKi) :: LenErrMsgTmp !< Length of ErrMsgTmp (for getting WindGrid info) INTEGER(IntKi) :: I !< Generic counter CHARACTER(61) :: NameUnitFmt !< Format specifier for the output file for channel names and units @@ -2364,38 +2373,48 @@ SUBROUTINE PointsVel_OutputWrite (FileUnit, FileName, Initialized, Settings, Gri ! If it hasn't been initially written to, do this then exit. Otherwise set a few things and continue. - IF ( .NOT. Initialized ) THEN + IF ( .NOT. OutFile%Initialized ) THEN - CALL GetNewUnit( FileUnit ) - CALL OpenFOutFile( FileUnit, TRIM(FileName), ErrStatTmp, ErrMsgTmp ) - CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'PointsVel_OutputWrite' ) + CALL GetNewUnit( OutFile%Unit ) + CALL OpenFOutFile( OutFile%Unit, TRIM(OutFile%Name), ErrStatTmp, ErrMsgTmp ) + CALL SetErrStat( ErrStatTmp, ErrMsgTmp, ErrStat, ErrMsg, 'PointData_OutputWrite' ) IF ( ErrStat >= AbortErrLev ) RETURN - Initialized = .TRUE. + OutFile%Initialized = .TRUE. ! Write header section - WRITE( FileUnit,'(A)', IOSTAT=ErrStatTmp ) '## This file was generated by '//TRIM(GetNVD(Settings%ProgInfo))// & + WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file was generated by '//TRIM(GetNVD(Settings%ProgInfo))// & ' on '//CurDate()//' at '//CurTime()//'.' - WRITE( FileUnit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wind velocity at the '// & - TRIM(Num2LStr(SIZE(GridXYZ,DIM=2)))//' points specified in the '// & - 'file '//TRIM(Settings%PointsFileName)//'.' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# ' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# ' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# ' - WRITE (FileUnit,'(A)', IOSTAT=ErrStatTmp ) '# ' - WRITE (FileUnit, NameUnitFmt, IOSTAT=ErrStatTmp ) 'T', 'X', 'Y', 'Z', 'U', 'V', 'W' - WRITE (FileUnit, NameUnitFmt, IOSTAT=ErrStatTmp ) '(s)', '(m)', '(m)', '(m)', '(m/s)', '(m/s)', '(m/s)' + if (IsVel) then + WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wind velocity at the '// & + TRIM(Num2LStr(SIZE(GridXYZ,DIM=2)))//' points specified in the '// & + 'file '//TRIM(Settings%PointsFileName)//'.' + else + WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wind acceleration at the '// & + TRIM(Num2LStr(SIZE(GridXYZ,DIM=2)))//' points specified in the '// & + 'file '//TRIM(Settings%PointsFileName)//'.' + end if + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' + WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' + WRITE (OutFile%Unit, NameUnitFmt, IOSTAT=ErrStatTmp ) 'T', 'X', 'Y', 'Z', 'U', 'V', 'W' + if (IsVel) then + WRITE (OutFile%Unit, NameUnitFmt, IOSTAT=ErrStatTmp ) '(s)', '(m)', '(m)', '(m)', '(m/s)', '(m/s)', '(m/s)' + else + WRITE (OutFile%Unit, NameUnitFmt, IOSTAT=ErrStatTmp ) '(s)', '(m)', '(m)', '(m)', '(m/s/s)', '(m/s/s)', '(m/s/s)' + end if ELSE DO I = 1,SIZE(GridXYZ,DIM=2) - WRITE (FileUnit, PointsVelFmt, IOSTAT=ErrStatTmp ) TIME, GridXYZ(1,I), GridXYZ(2,I), GridXYZ(3,I), GridVel(1,I), GridVel(2,I), GridVel(3,I) + WRITE (OutFile%Unit, PointsVelFmt, IOSTAT=ErrStatTmp ) TIME, GridXYZ(1,I), GridXYZ(2,I), GridXYZ(3,I), GridDat(1,I), GridDat(2,I), GridDat(3,I) ENDDO ENDIF -END SUBROUTINE PointsVel_OutputWrite +END SUBROUTINE PointData_OutputWrite @@ -2411,8 +2430,8 @@ SUBROUTINE printSettings( DvrFlags, DvrSettings ) CALL WrScr(' DvrIptFile: '//FLAG(DvrFlags%DvrIptFile)// ' '//TRIM(DvrSettings%DvrIptFileName)) CALL WrScr(' IfWIptFile: '//FLAG(DvrFlags%IfWIptFile)// ' '//TRIM(DvrSettings%IfWIptFileName)) CALL WrScr(' PointsFile: '//FLAG(DvrFlags%PointsFile)// ' '//TRIM(DvrSettings%PointsFileName)) - CALL WrScr(' FFTOutputName: '//FLAG(DvrFlags%FFTcalc)// ' '//TRIM(DvrSettings%FFTOutputName)) - CALL WrScr(' WindGridOutName: '//FLAG(DvrFlags%WindGrid)// ' '//TRIM(DvrSettings%WindGridOutputName)) + CALL WrScr(' FFTOutputName: '//FLAG(DvrFlags%FFTcalc)// ' '//TRIM(DvrSettings%FFTOutput%Name)) + CALL WrScr(' WindGridOutName: '//FLAG(DvrFlags%WindGrid)// ' '//TRIM(DvrSettings%WindGridOutput%Name)) CALL WrScr(' Summary: '//FLAG(DvrFlags%Summary)) CALL WrScr(' SummaryFile: '//FLAG(DvrFlags%SummaryFile)// ' '//TRIM(DvrSettings%SummaryFileName)) CALL WrScr(' TStart: '//FLAG(DvrFlags%TStart)// ' '//TRIM(Num2LStr(DvrSettings%TStart))) @@ -2443,13 +2462,11 @@ SUBROUTINE printSettings( DvrFlags, DvrSettings ) CALL WrScr(' Dx: '//FLAG(DvrFlags%Dx)// ' '//TRIM(Num2LStr(DvrSettings%GridDelta(1)))) CALL WrScr(' Dy: '//FLAG(DvrFlags%Dy)// ' '//TRIM(Num2LStr(DvrSettings%GridDelta(2)))) CALL WrScr(' Dz: '//FLAG(DvrFlags%Dz)// ' '//TRIM(Num2LStr(DvrSettings%GridDelta(3)))) - CALL WrScr(' WindGridOutputInit: '//FLAG(DvrFlags%WindGridOutputInit)//' Unit #: '//TRIM(Num2LStr(DvrSettings%WindGridOutputUnit))) + CALL WrScr(' WindGridOutputInit: '//FLAG(DvrSettings%WindGridOutput%Initialized)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%WindGridOutput%Unit))) end if - CALL WrScr(' FFTOutputInit: '//FLAG(DvrFlags%FFTOutputInit)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%FFTOutputUnit))) - do i = 1, size(DvrSettings%PointsOutputUnit) - CALL WrScr(' PointsOutputInit: '//FLAG(DvrFlags%PointsOutputInit(i))// ' Unit #: '//TRIM(Num2LStr(DvrSettings%PointsOutputUnit(i)))) - end do - RETURN + CALL WrScr(' FFTOutputInit: '//FLAG(DvrSettings%FFTOutput%Initialized)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%FFTOutput%Unit))) + CALL WrScr(' PointsVelOutputInit: '//FLAG(DvrSettings%PointsVelOutput%Initialized)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%PointsVelOutput%Unit))) + CALL WrScr(' PointsAccOutputInit: '//FLAG(DvrSettings%PointsVelOutput%Initialized)// ' Unit #: '//TRIM(Num2LStr(DvrSettings%PointsVelOutput%Unit))) END SUBROUTINE printSettings diff --git a/modules/inflowwind/src/InflowWind_Driver_Types.f90 b/modules/inflowwind/src/InflowWind_Driver_Types.f90 index 8b3cae3a64..cd1128c9a6 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Types.f90 @@ -31,6 +31,12 @@ MODULE InflowWind_Driver_Types IMPLICIT NONE + TYPE OutputFile + LOGICAL :: Initialized = .FALSE. !< Flag indicating that file has been initialized + CHARACTER(1024) :: Name = "" !< Filename for output from points read in from points file + INTEGER(IntKi) :: Unit = -1 !< Unit number for the output file for the Points file output + END TYPE + !> This contains flags to note if the settings were made. This same data structure is !! used both during the driver input file and the command line options. !! @@ -38,7 +44,7 @@ MODULE InflowWind_Driver_Types !! it is handled internally by InflowWInd. !! !! NOTE: The wind direction is specified by the InflowWind input file. - TYPE :: IfWDriver_Flags + TYPE :: IfWDriver_Flags LOGICAL :: DvrIptFile = .FALSE. !< Was an input file name given on the command line? LOGICAL :: IfWIptFile = .FALSE. !< Was an InflowWind input file requested? LOGICAL :: Summary = .FALSE. !< create a summary at command line? (data extents in the wind file) @@ -59,11 +65,9 @@ MODULE InflowWind_Driver_Types LOGICAL :: Dy = .FALSE. !< speficied a resolution in y LOGICAL :: Dz = .FALSE. !< specified a resolution in z - LOGICAL :: PointsFile = .FALSE. !< points filename to read in -- command line option only + LOGICAL :: PointsFile = .FALSE. !< points filename to read in + LOGICAL :: OutputAccel = .FALSE. !< flag to calculate and output wind acceleration in addition to velocity - LOGICAL :: WindGridOutputInit = .FALSE. !< Is the WindGridOut file initialized - LOGICAL :: PointsOutputInit(3) = .FALSE. !< Is the Points output file initialized - LOGICAL :: FFTOutputInit = .FALSE. !< Is the FFT output file initialized LOGICAL :: Verbose = .FALSE. !< Verbose error reporting LOGICAL :: VVerbose = .FALSE. !< Very Verbose error reporting @@ -71,42 +75,38 @@ MODULE InflowWind_Driver_Types LOGICAL :: WrBladed = .FALSE. !< Requested file conversion to Bladed format? LOGICAL :: WrVTK = .FALSE. !< Requested file output as VTK? LOGICAL :: WrUniform = .FALSE. !< Requested file output as Uniform wind format? - END TYPE IfWDriver_Flags + END TYPE IfWDriver_Flags ! This contains all the settings (possible passed in arguments). - TYPE :: IfWDriver_Settings - CHARACTER(1024) :: DvrIptFileName !< Driver input file name - CHARACTER(1024) :: IfWIptFileName !< Filename of InflowWind input file to read (if no driver input file) - CHARACTER(1024) :: SummaryFileName !< Filename for the summary information output - - CHARACTER(1024) :: PointsFileName !< Filename of points file to read in - CHARACTER(1024) :: PointsOutputName(3) !< Filename for output from points read in from points file - CHARACTER(1024) :: FFTOutputName !< Filename for output from points read in from points file - CHARACTER(1024) :: WindGridOutputName !< Filename for output from points read in from points file - - INTEGER(IntKi) :: WindGridOutputUnit !< Unit number for the output file for the wind grid data - INTEGER(IntKi) :: PointsOutputUnit(3) !< Unit number for the output file for the Points file output - INTEGER(IntKi) :: FFTOutputUnit !< Unit number for the output file for the FFT results - - INTEGER(IntKi) :: NumTimeSteps !< Number of timesteps - REAL(DbKi) :: DT !< resolution of time - REAL(DbKi) :: TStart !< range of time -- end time converted from TRange (command line option only) - - - REAL(ReKi) :: FFTcoord(1:3) !< (x,y,z) coordinate to do an FFT at - - REAL(ReKi) :: GridDelta(1:3) !< (GridDx,GridDy,GridDz) -- grid point spacing - INTEGER(IntKi) :: GridN(1:3) !< (GridNx,GridNy,GridNz) -- number of grid points - - REAL(ReKi) :: XRange(1:2) !< Range in the x-direction for the gridded data - REAL(ReKi) :: YRange(1:2) !< Range in the y-direction for the gridded data - REAL(ReKi) :: ZRange(1:2) !< Range in the z-direction for the gridded data - - TYPE(ProgDesc) :: ProgInfo !< Program info - TYPE(ProgDesc) :: IfWProgInfo !< Program info for InflowWind - - END TYPE IfWDriver_Settings + TYPE :: IfWDriver_Settings + CHARACTER(1024) :: DvrIptFileName = "" !< Driver input file name + CHARACTER(1024) :: IfWIptFileName = "" !< Filename of InflowWind input file to read (if no driver input file) + CHARACTER(1024) :: SummaryFileName = "" !< Filename for the summary information output + + CHARACTER(1024) :: PointsFileName = "" !< Filename of points file to read in + + INTEGER(IntKi) :: NumTimeSteps = 0 !< Number of timesteps + REAL(DbKi) :: DT = 0.0_DbKi !< resolution of time + REAL(DbKi) :: TStart = 0.0_DbKi !< range of time -- end time converted from TRange (command line option only) + + REAL(ReKi) :: FFTcoord(1:3) = 0.0_ReKi !< (x,y,z) coordinate to do an FFT at + + REAL(ReKi) :: GridDelta(1:3) = 0.0_ReKi !< (GridDx,GridDy,GridDz) -- grid point spacing + INTEGER(IntKi) :: GridN(1:3) = 1_IntKi !< (GridNx,GridNy,GridNz) -- number of grid points + + REAL(ReKi) :: XRange(1:2) = 0.0_ReKi !< Range in the x-direction for the gridded data + REAL(ReKi) :: YRange(1:2) = 0.0_ReKi !< Range in the y-direction for the gridded data + REAL(ReKi) :: ZRange(1:2) = 0.0_ReKi !< Range in the z-direction for the gridded data + + TYPE(ProgDesc) :: ProgInfo !< Program info + TYPE(OutputFile) :: WindGridOutput + TYPE(OutputFile) :: FFTOutput + TYPE(OutputFile) :: PointsVelOutput + TYPE(OutputFile) :: PointsAccOutput + TYPE(OutputFile) :: PointsRefOutput + + END TYPE IfWDriver_Settings END MODULE InflowWind_Driver_Types diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index 50739215bd..62e655f9d3 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -900,6 +900,14 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM IF ( ErrStat>= AbortErrLev ) RETURN m%WindViUVW = 0.0_ReKi + ! If output acceleration flag is set, allocate array to hold wind point accelerations. + IF (InitInp%OutputAccel) THEN + CALL AllocAry( m%WindAiUVW, 3, p%NWindVel, "Array of wind accelerations corresponding to the WindViLists", TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) RETURN + m%WindAiUVW = 0.0_ReKi + END IF + CALL AllocAry( m%u_Hub%PositionXYZ, 3, 1, "Array of positions for hub values", TmpErrStat, TmpErrMsg ) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) CALL AllocAry( m%y_Hub%VelocityUVW, 3, 1, "Array of velocities for hub values", TmpErrStat, TmpErrMsg ) @@ -1450,7 +1458,7 @@ END SUBROUTINE InflowWind_CloseSumFile SUBROUTINE CalculateOutput( Time, InputData, p, x, xd, z, OtherStates, y, m, FillWrOut, ErrStat, ErrMsg ) - + USE FlowField, only: FlowField_GetVelAcc IMPLICIT NONE @@ -1490,6 +1498,24 @@ SUBROUTINE CalculateOutput( Time, InputData, p, x, xd, z, OtherStates, y, m, Fil ErrStat = ErrID_None ErrMsg = "" + !----------------------------------------------------------------------- + ! Points coordinate transforms from to global to wind file coordinates + !----------------------------------------------------------------------- + + if (p%FlowField%Enabled) then + CALL FlowField_GetVelAcc(p%FlowField, 0, Time, InputData%PositionXYZ, & + y%VelocityUVW, y%AccelUVW, TmpErrStat, TmpErrMsg) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + ! Call IfW_UniformWind_CalcOutput again in order to get the values needed for the OutList -- note that we do not report errors from this + IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN + CALL FlowField_GetVelAcc(p%FlowField, 0, Time, p%WindViXYZ, & + m%WindViUVW, m%WindAiUVW, TmpErrStat, TmpErrMsg) + ENDIF + return + end if + !----------------------------------------------------------------------- ! Points coordinate transforms from to global to wind file coordinates diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index 4aea0a45ad..a56750358b 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -129,7 +129,7 @@ MODULE InflowWind_Types TYPE(FileInfoType) :: PassedFileData !< If we don't use the input file, pass everything through this [-] LOGICAL :: WindType2UseInputFile = .TRUE. !< Flag for toggling file based IO in wind type 2. [-] TYPE(FileInfoType) :: WindType2Data !< Optional slot for wind type 2 data if file IO is not used. [-] - LOGICAL :: CalcAccel = .FALSE. !< Flag to calculate acceleration. [-] + LOGICAL :: OutputAccel = .FALSE. !< Flag to output wind acceleration [-] TYPE(Lidar_InitInputType) :: lidar !< InitInput for lidar data [-] TYPE(IfW_4Dext_InitInputType) :: FDext !< InitInput for 4D external wind data [-] REAL(ReKi) :: RadAvg !< Radius (from hub) used for averaging wind speed [-] @@ -227,6 +227,7 @@ MODULE InflowWind_Types TYPE(IfW_4Dext_MiscVarType) :: FDext !< MiscVars from FDext [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AllOuts !< An array holding the value of all of the calculated (not only selected) output channels [see OutListParameters.xlsx spreadsheet] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViUVW !< List of UVW velocities for wind velocity measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ [meters/second] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindAiUVW !< List of UVW accelerations for wind acceleration measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ [m/s^2] TYPE(InflowWind_InputType) :: u_Avg !< inputs for computing rotor-averaged values [-] TYPE(InflowWind_OutputType) :: y_Avg !< outputs for computing rotor-averaged values [-] TYPE(InflowWind_InputType) :: u_Hub !< inputs for computing hub values [-] @@ -1210,7 +1211,7 @@ SUBROUTINE InflowWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCod CALL NWTC_Library_Copyfileinfotype( SrcInitInputData%WindType2Data, DstInitInputData%WindType2Data, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - DstInitInputData%CalcAccel = SrcInitInputData%CalcAccel + DstInitInputData%OutputAccel = SrcInitInputData%OutputAccel CALL Lidar_CopyInitInput( SrcInitInputData%lidar, DstInitInputData%lidar, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -1330,7 +1331,7 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 1 ! CalcAccel + Int_BufSz = Int_BufSz + 1 ! OutputAccel Int_BufSz = Int_BufSz + 3 ! lidar: size of buffers for each call to pack subtype CALL Lidar_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%lidar, ErrStat2, ErrMsg2, .TRUE. ) ! lidar CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1471,7 +1472,7 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - IntKiBuf(Int_Xferred) = TRANSFER(InData%CalcAccel, IntKiBuf(1)) + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutputAccel, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 CALL Lidar_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%lidar, ErrStat2, ErrMsg2, OnlySize ) ! lidar CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1661,7 +1662,7 @@ SUBROUTINE InflowWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - OutData%CalcAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%CalcAccel) + OutData%OutputAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutputAccel) Int_Xferred = Int_Xferred + 1 Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 @@ -5181,6 +5182,20 @@ SUBROUTINE InflowWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, Err END IF END IF DstMiscData%WindViUVW = SrcMiscData%WindViUVW +ENDIF +IF (ALLOCATED(SrcMiscData%WindAiUVW)) THEN + i1_l = LBOUND(SrcMiscData%WindAiUVW,1) + i1_u = UBOUND(SrcMiscData%WindAiUVW,1) + i2_l = LBOUND(SrcMiscData%WindAiUVW,2) + i2_u = UBOUND(SrcMiscData%WindAiUVW,2) + IF (.NOT. ALLOCATED(DstMiscData%WindAiUVW)) THEN + ALLOCATE(DstMiscData%WindAiUVW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%WindAiUVW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstMiscData%WindAiUVW = SrcMiscData%WindAiUVW ENDIF CALL InflowWind_CopyInput( SrcMiscData%u_Avg, DstMiscData%u_Avg, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) @@ -5234,6 +5249,9 @@ SUBROUTINE InflowWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ENDIF IF (ALLOCATED(MiscData%WindViUVW)) THEN DEALLOCATE(MiscData%WindViUVW) +ENDIF +IF (ALLOCATED(MiscData%WindAiUVW)) THEN + DEALLOCATE(MiscData%WindAiUVW) ENDIF CALL InflowWind_DestroyInput( MiscData%u_Avg, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -5393,6 +5411,11 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err IF ( ALLOCATED(InData%WindViUVW) ) THEN Int_BufSz = Int_BufSz + 2*2 ! WindViUVW upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WindViUVW) ! WindViUVW + END IF + Int_BufSz = Int_BufSz + 1 ! WindAiUVW allocated yes/no + IF ( ALLOCATED(InData%WindAiUVW) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WindAiUVW upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WindAiUVW) ! WindAiUVW END IF Int_BufSz = Int_BufSz + 3 ! u_Avg: size of buffers for each call to pack subtype CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Avg, ErrStat2, ErrMsg2, .TRUE. ) ! u_Avg @@ -5693,6 +5716,26 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_Xferred = Re_Xferred + 1 END DO END DO + END IF + IF ( .NOT. ALLOCATED(InData%WindAiUVW) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WindAiUVW,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindAiUVW,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%WindAiUVW,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%WindAiUVW,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%WindAiUVW,2), UBOUND(InData%WindAiUVW,2) + DO i1 = LBOUND(InData%WindAiUVW,1), UBOUND(InData%WindAiUVW,1) + ReKiBuf(Re_Xferred) = InData%WindAiUVW(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Avg, ErrStat2, ErrMsg2, OnlySize ) ! u_Avg CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -6118,6 +6161,29 @@ SUBROUTINE InflowWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + 1 END DO END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindAiUVW not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WindAiUVW)) DEALLOCATE(OutData%WindAiUVW) + ALLOCATE(OutData%WindAiUVW(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WindAiUVW.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WindAiUVW,2), UBOUND(OutData%WindAiUVW,2) + DO i1 = LBOUND(OutData%WindAiUVW,1), UBOUND(OutData%WindAiUVW,1) + OutData%WindAiUVW(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO END IF Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 61a47d579b..3c2490cc0f 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -560,6 +560,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, Init%InData_IfW%RootName = TRIM(p_FAST%OutFileRoot)//'.'//TRIM(y_FAST%Module_Abrev(Module_IfW)) Init%InData_IfW%UseInputFile = .TRUE. Init%InData_IfW%FixedWindFileRootName = .FALSE. + Init%InData_IfW%OutputAccel = p_FAST%MHK > 0 Init%InData_IfW%NumWindPoints = 0 IF ( p_FAST%CompServo == Module_SrvD ) Init%InData_IfW%NumWindPoints = Init%InData_IfW%NumWindPoints + 1 From 75583f17c599757e6f60894d430459360c1e9201 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 22 Feb 2023 21:47:20 +0000 Subject: [PATCH 14/51] Flow field supports Bladed wind files --- modules/inflowwind/CMakeLists.txt | 6 +- modules/inflowwind/src/FlowField.txt | 115 - modules/inflowwind/src/FlowField_IO.f90 | 2991 ++++++++++------- modules/inflowwind/src/FlowField_IO.txt | 26 +- modules/inflowwind/src/FlowField_IO_Types.f90 | 409 ++- .../src/{FlowField.f90 => IfW_FlowField.f90} | 96 +- modules/inflowwind/src/IfW_FlowField.txt | 116 + ...ield_Types.f90 => IfW_FlowField_Types.f90} | 237 +- modules/inflowwind/src/InflowWind.f90 | 50 +- modules/inflowwind/src/InflowWind.txt | 4 +- modules/inflowwind/src/InflowWind_Driver.f90 | 2 +- modules/inflowwind/src/InflowWind_Subs.f90 | 6 +- modules/inflowwind/src/InflowWind_Types.f90 | 12 +- 13 files changed, 2361 insertions(+), 1709 deletions(-) delete mode 100644 modules/inflowwind/src/FlowField.txt rename modules/inflowwind/src/{FlowField.f90 => IfW_FlowField.f90} (95%) create mode 100644 modules/inflowwind/src/IfW_FlowField.txt rename modules/inflowwind/src/{FlowField_Types.f90 => IfW_FlowField_Types.f90} (92%) diff --git a/modules/inflowwind/CMakeLists.txt b/modules/inflowwind/CMakeLists.txt index e056b4dfee..2c2f537ec3 100644 --- a/modules/inflowwind/CMakeLists.txt +++ b/modules/inflowwind/CMakeLists.txt @@ -24,13 +24,13 @@ if (GENERATE_TYPES) generate_f90_types(src/IfW_UniformWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_UniformWind_Types.f90 -noextrap) generate_f90_types(src/IfW_UserWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_UserWind_Types.f90 -noextrap) generate_f90_types(src/IfW_FFWind_Base.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_FFWind_Base_Types.f90 -noextrap) - generate_f90_types(src/FlowField.txt ${CMAKE_CURRENT_LIST_DIR}/src/FlowField_Types.f90 -noextrap) + generate_f90_types(src/IfW_FlowField.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_FlowField_Types.f90 -noextrap) generate_f90_types(src/FlowField_IO.txt ${CMAKE_CURRENT_LIST_DIR}/src/FlowField_IO_Types.f90 -noextrap) endif() set(IFW_SOURCES - src/FlowField_Types.f90 - src/FlowField.f90 + src/IfW_FlowField_Types.f90 + src/IfW_FlowField.f90 src/FlowField_IO_Types.f90 src/FlowField_IO.f90 src/IfW_BladedFFWind.f90 diff --git a/modules/inflowwind/src/FlowField.txt b/modules/inflowwind/src/FlowField.txt deleted file mode 100644 index 3077e8ee7f..0000000000 --- a/modules/inflowwind/src/FlowField.txt +++ /dev/null @@ -1,115 +0,0 @@ -#---------------------------------------------------------------------------------------------------------------------------------- -# Data structures for representing flow fields. -#---------------------------------------------------------------------------------------------------------------------------------- -# -#---------------------------------------------------------------------------------------------------------------------------------- - -param FlowField - IntKi Undef_FieldType - 0 - "This is the code for an undefined FieldType" - -param ^ - IntKi Uniform_FieldType - 1 - "Uniform FieldType from SteadyWind or Uniform Wind" - -param ^ - IntKi Grid3D_FieldType - 2 - "3D Grid FieldType from TurbSim, Bladed, HAWC" - -param ^ - IntKi Grid4D_FieldType - 3 - "4D Grid FieldType from FAST.Farm" - -param ^ - IntKi Point_FieldType - 4 - "Points FieldType from ExtInflow" - -param ^ - IntKi User_FieldType - 5 - "User FieldType configured by the user" - - -#---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ UniformFieldType ReKi RefHeight - - - "reference height; used to center the wind" meters -typedef ^ ^ ReKi RefLength - - - "reference length used to scale the linear shear" meters -typedef ^ ^ IntKi DataSize - - - "size of data in HH file" -typedef ^ ^ ReKi Time : - - "HH time array" seconds -typedef ^ ^ ReKi VelH : - - "HH horizontal wind speed" meters/sec -typedef ^ ^ ReKi VelHDot : - - "Derivative of HH horizontal wind speed wrt time" meters/sec -typedef ^ ^ ReKi VelV : - - "HH vertical wind speed, including tower shadow" meters/sec -typedef ^ ^ ReKi VelVDot : - - "Derivative of HH vertical wind speed wrt time" meters/sec -typedef ^ ^ ReKi VelGust : - - "HH wind gust speed" - -typedef ^ ^ ReKi VelGustDot : - - "Derivative of HH wind gust speed wrt time" - -typedef ^ ^ ReKi AngleH : - - "HH wind direction angle" degrees -typedef ^ ^ ReKi AngleHDot : - - "Derivative of HH wind direction angle wrt time" degrees -typedef ^ ^ ReKi AngleV : - - "HH upflow angle" degrees -typedef ^ ^ ReKi AngleVDot : - - "Derivative of HH upflow angle wrt time" degrees -typedef ^ ^ ReKi ShrH : - - "HH horizontal linear shear" - -typedef ^ ^ ReKi ShrHDot : - - "Derivative of HH horizontal linear shear wrt time" - -typedef ^ ^ ReKi ShrV : - - "HH vertical shear exponent" - -typedef ^ ^ ReKi ShrVDot : - - "Derivative of HH vertical shear exponent wrt time" - -typedef ^ ^ ReKi LinShrV : - - "HH vertical linear shear" seconds -typedef ^ ^ ReKi LinShrVDot : - - "Derivative of HH vertical linear shear wrt time" seconds - -typedef ^ UniformField_Interp ReKi VelH - - - "HH horizontal wind speed" meters/sec -typedef ^ ^ ReKi VelHDot - - - "derivative of HH horizontal wind speed wrt Time" meters/sec -typedef ^ ^ ReKi VelV - - - "HH vertical wind speed, including tower shadow" meters/sec -typedef ^ ^ ReKi VelVDot - - - "derivative of HH vertical wind speed wrt Time" meters/sec -typedef ^ ^ ReKi VelGust - - - "HH wind gust speed" - -typedef ^ ^ ReKi VelGustDot - - - "derivative of HH wind gust speed wrt Time" - -typedef ^ ^ ReKi AngleH - - - "HH wind direction angle" degrees -typedef ^ ^ ReKi AngleHDot - - - "derivative of HH wind direction angle wrt Time" degrees -typedef ^ ^ ReKi AngleV - - - "HH upflow angle" degrees -typedef ^ ^ ReKi AngleVDot - - - "derivative of HH upflow angle wrt Time" degrees -typedef ^ ^ ReKi ShrH - - - "HH horizontal linear shear" - -typedef ^ ^ ReKi ShrHDot - - - "derivative of HH horizontal linear shear wrt Time" - -typedef ^ ^ ReKi ShrV - - - "HH vertical shear exponent" - -typedef ^ ^ ReKi ShrVDot - - - "derivative of HH vertical shear exponent wrt Time" - -typedef ^ ^ ReKi LinShrV - - - "HH vertical linear shear" seconds -typedef ^ ^ ReKi LinShrVDot - - - "derivative of HH vertical linear shear wrt Time" seconds -typedef ^ ^ ReKi CosAngleH - - - "Horizontal angle components" - -typedef ^ ^ ReKi SinAngleH - - - "Horizontal angle components" - -typedef ^ ^ ReKi CosAngleV - - - "Vertical angle components" - -typedef ^ ^ ReKi SinAngleV - - - "Vertical angle components" - - -#---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ Grid3DFieldType IntKi WindFileFormat - - - "Binary file format description number" - -typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - -typedef ^ ^ Logical Periodic - .false. - "Flag to indicate if the wind file is periodic" - -typedef ^ ^ Logical InterpTower - .false. - "Flag to indicate if we should interpolate wind speeds below the tower" - -typedef ^ ^ Logical AddMeanAfterInterp - .false. - "Add the mean wind speed after interpolating at a given height?" - -typedef ^ ^ ReKi RefHeight - 0 - "Reference (hub) height of the grid" meters -typedef ^ ^ SiKi Vel :::: - - "Array of field velocities" - -typedef ^ ^ SiKi Acc :::: - - "Array of field accelerations" - -typedef ^ ^ SiKi VelTower ::: - - "Array of tower velocities" - -typedef ^ ^ SiKi AccTower ::: - - "Array of tower accelerations" - -typedef ^ ^ ReKi DTime - 0 - "Delta time" seconds -typedef ^ ^ ReKi Rate - 0 - "Data rate (1/FFDTime)" Hertz -typedef ^ ^ ReKi YHWid - 0 - "Half the grid width" meters -typedef ^ ^ ReKi ZHWid - 0 - "Half the grid height" meters -typedef ^ ^ ReKi GridBase - 0 - "the height of the bottom of the grid" meters -typedef ^ ^ ReKi InitXPosition - 0 - "the initial x position of grid (distance in FF is offset)" meters -typedef ^ ^ ReKi InvDY - 0 - "reciprocal of delta y" 1/meters -typedef ^ ^ ReKi InvDZ - 0 - "reciprocal of delta z" 1/meters -typedef ^ ^ ReKi MeanWS - 0 - "Mean wind speed (as defined in FF file), not necessarily of the portion used" meters/second -typedef ^ ^ ReKi InvMWS - 0 - "reciprocal of mean wind speed (MeanFFWS)" seconds/meter -typedef ^ ^ ReKi TotalTime - 0 - "The total time of the simulation" seconds -typedef ^ ^ IntKi NComp - 3 - "Number of wind components" - -typedef ^ ^ IntKi NYGrids - 0 - "Number of points in the lateral (y) direction of the grids" - -typedef ^ ^ IntKi NZGrids - 0 - "Number of points in the vertical (z) direction of the grids" - -typedef ^ ^ IntKi NTGrids - 0 - "Number of points in the vertical (z) direction on the tower (below the grids)" - -typedef ^ ^ IntKi NSteps - 0 - "Number of time steps in the FF array" - -typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - -typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - - -#---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ UserFieldType SiKi Dummy - - - "" - - -#---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ Grid4DFieldType IntKi n 4 - - "number of evenly-spaced grid points in the x, y, z, and t directions" - -typedef ^ ^ ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" -typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" -typedef ^ ^ SiKi Vel ::::: - - "this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt]" - -typedef ^ ^ ReKi TimeStart - - - "this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1))" s - -#---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ PointsFieldType ReKi Vel :: - - "Point velocities populated by external driver [uvw,point]" - - -#---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ FlowFieldType IntKi FieldType - 0 - "Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External}" - -typedef ^ ^ logical Enabled - .true. - "" - -typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters -typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians -typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" radians -typedef ^ ^ logical VelInterpCubic - .false. - "Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7]" - -typedef ^ ^ logical RotateWindBox - .false. - "flag indicating if the wind will be rotated" - -typedef ^ ^ logical AccFieldValid - .false. - "flag indicating that acceleration field has been calculated" - -typedef ^ ^ ReKi RotToWind {3}{3} - - "Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X')" - -typedef ^ ^ ReKi RotFromWind {3}{3} - - "Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind)" - -typedef ^ ^ UniformFieldType Uniform - - - "Uniform Flow Data" -typedef ^ ^ PointsFieldType Points - - - "External Point Flow Data" -typedef ^ ^ Grid3DFieldType Grid3D - - - "Grid Field Wind Data" -typedef ^ ^ Grid4DFieldType Grid4D - - - "External Grid Flow Data" -typedef ^ ^ UserFieldType User - - - "User Field Wind Data" diff --git a/modules/inflowwind/src/FlowField_IO.f90 b/modules/inflowwind/src/FlowField_IO.f90 index 34adcf1b53..27e42f3587 100644 --- a/modules/inflowwind/src/FlowField_IO.f90 +++ b/modules/inflowwind/src/FlowField_IO.f90 @@ -27,7 +27,7 @@ module FlowField_IO use NWTC_Library use FlowField_IO_Types -use FlowField +use IfW_FlowField implicit none private @@ -87,11 +87,11 @@ subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) select case (InitInp%WindType) case (1) ! Steady FF%FieldType = Uniform_FieldType - call SteadyWind_Init(InitInp%Steady, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) + call SteadyWind_ReadFile(InitInp%Steady, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) case (2) ! Uniform FF%FieldType = Uniform_FieldType - call UniformWind_Init(InitInp%Uniform, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) + call UniformWind_ReadFile(InitInp%Uniform, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) case (3) ! Binary TurbSim FF FF%FieldType = Grid3D_FieldType @@ -99,9 +99,7 @@ subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) case (4) ! Binary Bladed-Style FF FF%FieldType = Grid3D_FieldType - ! call Read_Bladed_Binary(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) - TmpErrStat = ErrID_Fatal - TmpErrMsg = "Binary Bladed Wind is not implemented" + call Bladed_ReadFile(InitInp%Bladed, InitInp%SumFileUnit, InitOut%Bladed, FF%Grid3D, InitOut%FileDat, TmpErrStat, TmpErrMsg) case (5) ! HAWC FF%FieldType = Grid3D_FieldType @@ -114,11 +112,9 @@ subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) case (7) ! Native Bladed FF FF%FieldType = Grid3D_FieldType - ! call Read_Bladed_Native(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) - TmpErrStat = ErrID_Fatal - TmpErrMsg = "Native Bladed Wind is not implemented" + call Bladed_ReadFile(InitInp%Bladed, InitInp%SumFileUnit, InitOut%Bladed, FF%Grid3D, InitOut%FileDat, TmpErrStat, TmpErrMsg) - case (8) ! External Grid + case (8) ! Grid FF%FieldType = Grid4D_FieldType TmpErrStat = ErrID_Fatal TmpErrMsg = "Grid4D Wind is not implemented" @@ -170,8 +166,8 @@ subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) return end if if (InitInp%VelInterpCubic) then - CALL WrScr ( ' Cubic velocity interpolation not implemented for WindType '//& - num2LStr(InitInp%WindType)//', using linear interpolation' ) + call WrScr(' Cubic velocity interpolation not implemented for WindType '// & + num2LStr(InitInp%WindType)//', using linear interpolation') FF%VelInterpCubic = .false. end if end select @@ -215,7 +211,7 @@ subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) end subroutine -subroutine SteadyWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) +subroutine SteadyWind_ReadFile(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) type(SteadyInitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(UniformFieldType), intent(out) :: UF @@ -223,7 +219,7 @@ subroutine SteadyWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = 'SteadyWind_Init' + character(*), parameter :: RoutineName = 'SteadyWind_ReadFile' integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg @@ -236,7 +232,7 @@ subroutine SteadyWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) UF%RefLength = 1.0_ReKi ! Allocate uniform wind data arrays - call Alloc_UniformWindArrays(UF, TmpErrStat, TmpErrMsg) + call UniformWind_AllocArrays(UF, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -295,7 +291,7 @@ subroutine SteadyWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) end subroutine -subroutine UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) +subroutine UniformWind_ReadFile(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) type(UniformInitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(UniformFieldType), intent(out) :: UF @@ -303,7 +299,7 @@ subroutine UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = 'UniformWind_Init' + character(*), parameter :: RoutineName = 'UniformWind_ReadFile' integer(IntKi), parameter :: MaxNumCols = 9 integer(IntKi), parameter :: MaxTries = 100 integer(IntKi) :: NumCols @@ -337,7 +333,7 @@ subroutine UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) UF%DataSize = WindFileInfo%NumLines ! Allocate uniform wind data arrays - call Alloc_UniformWindArrays(UF, TmpErrStat, TmpErrMsg) + call UniformWind_AllocArrays(UF, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -353,7 +349,8 @@ subroutine UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) ! so set upflow=0 and reduce number of columns to read remaning data call ParseAry(WindFileInfo, LineNo, "HH file line", TmpData(1:NumCols), NumCols, TmpErrStat, TmpErrMsg) if (TmpErrStat /= 0) then - CALL SetErrStat(ErrID_Info,' Could not read upflow column in uniform wind files. Assuming upflow is 0.', ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Info, ' Could not read upflow column in uniform wind files. Assuming upflow is 0.', & + ErrStat, ErrMsg, RoutineName) UF%AngleV = 0 NumCols = MaxNumCols - 1 end if @@ -502,12 +499,12 @@ subroutine UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) end subroutine -subroutine Alloc_UniformWindArrays(UF, ErrStat, ErrMsg) +subroutine UniformWind_AllocArrays(UF, ErrStat, ErrMsg) type(UniformFieldType), intent(inout) :: UF - integer(IntKi), intent(OUT) :: ErrStat - character(*), intent(OUT) :: ErrMsg + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = 'Alloc_UniformWindArrays' + character(*), parameter :: RoutineName = 'UniformWind_AllocArrays' integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg @@ -573,11 +570,11 @@ subroutine Alloc_UniformWindArrays(UF, ErrStat, ErrMsg) !> Read_TurbSim reads the binary TurbSim-format FF file (.bts). It fills the FFData array with !! velocity data for the grids and fills the Tower array with velocities at points on the tower !! (if data exists). -subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) +subroutine TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) type(TurbSimInitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit - type(Grid3DFieldType), intent(out) :: GF + type(Grid3DFieldType), intent(out) :: G3D type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg @@ -630,43 +627,43 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) ! Populate parameter data from header !---------------------------------------------------------------------------- - GF%WindFileFormat = header%FileID ! file format identifier - GF%Periodic = header%FileID == 8 ! 7 is used for non-periodic wind files; 8 is periodic wind - GF%InterpTower = .false. ! wind should not be interpolated at tower - GF%AddMeanAfterInterp = .false. ! do not add mean wind speed after interpolation + G3D%WindFileFormat = header%FileID ! file format identifier + G3D%Periodic = header%FileID == 8 ! 7 is used for non-periodic wind files; 8 is periodic wind + G3D%InterpTower = .false. ! wind should not be interpolated at tower + G3D%AddMeanAfterInterp = .false. ! do not add mean wind speed after interpolation - GF%DTime = real(header%dt, ReKi) ! grid spacing in time (dt), m/s - GF%Rate = 1.0_ReKi/GF%DTime ! Data rate (1/DTime), Hertz + G3D%DTime = real(header%dt, ReKi) ! grid spacing in time (dt), m/s + G3D%Rate = 1.0_ReKi/G3D%DTime ! Data rate (1/DTime), Hertz - GF%NComp = 3 ! TurbSim file file contains 3 wind components - GF%NYGrids = header%NYGrids ! the number of grid points laterally - GF%NZGrids = header%NZGrids ! the number of grid points vertically - GF%NTGrids = header%NTGrids ! the number of tower points - GF%NSteps = header%NSteps ! the number of time steps + G3D%NComp = 3 ! TurbSim file file contains 3 wind components + G3D%NYGrids = header%NYGrids ! the number of grid points laterally + G3D%NZGrids = header%NZGrids ! the number of grid points vertically + G3D%NTGrids = header%NTGrids ! the number of tower points + G3D%NSteps = header%NSteps ! the number of time steps - GF%InvDY = 1.0_ReKi/real(header%dy, ReKi) ! 1/dy - GF%YHWid = 0.5_ReKi*(GF%NYGrids - 1)/GF%InvDY ! half the grid width (m) + G3D%InvDY = 1.0_ReKi/real(header%dy, ReKi) ! 1/dy + G3D%YHWid = 0.5_ReKi*(G3D%NYGrids - 1)/G3D%InvDY ! half the grid width (m) - GF%InvDZ = 1.0_ReKi/real(header%dz, ReKi) ! 1/dz - GF%ZHWid = 0.5_ReKi*(GF%NZGrids - 1)/GF%InvDZ ! half the grid height (m) + G3D%InvDZ = 1.0_ReKi/real(header%dz, ReKi) ! 1/dz + G3D%ZHWid = 0.5_ReKi*(G3D%NZGrids - 1)/G3D%InvDZ ! half the grid height (m) - GF%MeanWS = real(header%mws, ReKi) ! the mean wind speed at hub height (m/s) - GF%InvMWS = 1.0_ReKi/GF%MeanWS ! inverse of mean wind speed + G3D%MeanWS = real(header%mws, ReKi) ! the mean wind speed at hub height (m/s) + G3D%InvMWS = 1.0_ReKi/G3D%MeanWS ! inverse of mean wind speed - GF%RefHeight = real(header%ref_height, ReKi) ! height of the hub (m) - GF%GridBase = real(header%grid_base_height, ReKi) ! height of the bottom of the grid (m) + G3D%RefHeight = real(header%ref_height, ReKi) ! height of the hub (m) + G3D%GridBase = real(header%grid_base_height, ReKi) ! height of the bottom of the grid (m) - if (GF%Periodic) then - GF%InitXPosition = 0 ! start at the hub - GF%TotalTime = GF%NSteps*GF%DTime + if (G3D%Periodic) then + G3D%InitXPosition = 0 ! start at the hub + G3D%TotalTime = G3D%NSteps*G3D%DTime else - GF%InitXPosition = GF%YHWid ! start half the grid width ahead of the turbine - GF%TotalTime = (GF%NSteps - 1)*GF%DTime + G3D%InitXPosition = G3D%YHWid ! start half the grid width ahead of the turbine + G3D%TotalTime = (G3D%NSteps - 1)*G3D%DTime end if - GF%WindProfileType = WindProfileType_None ! unused for turbsim - GF%PLExp = 0 ! unused for turbsim - GF%Z0 = 0 ! unused for turbsim + G3D%WindProfileType = WindProfileType_None ! unused for turbsim + G3D%PLExp = 0 ! unused for turbsim + G3D%Z0 = 0 ! unused for turbsim !---------------------------------------------------------------------------- ! Binary scaling factors from header @@ -699,13 +696,13 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) !---------------------------------------------------------------------------- ! Allocate storage for grid-field velocity data - call AllocAry(GF%Vel, GF%NComp, GF%NYGrids, GF%NZGrids, GF%NSteps, & + call AllocAry(G3D%Vel, G3D%NComp, G3D%NYGrids, G3D%NZGrids, G3D%NSteps, & 'grid-field velocity data', TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! Allocate storage for raw grid-field velocity for each time step - allocate (VelRaw(GF%NComp, GF%NYGrids, GF%NZGrids), stat=TmpErrStat) + allocate (VelRaw(G3D%NComp, G3D%NYGrids, G3D%NZGrids), stat=TmpErrStat) if (TmpErrStat /= 0) then call SetErrStat(ErrID_Fatal, "error allocating grid-field time step velocity data", & ErrStat, ErrMsg, RoutineName) @@ -713,16 +710,16 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) if (ErrStat >= AbortErrLev) return ! If tower grids specified - if (GF%NTGrids > 0) then + if (G3D%NTGrids > 0) then ! Allocate storage for tower velocity data - call AllocAry(GF%VelTower, GF%NComp, GF%NTGrids, GF%NSteps, & + call AllocAry(G3D%VelTower, G3D%NComp, G3D%NTGrids, G3D%NSteps, & 'tower wind velocity data.', TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! Allocate storage for raw tower data for each timestep - allocate (TwrRaw(GF%NComp, GF%NTGrids), stat=TmpErrStat) + allocate (TwrRaw(G3D%NComp, G3D%NTGrids), stat=TmpErrStat) if (TmpErrStat /= 0) then call SetErrStat(ErrID_Fatal, "error allocating tower time step velocity data", & ErrStat, ErrMsg, RoutineName) @@ -736,16 +733,16 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) ! This could take a while, so we'll write a message indicating what's going on: call WrScr(NewLine//' Reading a ' & - //TRIM(Num2LStr(GF%NYGrids))//'x' & - //TRIM(Num2LStr(GF%NZGrids))// & - ' grid ('//TRIM(Num2LStr(GF%YHWid*2))//' m wide, '// & - TRIM(Num2LStr(GF%GridBase))//' m to '// & - TRIM(Num2LStr(GF%GridBase + GF%ZHWid*2))// & + //TRIM(Num2LStr(G3D%NYGrids))//'x' & + //TRIM(Num2LStr(G3D%NZGrids))// & + ' grid ('//TRIM(Num2LStr(G3D%YHWid*2))//' m wide, '// & + TRIM(Num2LStr(G3D%GridBase))//' m to '// & + TRIM(Num2LStr(G3D%GridBase + G3D%ZHWid*2))// & ' m above ground) with a characteristic wind speed of '// & - TRIM(Num2LStr(GF%MeanWS))//' m/s. '//TRIM(DescStr)) + TRIM(Num2LStr(G3D%MeanWS))//' m/s. '//TRIM(DescStr)) ! Loop through time steps - do IT = 1, GF%NSteps + do IT = 1, G3D%NSteps ! Read grid-field raw wind data (normalized) comprised of 2-byte integers, INT(2) ! Indices are Velocity components, Y coordinates, Z coordinates @@ -758,12 +755,12 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) ! Loop through wind components (U, V, W), calculate de-normalized velocity (m/s) do IC = 1, 3 - GF%Vel(IC, :, :, IT) = (real(VelRaw(IC, :, :), SiKi) - Voffset(IC))/VSlope(IC) + G3D%Vel(IC, :, :, IT) = (real(VelRaw(IC, :, :), SiKi) - Voffset(IC))/VSlope(IC) end do !IC ! Read tower raw wind data (normalized) comprised of 2-byte integers, INT(2) ! Indices are Velocity components, Z coordinates - if (GF%NTGrids > 0) then + if (G3D%NTGrids > 0) then read (WindFileUnit, IOSTAT=TmpErrStat) TwrRaw if (TmpErrStat /= 0) then call SetErrStat(ErrID_Fatal, ' Error reading tower wind components in the FF binary file "'// & @@ -773,7 +770,7 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) ! Loop through wind components (U, V, W), calculate de-normalized velocity (m/s) do IC = 1, 3 - GF%VelTower(IC, :, IT) = (real(TwrRaw(IC, :), SiKi) - Voffset(IC))/VSlope(IC) + G3D%VelTower(IC, :, IT) = (real(TwrRaw(IC, :), SiKi) - Voffset(IC))/VSlope(IC) end do end if end do @@ -784,21 +781,21 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) close (WindFileUnit) - if (GF%Periodic) then - call WrScr(NewLine//' Processed '//TRIM(Num2LStr(GF%NSteps))//' time steps of '// & - TRIM(Num2LStr(GF%Rate))//'-Hz grid-field data (period of '// & - TRIM(Num2LStr(GF%DTime*(GF%NSteps)))//' seconds).') + if (G3D%Periodic) then + call WrScr(NewLine//' Processed '//TRIM(Num2LStr(G3D%NSteps))//' time steps of '// & + TRIM(Num2LStr(G3D%Rate))//'-Hz grid-field data (period of '// & + TRIM(Num2LStr(G3D%DTime*(G3D%NSteps)))//' seconds).') else - call WrScr(NewLine//' Processed '//TRIM(Num2LStr(GF%NSteps))//' time steps of '// & - TRIM(Num2LStr(GF%Rate))//'-Hz grid-field data ('// & - TRIM(Num2LStr(GF%DTime*(GF%NSteps - 1)))//' seconds).') + call WrScr(NewLine//' Processed '//TRIM(Num2LStr(G3D%NSteps))//' time steps of '// & + TRIM(Num2LStr(G3D%Rate))//'-Hz grid-field data ('// & + TRIM(Num2LStr(G3D%DTime*(G3D%NSteps - 1)))//' seconds).') end if !---------------------------------------------------------------------------- ! Store wind file metadata !---------------------------------------------------------------------------- - call PopulateWindFileDatFromGrid3DField(GF, InitInp%WindFileName, 3, GF%NTGrids > 0, FileDat) + call Grid3DField_PopulateWindFileDat(G3D, InitInp%WindFileName, 3, G3D%NTGrids > 0, FileDat) !---------------------------------------------------------------------------- ! Write the summary file @@ -810,32 +807,32 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) //TRIM(FlowField_IO_Ver%Name)//' '//TRIM(FlowField_IO_Ver%Ver) write (SumFileUnit, '(A)') TRIM(TmpErrMsg) write (SumFileUnit, '(5x,A)') 'FileName: '//TRIM(InitInp%WindFileName) - write (SumFileUnit, '(5x,A29,I3)') 'Binary file format id: ', GF%WindFileFormat - write (SumFileUnit, '(5x,A29,G12.4)') 'Reference height (m): ', GF%RefHeight - write (SumFileUnit, '(5x,A29,G12.4)') 'Timestep (s): ', GF%DTime - write (SumFileUnit, '(5x,A29,I12)') 'Number of timesteps: ', GF%NSteps - write (SumFileUnit, '(5x,A29,G12.4)') 'Mean windspeed (m/s): ', GF%MeanWS - write (SumFileUnit, '(5x,A29,L1)') 'Windfile is periodic: ', GF%Periodic - write (SumFileUnit, '(5x,A29,L1)') 'Windfile includes tower: ', GF%NTGrids > 0 - - if (GF%Periodic) then + write (SumFileUnit, '(5x,A29,I3)') 'Binary file format id: ', G3D%WindFileFormat + write (SumFileUnit, '(5x,A29,G12.4)') 'Reference height (m): ', G3D%RefHeight + write (SumFileUnit, '(5x,A29,G12.4)') 'Timestep (s): ', G3D%DTime + write (SumFileUnit, '(5x,A29,I12)') 'Number of timesteps: ', G3D%NSteps + write (SumFileUnit, '(5x,A29,G12.4)') 'Mean windspeed (m/s): ', G3D%MeanWS + write (SumFileUnit, '(5x,A29,L1)') 'Windfile is periodic: ', G3D%Periodic + write (SumFileUnit, '(5x,A29,L1)') 'Windfile includes tower: ', G3D%NTGrids > 0 + + if (G3D%Periodic) then write (SumFileUnit, '(5x,A)') 'Time range (s): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(GF%TotalTime))//' ]' + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(G3D%TotalTime))//' ]' else ! Shift the time range to compensate for the shifting of the wind grid write (SumFileUnit, '(5x,A)') 'Time range (s): [ '// & - TRIM(Num2LStr(-GF%InitXPosition*GF%InvMWS))//' : '// & - TRIM(Num2LStr(GF%TotalTime - GF%InitXPosition*GF%InvMWS))//' ]' + TRIM(Num2LStr(-G3D%InitXPosition*G3D%InvMWS))//' : '// & + TRIM(Num2LStr(G3D%TotalTime - G3D%InitXPosition*G3D%InvMWS))//' ]' end if write (SumFileUnit, '(5x,A)') 'Y range (m): [ '// & - TRIM(Num2LStr(-GF%YHWid))//' : '//TRIM(Num2LStr(GF%YHWid))//' ]' + TRIM(Num2LStr(-G3D%YHWid))//' : '//TRIM(Num2LStr(G3D%YHWid))//' ]' - if (GF%NTGrids > 0) then + if (G3D%NTGrids > 0) then write (SumFileUnit, '(5x,A)') 'Z range (m): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(GF%RefHeight + GF%ZHWid))//' ]' + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(G3D%RefHeight + G3D%ZHWid))//' ]' else write (SumFileUnit, '(5x,A)') 'Z range (m): [ '// & - TRIM(Num2LStr(GF%RefHeight - GF%ZHWid))//' : '//TRIM(Num2LStr(GF%RefHeight + GF%ZHWid))//' ]' + TRIM(Num2LStr(G3D%RefHeight - G3D%ZHWid))//' : '//TRIM(Num2LStr(G3D%RefHeight + G3D%ZHWid))//' ]' end if ! Get IO status for unit @@ -848,11 +845,11 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) end subroutine -subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) +subroutine HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) type(HAWCInitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit - type(Grid3DFieldType), intent(out) :: GF + type(Grid3DFieldType), intent(out) :: G3D type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg @@ -876,56 +873,50 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" - GF%WindFileFormat = 0 - GF%Periodic = .true. - GF%InterpTower = .true. - GF%AddMeanAfterInterp = .true. + G3D%WindFileFormat = 0 + G3D%Periodic = .true. + G3D%InterpTower = .true. + G3D%AddMeanAfterInterp = .true. - GF%DTime = InitInp%dx/InitInp%URef - GF%Rate = 1.0_ReKi/GF%DTime + G3D%DTime = InitInp%dx/InitInp%G3D%URef + G3D%Rate = 1.0_ReKi/G3D%DTime - GF%NComp = 3 - GF%NYGrids = InitInp%ny - GF%NZGrids = InitInp%nz - GF%NTGrids = 0 - GF%NSteps = InitInp%nx + G3D%NComp = 3 + G3D%NYGrids = InitInp%ny + G3D%NZGrids = InitInp%nz + G3D%NTGrids = 0 + G3D%NSteps = InitInp%nx - GF%YHWid = 0.5_ReKi*InitInp%dy*(GF%NYGrids - 1) - GF%InvDY = 1.0/InitInp%dy + G3D%YHWid = 0.5_ReKi*InitInp%dy*(G3D%NYGrids - 1) + G3D%InvDY = 1.0/InitInp%dy - GF%ZHWid = 0.5_ReKi*InitInp%dz*(GF%NZGrids - 1) - GF%InvDZ = 1.0_ReKi/InitInp%dz + G3D%ZHWid = 0.5_ReKi*InitInp%dz*(G3D%NZGrids - 1) + G3D%InvDZ = 1.0_ReKi/InitInp%dz - GF%MeanWS = InitInp%URef - GF%InvMWS = 1.0_ReKi/GF%MeanWS + G3D%MeanWS = InitInp%G3D%URef + G3D%InvMWS = 1.0_ReKi/G3D%MeanWS - GF%RefHeight = InitInp%RefHt - GF%GridBase = GF%RefHeight - GF%ZHWid + G3D%RefHeight = InitInp%G3D%RefHt + G3D%GridBase = G3D%RefHeight - G3D%ZHWid - GF%InitXPosition = InitInp%XOffset - GF%TotalTime = GF%NSteps*InitInp%dx/GF%MeanWS + G3D%InitXPosition = InitInp%G3D%XOffset + G3D%TotalTime = G3D%NSteps*InitInp%dx/G3D%MeanWS - GF%WindProfileType = InitInp%WindProfileType - GF%Z0 = InitInp%Z0 - GF%PLExp = InitInp%PLExp + G3D%WindProfileType = InitInp%G3D%WindProfileType + G3D%Z0 = InitInp%G3D%Z0 + G3D%PLExp = InitInp%G3D%PLExp ScaleFactors = 0.0_ReKi !---------------------------------------------------------------------------- - ! Validate arguments + ! Validate initialization iput !---------------------------------------------------------------------------- - if ((InitInp%ScaleMethod == ScaleMethod_Direct) .and. any(InitInp%SF(:GF%NComp) < 0.0_ReKi)) then - call SetErrStat(ErrID_Fatal, 'Turbulence scaling factors must not be negative.', ErrStat, ErrMsg, RoutineName) - elseif ((InitInp%ScaleMethod == ScaleMethod_StdDev) .and. any(InitInp%SigmaF(:GF%NComp) < 0.0_ReKi)) then - call SetErrStat(ErrID_Fatal, 'Turbulence standard deviations must not be negative.', ErrStat, ErrMsg, RoutineName) - else if ((InitInp%ScaleMethod /= 0) .and. (InitInp%ScaleMethod /= 1) .and. (InitInp%ScaleMethod /= 2)) then - call SetErrStat(ErrID_Fatal, 'Turbulence scaling method must be 0, 1, or 2.', ErrStat, ErrMsg, RoutineName) - else if (InitInp%RefHt < 0.0_ReKi .or. EqualRealNos(GF%RefHeight, 0.0_ReKi)) then - call SetErrStat(ErrID_Fatal, 'The grid reference height must be larger than 0.', ErrStat, ErrMsg, RoutineName) - else if (GF%MeanWS < 0.0_ReKi) then - call SetErrStat(ErrID_Fatal, 'The reference wind speed must not be negative.', ErrStat, ErrMsg, RoutineName) - else if (InitInp%nx < 1) then + call Grid3DField_ValidateInput(InitInp%G3D, 3, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + if (InitInp%nx < 1) then call SetErrStat(ErrID_Fatal, 'Number of grid points in the X direction must be at least 1.', ErrStat, ErrMsg, RoutineName) else if (InitInp%ny < 1) then call SetErrStat(ErrID_Fatal, 'Number of grid points in the Y direction must be at least 1.', ErrStat, ErrMsg, RoutineName) @@ -937,10 +928,6 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) call SetErrStat(ErrID_Fatal, 'The grid spacing in the Y direction must be larger than 0.', ErrStat, ErrMsg, RoutineName) else if (InitInp%dz < 0.0_ReKi .or. EqualRealNos(InitInp%dz, 0.0_ReKi)) then call SetErrStat(ErrID_Fatal, 'The grid spacing in the Z direction must be larger than 0.', ErrStat, ErrMsg, RoutineName) - else if (GF%GridBase < 0.0_ReKi) then - call SetErrStat(ErrID_Severe, 'WARNING: The bottom of the grid is located at a height of '// & - trim(Num2LStr(GF%GridBase))//' meters, which is below the ground.'// & - ' Winds below the ground will be set to 0.', ErrStat, ErrMsg, RoutineName) end if if (ErrStat >= AbortErrLev) return @@ -949,13 +936,13 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) !---------------------------------------------------------------------------- ! Allocate storage for grid-field velocity data - call AllocAry(GF%Vel, GF%NComp, GF%NYGrids, GF%NZGrids, GF%NSteps, & + call AllocAry(G3D%Vel, G3D%NComp, G3D%NYGrids, G3D%NZGrids, G3D%NSteps, & 'grid-field velocity data', TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! Allocate storage for raw grid-field velocity for each time step - allocate (VelRaw(GF%NZGrids, GF%NYGrids), stat=TmpErrStat) + allocate (VelRaw(G3D%NZGrids, G3D%NYGrids), stat=TmpErrStat) if (TmpErrStat /= 0) then call SetErrStat(ErrID_Fatal, "error allocating grid-field time step velocity data", & ErrStat, ErrMsg, RoutineName) @@ -968,10 +955,10 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) ! Display message indicating that file is being read call WrScr(NewLine//' Reading HAWC wind files with grids of '// & - TRIM(Num2LStr(GF%NSteps))//' x '//TRIM(Num2LStr(GF%NYGrids))//' x '//TRIM(Num2LStr(GF%NZGrids))//' points'// & - ' ('//TRIM(Num2LStr(GF%YHWid*2))//' m wide, '//TRIM(Num2LStr(GF%GridBase))//' m to '// & - TRIM(Num2LStr(GF%GridBase + GF%ZHWid*2))// & - ' m above ground) with a characteristic wind speed of '//TRIM(Num2LStr(GF%MeanWS))//' m/s. ') + TRIM(Num2LStr(G3D%NSteps))//' x '//TRIM(Num2LStr(G3D%NYGrids))//' x '//TRIM(Num2LStr(G3D%NZGrids))//' points'// & + ' ('//TRIM(Num2LStr(G3D%YHWid*2))//' m wide, '//TRIM(Num2LStr(G3D%GridBase))//' m to '// & + 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) @@ -979,7 +966,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) if (ErrStat >= AbortErrLev) return ! Loop through wind components (X, Y, Z) - do IC = 1, GF%NComp + do IC = 1, G3D%NComp ! Open wind file for this component call OpenBInpFile(WindFileUnit, InitInp%WindFileName(IC), TmpErrStat, TmpErrMsg) @@ -987,7 +974,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) if (ErrStat >= AbortErrLev) return ! Loop through time steps - do IX = 1, GF%NSteps + do IX = 1, G3D%NSteps ! Read file data for this timestep (Z(1:N),Y(N:1),C(1:3)) read (WindFileUnit, IOSTAT=TmpErrStat) VelRaw @@ -1001,10 +988,10 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) end if ! Reorganize raw data into grid-field array (reverse Y indices) - do IZ = 1, GF%NZGrids - ! Vel(NFFComp, NYGrids, NZGrids, NSteps) + do IZ = 1, G3D%NZGrids + ! Vel(NComp, NYGrids, NZGrids, NSteps) ! VelRaw(NZGrids, NYGrids) - GF%Vel(IC, :, IZ, IX) = VelRaw(IZ, GF%NYGrids:1:-1) + G3D%Vel(IC, :, IZ, IX) = VelRaw(IZ, G3D%NYGrids:1:-1) end do end do @@ -1014,63 +1001,23 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) end do !---------------------------------------------------------------------------- - ! Scale turbulence + ! Scale turbulence to requested intensity !---------------------------------------------------------------------------- - select case (InitInp%ScaleMethod) - - case (ScaleMethod_None) ! No scaling - ScaleFactors = 1.0_ReKi - - case (ScaleMethod_Direct) ! Apply scale factors from file - ScaleFactors = InitInp%SF - - case (ScaleMethod_StdDev) ! Use scale factor to get requested sigma - - ! find the center point of the grid (if we don't have an odd number - ! of grid points, we'll pick the point closest to the center) - iz = ishft(InitInp%nz + 1, -1) ! integer divide by 2 - iy = ishft(InitInp%ny + 1, -1) ! integer divide by 2 - - ! Loop through components - do ic = 1, GF%NComp - - ! Mean of component for all time - vMean = sum(GF%Vel(ic, iy, iz, :))/InitInp%nx - - ! Sum of square of component value for all time - vSum2 = dot_product(GF%Vel(ic, iy, iz, :), GF%Vel(ic, iy, iz, :)) - - ! Standard deviation of component - ActualSigma = real(sqrt(abs(vSum2/InitInp%nx - vMean**2)), kind(ActualSigma)) - - ! If actual sigma is nearly zero, - if (EqualRealNos(ActualSigma, 0.0_ReKi)) then - ScaleFactors(ic) = 0.0_ReKi - if (.not. EqualRealNos(InitInp%SigmaF(ic), 0.0_ReKi)) then - call SetErrStat(ErrID_Fatal,"Computed standard deviation is zero; cannot scale to achieve target non-zero standard deviation.", ErrStat, ErrMsg, RoutineName ) - end if - else - ScaleFactors(ic) = InitInp%SigmaF(ic)/ActualSigma - end if - end do - end select - - ! Loop through components and apply scale factors - do ic = 1, GF%NComp - GF%Vel(ic, :, :, :) = real(ScaleFactors(ic)*GF%Vel(ic, :, :, :), SiKi) - end do + call ScaleTurbulence(InitInp%G3D, G3D%Vel, ScaleFactors, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return !---------------------------------------------------------------------------- ! Remove the U component mean wind speed !---------------------------------------------------------------------------- ! If scaling method is not none, remove mean value of X component at each grid point - if (InitInp%ScaleMethod /= ScaleMethod_None) then - do iz = 1, GF%NZGrids - do iy = 1, GF%NYGrids - vMean = sum(GF%Vel(1, iy, iz, :))/GF%NSteps - GF%Vel(1, iy, iz, :) = real(GF%Vel(1, iy, iz, :) - vMean, SiKi) + if (InitInp%G3D%ScaleMethod /= ScaleMethod_None) then + do iz = 1, G3D%NZGrids + do iy = 1, G3D%NYGrids + vMean = sum(G3D%Vel(1, iy, iz, :))/G3D%NSteps + G3D%Vel(1, iy, iz, :) = real(G3D%Vel(1, iy, iz, :) - vMean, SiKi) end do end do end if @@ -1079,7 +1026,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) ! Store wind file metadata !---------------------------------------------------------------------------- - call PopulateWindFileDatFromGrid3DField(GF, InitInp%WindFileName(1), 5, .false., FileDat) + call Grid3DField_PopulateWindFileDat(G3D, InitInp%WindFileName(1), 5, .false., FileDat) !---------------------------------------------------------------------------- ! Write the summary file @@ -1089,18 +1036,18 @@ subroutine HAWC_Init(InitInp, SumFileUnit, GF, FileDat, ErrStat, ErrMsg) write (SumFileUnit, '(A)') write (SumFileUnit, '(A)') 'HAWC wind type. Read by InflowWind sub-module FlowField_IO' - write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', GF%RefHeight - write (SumFileUnit, '(A34,G12.4)') ' Timestep (s): ', GF%DTime - write (SumFileUnit, '(A34,I12)') ' Number of timesteps: ', GF%NSteps - write (SumFileUnit, '(A34,G12.4)') ' Mean windspeed (m/s): ', GF%MeanWS + write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', G3D%RefHeight + write (SumFileUnit, '(A34,G12.4)') ' Timestep (s): ', G3D%DTime + write (SumFileUnit, '(A34,I12)') ' Number of timesteps: ', G3D%NSteps + write (SumFileUnit, '(A34,G12.4)') ' Mean windspeed (m/s): ', G3D%MeanWS write (SumFileUnit, '(A)') ' Time range (s): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(GF%TotalTime))//' ]' + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(G3D%TotalTime))//' ]' write (SumFileUnit, '(A)') ' X range (m): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(GF%TotalTime*GF%MeanWS))//' ]' + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(G3D%TotalTime*G3D%MeanWS))//' ]' write (SumFileUnit, '(A)') ' Y range (m): [ '// & - TRIM(Num2LStr(-GF%YHWid))//' : '//TRIM(Num2LStr(GF%YHWid))//' ]' + TRIM(Num2LStr(-G3D%YHWid))//' : '//TRIM(Num2LStr(G3D%YHWid))//' ]' write (SumFileUnit, '(A)') ' Z range (m): [ '// & - TRIM(Num2LStr(GF%GridBase))//' : '//TRIM(Num2LStr(GF%GridBase + GF%ZHWid*2.0))//' ]' + TRIM(Num2LStr(G3D%GridBase))//' : '//TRIM(Num2LStr(G3D%GridBase + G3D%ZHWid*2.0))//' ]' write (SumFileUnit, '(A)') 'Scaling factors used:' write (SumFileUnit, '(A)') ' u v w ' @@ -1134,11 +1081,11 @@ subroutine User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) end subroutine !> Grid4D_Init initializes a wind field defined by a 4D grid. -subroutine Grid4D_Init(InitInp, SumFileUnit, EGF, FileDat, ErrStat, ErrMsg) +subroutine Grid4D_Init(InitInp, SumFileUnit, G4D, FileDat, ErrStat, ErrMsg) type(Grid4DInitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit - type(Grid4DFieldType), intent(out) :: EGF + type(Grid4DFieldType), intent(out) :: G4D type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg @@ -1151,19 +1098,19 @@ subroutine Grid4D_Init(InitInp, SumFileUnit, EGF, FileDat, ErrStat, ErrMsg) ErrMsg = "" ! Initialize field from inputs - EGF%n = InitInp%n - EGF%delta = InitInp%delta - EGF%pZero = InitInp%pZero - EGF%TimeStart = 0.0_ReKi + G4D%n = InitInp%n + G4D%delta = InitInp%delta + G4D%pZero = InitInp%pZero + G4D%TimeStart = 0.0_ReKi ! uvw velocity components at x,y,z,t coordinates - call AllocAry(EGF%Vel, 3, EGF%n(1), EGF%n(2), EGF%n(3), EGF%n(4), & + call AllocAry(G4D%Vel, 3, G4D%n(1), G4D%n(2), G4D%n(3), G4D%n(4), & 'External Grid Velocity', TmpErrStat, TmpErrMsg) call SetErrStat(ErrStat, ErrMsg, TmpErrStat, TmpErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! Initialize velocities to zero - EGF%Vel = 0.0_SiKi + G4D%Vel = 0.0_SiKi if (SumFileUnit > 0) then write (SumFileUnit, '(A)') InitInp%n @@ -1171,1110 +1118,1548 @@ subroutine Grid4D_Init(InitInp, SumFileUnit, EGF, FileDat, ErrStat, ErrMsg) end subroutine -subroutine PopulateWindFileDatFromGrid3DField(Grid3DField, FileName, WindType, HasTower, FileDat) +subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, ErrMsg) - type(Grid3DFieldType), intent(in) :: Grid3DField - character(*), intent(in) :: FileName - integer(IntKi), intent(in) :: WindType - logical, intent(in) :: HasTower - type(WindFileDat), intent(out) :: FileDat + type(BladedInitInputType), intent(in) :: InitInp !< Initialization data passed to the module + integer(IntKi), intent(in) :: SumFileUnit + type(BladedInitOutputType), intent(out) :: InitOut !< Initial output + type(Grid3DFieldType), intent(out) :: G3D !< Parameters + type(WindFileDat), intent(out) :: FileDat + integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered + character(*), intent(out) :: ErrMsg !< Message about errors + + ! REAL(ReKi), INTENT( OUT) :: TI (3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI + character(*), parameter :: RoutineName = "Bladed_ReadFile" + type(Grid3DInitInputType) :: G3D_InitInp ! initialization input for grid 3d field + real(ReKi) :: BinTI(3) ! turbulence intensities of the wind components as defined in the FF binary file, not necessarially the actual TI + real(ReKi) :: NatTI(3) ! turbulence intensities of the wind components as defined in the native FF summary file + real(ReKi) :: UBar + real(ReKi) :: ZCenter + real(ReKi) :: ScaleFactors(3) ! turbulence scaling factors + real(ReKi) :: TI(3) + real(ReKi) :: SigmaF(3) ! Turbulence standard deviation + integer(IntKi) :: ScaleMethod + integer(IntKi) :: UnitWind ! Unit number for the InflowWind input file + integer(B2Ki) :: Dum_Int2 + integer(IntKi) :: I + logical :: CWise + logical :: LHR ! Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) + logical :: Exists + character(1028) :: SumFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. + character(1028) :: TwrFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. + character(1024) :: BinFileName + character(1024) :: PriPath + character(ErrMsgLen) :: TmpErrMsg ! temporary error message + integer(IntKi) :: TmpErrStat ! temporary error status + + ErrMsg = '' + ErrStat = ErrID_None - FileDat%FileName = FileName - FileDat%WindType = WindType - FileDat%RefHt = Grid3DField%RefHeight - FileDat%RefHt_Set = .true. - FileDat%DT = Grid3DField%DTime - FileDat%NumTSteps = Grid3DField%NSteps - FileDat%ConstantDT = .true. + if (InitInp%NativeBladedFmt) then - if (Grid3DField%Periodic) then - FileDat%TRange = [0.0_ReKi, Grid3DField%TotalTime] - FileDat%TRange_Limited = .false. - else ! Shift the time range to compensate for the shifting of the wind grid - FileDat%TRange = [0.0_ReKi, Grid3DField%TotalTime] - Grid3DField%InitXPosition*Grid3DField%InvMWS - FileDat%TRange_Limited = .true. + call Bladed_ReadNativeSummary(InitInp%WindFileName, G3D_InitInp%PLExp, G3D_InitInp%VLinShr, & + G3D_InitInp%HLinShr, G3D_InitInp%RefLength, NatTI, G3D%MeanWS, & + G3D%RefHeight, InitOut%PropagationDir, InitOut%VFlowAngle, & + BinFileName, G3D_InitInp%XOffset, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + if (pathIsRelative(BinFileName)) then + call GetPath(InitInp%WindFileName, PriPath) ! Binary file will be relative to the path where the primary input file is located. + BinFileName = TRIM(PriPath)//TRIM(BinFileName) + end if + + if (InitInp%FixedWindFileRootName) then ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data + if (InitInp%TurbineID == 0) then ! .TRUE. for the FAST.Farm low-resolution domain + BinFileName = TRIM(BinFileName)//TRIM(PathSep)//'Low' + else ! FAST.Farm high-resolution domain(s) + BinFileName = TRIM(BinFileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) + end if + end if + + ! default values for Bladed Format + CWise = .false. + ZCenter = G3D%RefHeight + G3D%Periodic = .true. + + G3D_InitInp%ScaleMethod = ScaleMethod_StdDev + G3D_InitInp%SigmaF = NatTI*G3D%MeanWS + G3D_InitInp%SF = SigmaF + + ! it could also have logarithmic, but I'm going to leave that off for now + G3D_InitInp%RefHt = G3D%RefHeight + G3D_InitInp%URef = G3D%MeanWS + G3D_InitInp%WindProfileType = WindProfileType_PL ! it could also have logarithmic, but I'm going to leave that off for now + + InitOut%TI = 100.0_ReKi + UBar = 0.0_ReKi + LHR = .true. + + else + InitOut%PropagationDir = 0.0_ReKi + InitOut%VFlowAngle = 0.0_ReKi + G3D_InitInp%VLinShr = 0.0_ReKi + G3D_InitInp%HLinShr = 0.0_ReKi + G3D_InitInp%RefLength = 1.0_ReKi + + BinFileName = InitInp%WindFileName end if - FileDat%YRange = [-Grid3DField%YHWid, Grid3DField%YHWid] - FileDat%YRange_Limited = .true. ! Hard boundaries enforced in y-direction + ! Get a unit number to use - ! If has tower data - if (HasTower) then - FileDat%ZRange = [0.0_Reki, Grid3DField%RefHeight + Grid3DField%ZHWid] + call GetNewUnit(UnitWind, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + !---------------------------------------------------------------------------------------------- + ! 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 SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Read the first binary integer from the file to get info on the type. + ! Cannot use library read routines since this is a 2-byte integer. + read (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 + close (UnitWind) + + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading first binary integer from file "'//TRIM(BinFileName)//'."', & + ErrStat, ErrMsg, RoutineName) + return + end if + + !---------------------------------------------------------------------------------------------- + ! Read the files to get the required FF data. + !---------------------------------------------------------------------------------------------- + + ! Store the binary format information so the InflowWind code can use it. + ! Also changes to IntKi from INT(2) to compare in the SELECT below + G3D%WindFileFormat = Dum_Int2 + + select case (G3D%WindFileFormat) + + case (-1, -2, -3, -99) ! Bladed-style binary format + + if (.not. InitInp%NativeBladedFmt) then + + !........................................................................................... + ! Create full-field summary file name from binary file root name. Also get tower file + ! name. + !........................................................................................... + + call GetRoot(BinFileName, SumFile) + + TwrFile = TRIM(SumFile)//'.twr' + SumFile = TRIM(SumFile)//'.sum' + + !........................................................................................... + ! Read the summary file to get necessary scaling information + !........................................................................................... + + call Bladed_ReadTurbSimSummary(UnitWind, TRIM(SumFile), CWise, ZCenter, InitOut%TI, UBar, G3D%RefHeight, G3D%Periodic, LHR, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + close (UnitWind) + return + end if + + end if + + !........................................................................................... + ! Open the binary file and read its header + !........................................................................................... + + call OpenBInpFile(UnitWind, TRIM(BinFileName), TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + close (UnitWind) + return + end if + + if (Dum_Int2 == -99) then ! Newer-style BLADED format + call Bladed_ReadHeader1(UnitWind, BinTI, G3D, InitInp%NativeBladedFmt, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + close (UnitWind) + return + end if + + ! If the TIs are also in the binary file (BinTI > 0), + ! use those numbers instead of ones from the summary file + + if (.not. InitInp%NativeBladedFmt) then + do I = 1, G3D%NComp + if (BinTI(I) > 0) InitOut%TI(I) = BinTI(I) + end do + end if + + else + call Bladed_ReadHeader0(UnitWind, G3D, InitInp%NativeBladedFmt, TmpErrStat, TmpErrMsg) ! Older-style BLADED format + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + close (UnitWind) + return + end if + + end if + + !------------------------------------------------------------------------- + ! Let's see if the summary and binary FF wind files go together before continuing. + !------------------------------------------------------------------------- + + if (.not. InitInp%NativeBladedFmt) then + if (ABS(UBar - G3D%MeanWS) > 0.1) then + call SetErrStat(ErrID_Fatal, ' Error: Incompatible mean hub-height wind speeds in FF wind files. '// & + '(Check that the .sum and .wnd files were generated together.)', ErrStat, ErrMsg, RoutineName) + close (UnitWind) + return + end if + + end if + + !------------------------------------------------------------------------- + ! Calculate the height of the bottom of the grid + !------------------------------------------------------------------------- + + G3D%GridBase = ZCenter - G3D%ZHWid ! the location, in meters, of the bottom of the grid + if (G3D%GridBase < 0.0_ReKi) then + call SetErrStat(ErrID_Severe, 'WARNING: The bottom of the grid is located at a height of '// & + TRIM(Num2LStr(G3D%GridBase))//' meters, which is below the ground.'// & + ' Winds below the ground will be set to 0.', ErrStat, ErrMsg, RoutineName) + end if + + !------------------------------------------------------------------------- + ! Read the binary grids (converted tƒo m/s) and close the file + !------------------------------------------------------------------------- + + call Bladed_ReadGrids(UnitWind, InitInp%NativeBladedFmt, CWise, LHR, InitOut%TI, G3D, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + + close (UnitWind) + if (InitInp%NativeBladedFmt) InitOut%TI = NatTI*100.0_ReKi ! report these TI for the native Bladed format in percent + + if (ErrStat >= AbortErrLev) return + + !------------------------------------------------------------------------- + ! Read the tower points file + !------------------------------------------------------------------------- + + if (InitInp%TowerFileExist .and. .not. InitInp%NativeBladedFmt) then ! If we specified a tower file + inquire (FILE=TRIM(TwrFile), EXIST=Exists) + + ! Double check that the tower file exists and read it. If it was requested but doesn't exist, + ! throw fatal error and exit. + if (Exists) then + call Bladed_ReadTower(UnitWind, G3D, TwrFile, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + close (UnitWind) + return + end if + else + call SetErrStat(ErrID_Fatal, ' Tower file '//TRIM(TwrFile)//' specified for Bladed full-field '// & + 'wind files does not exist.', ErrStat, ErrMsg, RoutineName) + close (UnitWind) + return + end if + else + G3D%NTGrids = 0_IntKi + end if + + case DEFAULT + call SetErrStat(ErrID_Fatal, ' This is not a bladed-style binary wind file (binary format identifier: '// & + TRIM(Num2LStr(G3D%WindFileFormat))//'. This might be a TurbSim binary wind file.', & + ErrStat, ErrMsg, RoutineName) + return + + end select + + !---------------------------------------------------------------------------- + ! Post reading + !---------------------------------------------------------------------------- + + !---------------------------------------------------------------------------- + ! If the wind file has zero-mean and unit standard deviation (native Bladed format), scale the data: + !---------------------------------------------------------------------------- + + G3D%AddMeanAfterInterp = .false. + + if (InitInp%NativeBladedFmt) then + + G3D%InterpTower = .true. + G3D%AddMeanAfterInterp = .true. + + ! Validate scaling data if we've got native-Bladed format + call Grid3DField_ValidateInput(G3D_InitInp, G3D%NComp, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! scale to requested TI (or use requested scale factors) + call ScaleTurbulence(G3D_InitInp, G3D%Vel(:, :, :, 1:G3D%NSteps), ScaleFactors, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return else - FileDat%ZRange = [Grid3DField%GridBase, Grid3DField%GridBase + Grid3DField%ZHWid*2.0] + G3D%InterpTower = .false. + G3D%WindProfileType = WindProfileType_None end if - FileDat%ZRange_Limited = .true. - FileDat%BinaryFormat = Grid3DField%WindFileFormat - FileDat%IsBinary = .true. - FileDat%MWS = Grid3DField%MeanWS + if (G3D%Periodic) then + G3D%InitXPosition = 0 ! start at the hub + G3D%TotalTime = G3D%NSteps*G3D%DTime + else + G3D%InitXPosition = G3D%YHWid ! start half the grid width ahead of the turbine + G3D%TotalTime = (G3D%NSteps - 1)*G3D%DTime + end if - FileDat%TI = 0.0_ReKi - FileDat%TI_listed = .false. + IF (InitInp%NativeBladedFmt) THEN + G3D%InitXPosition = G3D_InitInp%XOffset + END IF -end subroutine + !------------------------------------------------------------------------------------------------- + ! Set the InitOutput information + !------------------------------------------------------------------------------------------------- + + InitOut%TI = TI + + !------------------------------------------------------------------------------------------------- + ! Write to the summary file + !------------------------------------------------------------------------------------------------- + + if (SumFileUnit > 0) then + write (SumFileUnit, '(A)') + write (SumFileUnit, '(A)') 'Bladed-style wind type. Read by InflowWind sub-module '// & + TRIM(FlowField_IO_Ver%Name)//' '//TRIM(FlowField_IO_Ver%Ver) + write (SumFileUnit, '(A)') TRIM(TmpErrMsg) + write (SumFileUnit, '(A)') ' FileName: '//TRIM(InitInp%WindFileName) + write (SumFileUnit, '(A34,I3)') ' Binary file format id: ', G3D%WindFileFormat + write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', G3D%RefHeight + write (SumFileUnit, '(A34,G12.4)') ' Timestep (s): ', G3D%DTime + write (SumFileUnit, '(A34,I12)') ' Number of timesteps: ', G3D%NSteps + write (SumFileUnit, '(A34,G12.4)') ' Mean windspeed (m/s): ', G3D%MeanWS + write (SumFileUnit, '(A)') ' Characteristic TI: [ '// & + TRIM(Num2LStr(TI(1)))//', '//TRIM(Num2LStr(TI(2)))//', '//TRIM(Num2LStr(TI(3)))//' ] ' + write (SumFileUnit, '(A34,L1)') ' Windfile is periodic: ', G3D%Periodic + write (SumFileUnit, '(A34,L1)') ' Windfile includes tower: ', G3D%NTGrids > 0 + + if (G3D%Periodic) then + write (SumFileUnit, '(A)') ' Time range (s): [ '// & + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(G3D%TotalTime))//' ]' + else ! Shift the time range to compensate for the shifting of the wind grid + write (SumFileUnit, '(A)') ' Time range (s): [ '// & + TRIM(Num2LStr(-G3D%InitXPosition*G3D%InvMWS))//' : '// & + TRIM(Num2LStr(G3D%TotalTime - G3D%InitXPosition*G3D%InvMWS))//' ]' + end if + + write (SumFileUnit, '(A)') ' Y range (m): [ '// & + TRIM(Num2LStr(-G3D%YHWid))//' : '//TRIM(Num2LStr(G3D%YHWid))//' ]' + + if (G3D%NTGrids > 0) then + write (SumFileUnit, '(A)') ' Z range (m): [ '// & + TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(G3D%RefHeight + G3D%ZHWid))//' ]' + else + write (SumFileUnit, '(A)') ' Z range (m): [ '// & + TRIM(Num2LStr(G3D%RefHeight - G3D%ZHWid))//' : '//TRIM(Num2LStr(G3D%RefHeight + G3D%ZHWid))//' ]' + end if + + ! We are assuming that if the last line was written ok, then all of them were. + if (TmpErrStat /= 0_IntKi) then + call SetErrStat(ErrID_Fatal, 'Error writing to summary file.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + +end subroutine Bladed_ReadFile + +subroutine Bladed_ReadTurbSimSummary(UnitWind, FileName, CWise, ZCenter, TI, UBar, RefHt, Periodic, LHR, ErrStat, ErrMsg) + + character(*), parameter :: RoutineName = "Bladed_ReadTurbSimSummary" + + ! Passed variables + integer(IntKi), intent(in) :: UnitWind !< unit number for the file to open + character(*), intent(in) :: FileName !< name of the summary file + logical, intent(out) :: CWise !< rotation (for reading the order of the binary data) + real(ReKi), intent(out) :: ZCenter !< the height at the center of the grid + real(ReKi), intent(out) :: TI(3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI + real(ReKi), intent(out) :: UBar !< mean (advection) wind speed + real(ReKi), intent(out) :: RefHt !< Reference height + logical, intent(out) :: Periodic !< rotation (for reading the order of the binary data) + logical, intent(out) :: LHR !< Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) + integer(IntKi), intent(out) :: ErrStat !< returns 0 if no error encountered in the subroutine + character(*), intent(out) :: ErrMsg !< holds the error messages + + ! Local variables + real(ReKi) :: ZGOffset ! The vertical offset of the turbine on rectangular grid (allows turbulence not centered on turbine hub) + + integer, parameter :: NumStrings = 7 ! number of strings to be looking for in the file + + integer(IntKi) :: FirstIndx ! The first character of a line where data is located + integer(IntKi) :: I ! A loop counter + integer(IntKi) :: LastIndx ! The last character of a line where data is located + integer(IntKi) :: LineCount ! Number of lines that have been read in the file + + logical :: StrNeeded(NumStrings) ! if the string has been found + + character(1024) :: LINE ! temporary storage for reading a line from the file + + ! Temporary variables for error handling + integer(IntKi) :: TmpErrStat ! temporary error status + character(ErrMsgLen) :: TmpErrMsg ! temporary error message + + !---------------------------------------------------------------------------------------------- + ! Initialize some variables + !---------------------------------------------------------------------------------------------- + + ErrStat = ErrID_None + ErrMsg = '' + + LineCount = 0 + StrNeeded(:) = .true. + ZGOffset = 0.0 + RefHt = 0.0 + Periodic = .false. + LHR = .false. + CWise = .false. ! default value, in case it is not in this file + + !---------------------------------------------------------------------------------------------- + ! Open summary file. + !---------------------------------------------------------------------------------------------- + + call OpenFInpFile(UnitWind, TRIM(FileName), TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + !---------------------------------------------------------------------------------------------- + ! Read the summary file. + !---------------------------------------------------------------------------------------------- + + ! Here are the strings we're looking for, in this order: + ! 1) 'CLOCKWISE' (optional) + ! 2) 'HUB HEIGHT' + ! 3) (unused; decided we didn't need to read data also stored in the binary file) + ! 4) 'UBAR' + ! 5) 'HEIGHT OFFSET' (optional) + ! 6) 'PERIODIC' (optional) + ! 7) 'BLADED LEFT-HAND RULE' (optional) + + do while ((ErrStat == ErrID_None) .and. StrNeeded(NumStrings)) + + LineCount = LineCount + 1 + + read (UnitWind, '(A)', IOSTAT=TmpErrStat) LINE + if (TmpErrStat /= 0) then + + ! the "HEIGHT OFFSET", "PERIODIC", and "BLADED LEFT-HAND RULE" parameters are not necessary. We'll assume they are zero/false if we didn't find it. + ! We will also assume "CLOCKWISE" is false if we didn't find it. + if (StrNeeded(2) .or. StrNeeded(4)) then + call SetErrStat(ErrID_Fatal, ' Error reading line #'//TRIM(Num2LStr(LineCount))//' of the summary file, "'// & + TRIM(FileName)//'". Could not find all of the required parameters.', ErrStat, ErrMsg, RoutineName) + return + else + exit + end if + + end if + + call Conv2UC(LINE) + + if (StrNeeded(2)) then ! if "CLOCKWISE" (StrNeeded(1)) is in the file, we would have already read it. If not, it's not in this file. + + if (StrNeeded(1)) then + + !------------------------------------------------------------------------------------------- + ! #1: Get the rotation direction, using the string "CLOCKWISE" + !------------------------------------------------------------------------------------------- + + if (INDEX(LINE, 'CLOCKWISE') > 0) then + + read (LINE, *, IOSTAT=TmpErrStat) CWise ! Look for True/False values + + if (TmpErrStat /= 0) then ! Look for Yes/No values instead + + LINE = ADJUSTL(LINE) ! Remove leading spaces from input line + + select case (LINE(1:1)) + case ('Y') + CWise = .true. + case ('N') + CWise = .false. + case DEFAULT + call SetErrStat(ErrID_Fatal, ' Error reading rotation direction (CLOCKWISE) from FF summary file.', ErrStat, ErrMsg, RoutineName) + return + end select + cycle + + end if ! TmpErrStat /= 0 + StrNeeded(1) = .false. + + end if ! INDEX for "CLOCKWISE" + + end if + + !------------------------------------------------------------------------------------------- + ! #2: Get the hub height, using the strings "HUB HEIGHT" or "ZHUB" + !------------------------------------------------------------------------------------------- + + if (INDEX(LINE, 'HUB HEIGHT') > 0 .or. INDEX(LINE, 'ZHUB') > 0) then + + read (LINE, *, IOSTAT=TmpErrStat) RefHt + + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading hub height from FF summary file.', ErrStat, ErrMsg, RoutineName) + return + end if + StrNeeded(2) = .false. + + end if !INDEX for "HUB HEIGHT" or "ZHUB" + + ! ELSEIF ( StrNeeded(3) ) THEN + ! + ! !------------------------------------------------------------------------------------------- + ! ! #3: Get the grid width (& height, if available), using the strings "GRID WIDTH" or "RDIAM" + ! ! If GRID HEIGHT is specified, use it, too. -- THIS IS UNNECESSARY AS IT'S STORED IN THE BINARY FILE + ! !------------------------------------------------------------------------------------------- + + elseif (StrNeeded(4)) then + + !------------------------------------------------------------------------------------------- + ! #4: Get the mean wind speed "UBAR" and turbulence intensities from following lines for + ! scaling Bladed-style FF binary files + !------------------------------------------------------------------------------------------- + + if (INDEX(LINE, 'UBAR') > 0) then + + FirstIndx = INDEX(LINE, '=') + 1 ! Look for the equal siqn to find the number we're looking for + + read (LINE(FirstIndx:LEN(LINE)), *, IOSTAT=TmpErrStat) UBar + + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading UBar binary data normalizing parameter from FF summary file.', ErrStat, ErrMsg, RoutineName) + return + end if + + do I = 1, 3 + + LineCount = LineCount + 1 + + read (UnitWind, '(A)', IOSTAT=TmpErrStat) LINE + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading line #'//TRIM(Num2LStr(LineCount))//' of the summary file, "'//TRIM(FileName)// & + '". Could not find all of the required parameters.', ErrStat, ErrMsg, RoutineName) + return + end if + + FirstIndx = INDEX(LINE, '=') + 1 ! Read the number between the = and % signs + LastIndx = INDEX(LINE, '%') - 1 + + if (LastIndx <= FirstIndx) LastIndx = LEN(LINE) ! If there's no % sign, read to the end of the line + + read (LINE(FirstIndx:LastIndx), *, IOSTAT=TmpErrStat) TI(I) + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading TI('//TRIM(Num2LStr(I))// & + ') binary data normalizing parameter from FF summary file.', ErrStat, ErrMsg, RoutineName) + return + end if + + end do !I + + StrNeeded(4) = .false. + + end if + + elseif (StrNeeded(5)) then + + !------------------------------------------------------------------------------------------- + ! #5: Get the grid "HEIGHT OFFSET", if it exists (in TurbSim). Otherwise, assume it's zero + ! ZGOffset = HH - GridBase - ParamData%FF%FFZHWid + !------------------------------------------------------------------------------------------- + if (INDEX(LINE, 'HEIGHT OFFSET') > 0) then + + FirstIndx = INDEX(LINE, '=') + 1 + + read (LINE(FirstIndx:LEN(LINE)), *, IOSTAT=TmpErrStat) ZGOffset + + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading height offset from FF summary file.', ErrStat, ErrMsg, RoutineName) + return + end if + + StrNeeded(5) = .false. + + end if !INDEX for "HEIGHT OFFSET" + + else + + if (StrNeeded(6)) then + + !------------------------------------------------------------------------------------------- + ! #6: Get the grid "PERIODIC", if it exists (in TurbSim). Otherwise, assume it's + ! not a periodic file (would only show up if the HEIGHT OFFSET is in the file) + !------------------------------------------------------------------------------------------- + if (INDEX(LINE, 'PERIODIC') > 0) then + + Periodic = .true. + StrNeeded(6) = .false. + cycle + end if !INDEX for "PERIODIC" + end if + + if (StrNeeded(7)) then + + if (INDEX(LINE, 'BLADED LEFT-HAND RULE') > 0) then + LHR = .true. + StrNeeded(7) = .false. + end if ! INDEX for "BLADED LEFT-HAND RULE" + + end if + + end if ! StrNeeded + + end do !WHILE + + !------------------------------------------------------------------------------------------------- + ! Close the summary file + !------------------------------------------------------------------------------------------------- + + close (UnitWind) + + !------------------------------------------------------------------------------------------------- + ! Calculate the height of the grid center + !------------------------------------------------------------------------------------------------- + + ZCenter = RefHt - ZGOffset + +end subroutine Bladed_ReadTurbSimSummary + +subroutine Bladed_ReadNativeSummary(FileName, PLExp, VLinShr, HLinShr, RefLength, TI, & + UBar, RefHt, PropagationDir, VFlowAngle, BinFileName, & + XOffset, ErrStat, ErrMsg) + + character(*), intent(in) :: FileName !< name of the summary file + real(ReKi), intent(out) :: PLExp !< the power-law exponent for vertical wind shear + real(ReKi), intent(out) :: VLinShr !< the linear shape for vertical wind shear + real(ReKi), intent(out) :: HLinShr !< the linear shape for horizontal wind shear + real(ReKi), intent(out) :: RefLength !< Reference (rotor) diameter + real(ReKi), intent(out) :: TI(3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI + real(ReKi), intent(out) :: UBar !< mean (advection) wind speed + real(ReKi), intent(out) :: RefHt !< Reference height + real(ReKi), intent(out) :: PropagationDir !< propagation direction + real(ReKi), intent(out) :: VFlowAngle !< vertical flow angle + character(*), intent(out) :: BinFileName !< name of the binary file containing wind data + real(ReKi), intent(out) :: XOffset !< distance offset for start of wind files + integer(IntKi), intent(out) :: ErrStat !< returns 0 if no error encountered in the subroutine + character(*), intent(out) :: ErrMsg !< holds the error messages + + character(*), parameter :: RoutineName = "Bladed_ReadNativeSummary" + integer(IntKi), parameter :: UnEc = -1 ! echo file unit number (set to something else > 0 for debugging) + integer(IntKi) :: CurLine ! Current line to parse in FileInfo data structure + integer(IntKi) :: ErrStat2 ! temporary error status + character(ErrMsgLen) :: ErrMsg2 ! temporary error message + + type(FileInfoType) :: FileInfo ! The derived type for holding the file information. + + ErrStat = ErrID_None + ErrMsg = '' + +!---------------------------------------------------------------------------- +! Open and read the summary file; store data in FileInfo structure. +!---------------------------------------------------------------------------- + + call ProcessComFile(FileName, FileInfo, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + +!---------------------------------------------------------------------------- +! Process the lines stored in FileInfo +!---------------------------------------------------------------------------- + + CurLine = 1 + + call ParseVar(FileInfo, CurLine, 'UBAR', UBar, ErrStat2, ErrMsg2, UnEc) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call ParseVar(FileInfo, CurLine, 'REFHT', RefHt, ErrStat2, ErrMsg2, UnEc) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call ParseVar(FileInfo, CurLine, 'TI', TI(1), ErrStat2, ErrMsg2, UnEc) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call ParseVar(FileInfo, CurLine, 'TI_V', TI(2), ErrStat2, ErrMsg2, UnEc) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call ParseVar(FileInfo, CurLine, 'TI_W', TI(3), ErrStat2, ErrMsg2, UnEc) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call ParseVar(FileInfo, CurLine, 'WDIR', PropagationDir, ErrStat2, ErrMsg2, UnEc) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + PropagationDir = R2D*PropagationDir + + call ParseVar(FileInfo, CurLine, 'FLINC', VFlowAngle, ErrStat2, ErrMsg2, UnEc) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + VFlowAngle = R2D*VFlowAngle ! convert to degrees + + call ParseVar(FileInfo, CurLine, 'WINDF', BinFileName, ErrStat2, ErrMsg2, UnEc) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call ParseVar(FileInfo, CurLine, 'WSHEAR', PLExp, ErrStat2, ErrMsg2, UnEc) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + end if + + call ParseVar(FileInfo, CurLine, 'VLINSHEAR', VLinShr, ErrStat2, ErrMsg2, UnEc) + if (ErrStat2 /= ErrID_None) then + VLinShr = 0.0_ReKi ! this will be the default if VLINSHEAR is not in the file + end if + + call ParseVar(FileInfo, CurLine, 'HLINSHEAR', HLinShr, ErrStat2, ErrMsg2, UnEc) + if (ErrStat2 /= ErrID_None) then + HLinShr = 0.0_ReKi ! this will be the default if HLINSHEAR is not in the file + end if + + call ParseVar(FileInfo, CurLine, 'REFLENGTH', RefLength, ErrStat2, ErrMsg2, UnEc) + if (ErrStat2 /= ErrID_None) then + RefLength = 0.0_ReKi ! this will be the default if RefLength is not in the file; it will cause an error if either of the linear shears are non-zero + end if + + call ParseVar(FileInfo, CurLine, 'XOffset', XOffset, ErrStat2, ErrMsg2, UnEc) + if (ErrStat2 /= ErrID_None) then + XOffset = 0.0_ReKi ! this will be the default if offset is not in the file + end if + +!---------------------------------------------------------------------------- +! Clean FileInfo data structure (including pointers and allocatable arrays) +!---------------------------------------------------------------------------- + + call Cleanup() + +contains + + subroutine Cleanup() + call NWTC_Library_DestroyFileInfoType(FileInfo, ErrStat2, ErrMsg2) + end subroutine Cleanup + +end subroutine Bladed_ReadNativeSummary + +!==================================================================================================== +!> Reads the binary headers from the turbulence files of the old Bladed variety. Note that + !! because of the normalization, neither ParamData%FF%NZGrids or ParamData%FF%NYGrids are larger than 32 points. + !! 21-Sep-2009 - B. Jonkman, NREL/NWTC. + !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 +subroutine Bladed_ReadHeader0(WindFileUnit, G3D, NativeBladedFmt, ErrStat, ErrMsg) + + integer(IntKi), intent(in) :: WindFileUnit !< unit number of already-opened wind file + type(Grid3DFieldType), intent(inout) :: G3D !< Parameters + logical, intent(in) :: NativeBladedFmt !< Whether this should ignore the advection speed in the binary file + integer(IntKi), intent(out) :: ErrStat !< error status + character(*), intent(out) :: ErrMsg !< error message + + type :: HeaderType + integer(B2Ki) :: NComp + integer(B2Ki) :: DeltaZ, DeltaY, DeltaX + integer(B2Ki) :: NStepsHalf, MWS10 + integer(B2Ki) :: zLu, yLu, xLu, dummy, rnd + integer(B2Ki) :: NZ1000, NY1000 + end type + + character(*), parameter :: RoutineName = "Bladed_ReadHeader0" + real(ReKi) :: FFXDelt + real(ReKi) :: FFYDelt + real(ReKi) :: FFZDelt + + type(HeaderType) :: header + integer(B2Ki) :: dummy(6) + integer(IntKi) :: iostat ! for checking the IOSTAT from a READ or Open statement + + ErrStat = ErrID_None + ErrMsg = '' + + !---------------------------------------------------------------------------- + ! Read the header (file has just been opened) + !---------------------------------------------------------------------------- + + ! Read header + read (WindFileUnit, IOSTAT=iostat) header + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading header 0 from binary FF file.', & + ErrStat, ErrMsg, RoutineName) + return + end if + + G3D%NComp = -1*header%NComp + + FFZDelt = 0.001*header%DeltaZ + G3D%InvDZ = 1.0/FFZDelt + + FFYDelt = 0.001*header%DeltaY + G3D%InvDY = 1.0/FFYDelt + + FFXDelt = 0.001*header%DeltaX + G3D%NSteps = 2*header%NStepsHalf + + if (.not. NativeBladedFmt) G3D%MeanWS = 0.1*header%MWS10 + G3D%InvMWS = 1.0/G3D%MeanWS + G3D%DTime = FFXDelt/G3D%MeanWS + G3D%Rate = 1.0/G3D%DTime + + G3D%NZGrids = header%NZ1000/1000 + G3D%ZHWid = 0.5*FFZDelt*(G3D%NZGrids - 1) + + G3D%NYGrids = header%NY1000/1000 + G3D%YHWid = 0.5*FFYDelt*(G3D%NYGrids - 1) + + if (G3D%NComp == 3) then + read (WindFileUnit, IOSTAT=iostat) dummy + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading header 0 from binary FF file.', & + ErrStat, ErrMsg, RoutineName) + return + end if + end if + +end subroutine Bladed_ReadHeader0 + +subroutine Bladed_ReadHeader1(UnitWind, TI, G3D, NativeBladedFmt, ErrStat, ErrMsg) + + integer(IntKi), intent(in) :: UnitWind !< unit number of already-opened wind file + real(ReKi), intent(out) :: TI(3) !< turbulence intensity contained in file header + type(Grid3DFieldType), intent(inout) :: G3D !< Parameters + logical, intent(in) :: NativeBladedFmt !< Whether this should ignore the advection speed in the binary file + integer(IntKi), intent(out) :: ErrStat !< error status + character(*), intent(out) :: ErrMsg !< error message + + type :: Turb4Type + integer(B4Ki) :: NComp + real(SiKi) :: Latitude, RoughLen, RefHeight, TurbInt(3) + end type + + type :: Turb78Type + integer(B4Ki) :: HeaderSize, NComp + end type + + type :: Turb7Type + real(SiKi) :: CoherenceDecay, CoherenceScale + end type + + type :: Turb8Type + real(SiKi) :: dummy1(6) + integer(B4Ki) :: dummy2(3) + real(SiKi) :: dummy3(2) + integer(B4Ki) :: dummy4(3) + real(SiKi) :: dummy5(2) + end type + + type :: Sub1Type + real(SiKi) :: DeltaZ, DeltaY, DeltaX + integer(B4Ki) :: NStepsHalf + real(SiKi) :: MeanWS, zLu, yLu, xLu + integer(B4Ki) :: dummy, rnd, NZ, NY + end type + + type :: Sub2Type + real(SiKi) :: zLv, yLv, xLv, zLw, yLw, xLw + end type + + character(*), parameter :: RoutineName = "Bladed_ReadHeader1" + + type(Turb4Type) :: Turb4 + type(Turb78Type) :: Turb78 + type(Sub1Type) :: Sub1 + type(Sub2Type) :: Sub2 + type(Turb7Type) :: Turb7 + type(Turb8Type) :: Turb8 + + real(ReKi) :: FFXDelt + real(ReKi) :: FFYDelt + real(ReKi) :: FFZDelt + integer(B2Ki) :: Dum_Int2 + integer(B2Ki) :: TurbType + integer(IntKi) :: iostat + + ErrStat = ErrID_None + ErrMsg = '' + + ! Initialize turbulence intensities + TI(:) = -1 !Initialize to -1 (not all models contain TI) + + !---------------------------------------------------------------------------- + ! File reading + !---------------------------------------------------------------------------- + + ! Read 2-byte integer. Can't use library routines for this. + read (UnitWind, IOSTAT=iostat) Dum_Int2 ! -99 (file ID) + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading integer from binary FF file.', ErrStat, ErrMsg, RoutineName) + return + end if + + ! Read 2-byte integer. Can't use library routines for this. + read (UnitWind, IOSTAT=iostat) TurbType ! turbulence type + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading turbulence type from binary FF file.', ErrStat, ErrMsg, RoutineName) + return + end if + + select case (TurbType) + + case (1, 2) ! 1-component Von Karman (1) or Kaimal (2) + G3D%NComp = 1 + + case (3, 5) ! 3-component Von Karman (3) or IEC-2 Kaimal (5) + G3D%NComp = 3 + + case (4) ! improved Von Karman + + read (UnitWind, IOSTAT=iostat) Turb4 + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading number of components from binary FF file.', & + ErrStat, ErrMsg, RoutineName) + return + end if + + G3D%NComp = Turb4%NComp + TI = Turb4%TurbInt + + case (7, 8) ! General Kaimal (7) or Mann model (8) + + read (UnitWind, IOSTAT=iostat) Turb78 + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading number of header records from binary FF file.', & + ErrStat, ErrMsg, RoutineName) + return + end if + + G3D%NComp = Turb78%NComp + + case DEFAULT + + call SetErrStat(ErrID_Warn, ' InflowWind does not recognize the full-field turbulence file type ='// & + TRIM(Num2LStr(int(TurbType)))//'.', ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + end select + + read (UnitWind, IOSTAT=iostat) Sub1 + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading header Sub1 from binary FF file.', ErrStat, ErrMsg, RoutineName) + return + end if + + FFZDelt = Sub1%DeltaZ + G3D%InvDZ = 1.0/FFZDelt + + FFYDelt = Sub1%DeltaY + G3D%InvDY = 1.0/FFYDelt + + FFXDelt = Sub1%DeltaX + + G3D%NSteps = 2*Sub1%NStepsHalf + + if (.not. NativeBladedFmt) G3D%MeanWS = Sub1%MeanWS + G3D%InvMWS = 1.0/G3D%MeanWS + G3D%DTime = FFXDelt/G3D%MeanWS + G3D%Rate = 1.0/G3D%DTime + + G3D%NZGrids = Sub1%NZ + G3D%ZHWid = 0.5*FFZDelt*(G3D%NZGrids - 1) ! half the vertical size of the grid + + G3D%NYGrids = Sub1%NY + G3D%YHWid = 0.5*FFYDelt*(G3D%NYGrids - 1) + + ! unused variables: zLv, yLv, xLv, zLw, yLw, xLw + if (G3D%NComp == 3) then + read (UnitWind, IOSTAT=iostat) Sub2 + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading 4-byte length scales from binary FF file.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + + select case (TurbType) + case (7) ! General Kaimal model + + ! Unused variables: coherence decay constant and coherence scale parameter in m + read (UnitWind, IOSTAT=iostat) Turb7 + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading header for Turb7 from binary FF file.', & + ErrStat, ErrMsg, RoutineName) + return + end if + + case (8) ! Mann model + + ! Unused variables + read (UnitWind, IOSTAT=iostat) Turb8 + if (iostat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading header for Turb8 from binary FF file.', & + ErrStat, ErrMsg, RoutineName) + return + end if + + end select !TurbType + +end subroutine Bladed_ReadHeader1 + +subroutine Bladed_ReadGrids(UnitWind, NativeBladedFmt, CWise, LHR, TI, G3D, ErrStat, ErrMsg) + + integer(IntKi), intent(in) :: UnitWind !< unit number of already-opened wind file + logical, intent(in) :: NativeBladedFmt !< whether this data is in native Bladed format (scale to zero mean and unit standard deviation) + logical, intent(in) :: CWise !< clockwise flag (determines if y is increasing or decreasing in file) + logical, intent(in) :: LHR !< Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) + real(ReKi), intent(in) :: TI(3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI + type(Grid3DFieldType), intent(inout) :: G3D !< Parameters + integer(IntKi), intent(out) :: ErrStat !< error status + character(*), intent(out) :: ErrMsg !< error message + + character(*), parameter :: RoutineName = "Bladed_ReadGrids" + real(ReKi) :: FF_Scale(3) !< used for "un-normalizing" the data + real(ReKi) :: FF_Offset(3) !< used for "un-normalizing" the data + integer(B2Ki), allocatable :: raw_ff(:, :, :) + integer(IntKi) :: CFirst, CLast, CStep + integer(IntKi) :: IC, IR, IT + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + + ErrMsg = "" + ErrStat = ErrID_None + + if (NativeBladedFmt) then + FF_Scale = 0.001_ReKi + FF_Offset = 0.0_ReKi + else + FF_Scale = 0.001_ReKi*G3D%MeanWS*TI/100.0_ReKi + FF_Offset = (/G3D%MeanWS, 0.0_ReKi, 0.0_ReKi/) ! used for "un-normalizing" the data + end if + + ! Bladed convention has positive V pointed along negative Y + if (LHR) then ! left-hand rule + FF_Scale(2) = -FF_Scale(2) + end if + + !---------------------------------------------------------------------------- + ! Generate an informative message + !---------------------------------------------------------------------------- + ! This could take a while, so we'll write a message to tell users what's going on: + + call WrScr(NewLine//' Reading a '//TRIM(Num2LStr(G3D%NYGrids))//'x'// & + TRIM(Num2LStr(G3D%NZGrids))// & + ' grid ('//TRIM(Num2LStr(G3D%YHWid*2))//' m wide, '// & + TRIM(Num2LStr(G3D%GridBase))//' m to '// & + TRIM(Num2LStr(G3D%GridBase + G3D%ZHWid*2))// & + ' m above ground) with a characteristic wind speed of '// & + TRIM(Num2LStr(G3D%MeanWS))//' m/s. ') + + !---------------------------------------------------------------------------- + ! Allocate space for the data array + !---------------------------------------------------------------------------- + + ! Add another step, just in case there is an odd number of steps. + G3D%NSteps = G3D%NSteps + 1 + + ! If velocity array is allocated and the size is wrong, deallocate + if (allocated(G3D%Vel)) then + if (SIZE(G3D%Vel, 1) /= G3D%NZGrids .or. & + SIZE(G3D%Vel, 2) /= G3D%NYGrids .or. & + SIZE(G3D%Vel, 3) /= G3D%NComp .or. & + SIZE(G3D%Vel, 3) /= G3D%NSteps) then + deallocate (G3D%Vel) + end if + end if + + ! If velocity array isn't allocated, allocate it with proper size + if (.not. ALLOCATED(G3D%Vel)) then + call AllocAry(G3D%Vel, G3D%NComp, G3D%NYGrids, G3D%NZGrids, G3D%NSteps, & + 'Full-field wind data array.', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + ! Allocate space to read all data for a given time slice + allocate (raw_ff(G3D%NComp, G3D%NYGrids, G3D%NZGrids), STAT=TmpErrStat) + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating memory for '// & + TRIM(Num2LStr(G3D%NComp*G3D%NYGrids*G3D%NZGrids))// & + ' B2Ki in the raw data array.', ErrStat, ErrMsg, RoutineName) + return + end if + + !---------------------------------------------------------------------------- + ! Initialize the data and set column indexing to account for + ! direction of turbine rotation (CWise) + !---------------------------------------------------------------------------- + + ! Initialize velocity components not in file to zero + do IC = G3D%NComp + 1, 3 + G3D%Vel(IC, :, :, :) = 0.0_SiKi + end do + + if (CWise) then + CFirst = G3D%NYGrids + CLast = 1 + CStep = -1 + else + CFirst = 1 + CLast = G3D%NYGrids + CStep = 1 + end if + + !---------------------------------------------------------------------------- + ! Loop through all the time steps, reading the data and converting to m/s + !---------------------------------------------------------------------------- + + ! Loop through time steps + do IT = 1, G3D%NSteps + + ! Read raw data (NFFComp,NYGrids,NZGrids) + read (UnitWind, IOStat=TmpErrStat) raw_ff + + ! If data was read successfully, transfer into velocity array, continue + if (TmpErrStat == 0) then + do IC = 1, G3D%NComp + G3D%Vel(IC, :, :, IT) = real(FF_Offset(IC) + FF_Scale(IC)*raw_ff(IC, CFirst:CLast:CStep, :), SiKi) + end do + cycle + end if + + ! If time iterator equals number of steps, then the number of steps were even + ! so fix the number of steps and exit loop + if (IT == G3D%NSteps) then + G3D%NSteps = G3D%NSteps - 1 + ErrStat = ErrID_None + exit + end if + + ! Otherwise, an error occurred reading the file, return + call SetErrStat(ErrID_Fatal, ' Error reading binary data file. '// & + 'ic = '//TRIM(Num2LStr(ic))// & + ', ir = '//TRIM(Num2LStr(ir))// & + ', it = '//TRIM(Num2LStr(it))// & + ', nffsteps = '//TRIM(Num2LStr(G3D%NSteps)), ErrStat, ErrMsg, RoutineName) + return + end do + + if (G3D%Periodic) then + call WrScr(NewLine//' Processed '//TRIM(Num2LStr(G3D%NSteps))//' time steps of '// & + TRIM(Num2LStr(G3D%Rate))//'-Hz full-field data (period of '// & + TRIM(Num2LStr(G3D%DTime*G3D%NSteps))//' seconds).') + + else + call WrScr(NewLine//' Processed '//TRIM(Num2LStr(G3D%NSteps))//' time steps of '// & + TRIM(Num2LStr(G3D%Rate))//'-Hz full-field data ('// & + TRIM(Num2LStr(G3D%DTime*(G3D%NSteps - 1)))//' seconds).') + end if + +end subroutine Bladed_ReadGrids + +subroutine Bladed_ReadTower(UnitWind, G3D, TwrFileName, ErrStat, ErrMsg) + + integer(IntKi) :: UnitWind !< unit number of wind file to be opened + type(Grid3DFieldType), intent(inout) :: G3D !< Parameters + character(*), intent(in) :: TwrFileName + integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) + character(*), intent(out) :: ErrMsg !< a message for errors that occur + + type :: HeaderType + real(SiKi) :: DZ, DX, Zmax + integer(B4Ki) :: NumOutSteps, NumZ + real(SiKi) :: UHub, TI(3) + end type + + character(*), parameter :: RoutineName = "Bladed_ReadTower" + real(ReKi), parameter :: FF_Offset(3) = (/1.0, 0.0, 0.0/) ! used for "un-normalizing" the data + real(ReKi), parameter :: TOL = 1E-4 ! tolerence for wind file comparisons + integer(IntKi) :: IC, IT ! loop counters + real(SiKi) :: TI(3) ! scaling values for "un-normalizing the data" [approx. turbulence intensities of the wind components] + integer(B2Ki), allocatable :: raw_twr(:, :) ! holds tower velocity for one timestep + type(HeaderType) :: header + integer(IntKi) :: TmpErrStat ! IOSTAT value. + character(ErrMsgLen) :: TmpErrMsg + + ErrMsg = '' + ErrStat = ErrID_None + + !---------------------------------------------------------------------------- + ! Initialization + !---------------------------------------------------------------------------- + + ! If number of wind components is not three, return with error + if (G3D%NComp /= 3) then + call SetErrStat(ErrID_Fatal, ' Error: Tower binary files require 3 wind components.', & + ErrStat, ErrMsg, RoutineName) + return + end if + + ! Initialize the number of tower grids to zero + G3D%NTGrids = 0 + + !---------------------------------------------------------------------------- + ! Open the file + !---------------------------------------------------------------------------- + + call OpenBInpFile(UnitWind, TRIM(TwrFileName), TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + !---------------------------------------------------------------------------- + ! Read the header information and check that it's compatible with the + ! FF Bladed-style binary parameters already read. + !---------------------------------------------------------------------------- + + read (UnitWind, IOSTAT=TmpErrStat) header + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, & + ' Error reading header of the binary tower file "' & + //TRIM(TwrFileName)//'."', ErrStat, ErrMsg, RoutineName) + return + end if + + ! If delta Z in file doesn't match tower file + if (ABS(header%DZ*G3D%InvDZ - 1) > TOL) then + call SetErrStat(ErrID_Fatal, ' Z resolution in the FF binary file does not match the tower file.', & + ErrStat, ErrMsg, RoutineName) + end if + + ! If X resolution doesn't match the tower file + if (ABS(header%DX*G3D%InvMWS/G3D%DTime - 1) > TOL) then + call SetErrStat(ErrID_Fatal, ' Time resolution in the FF binary file does not match the tower file.', & + ErrStat, ErrMsg, RoutineName) + end if + + ! If the height doesn't match the tower file + if (ABS(header%Zmax/G3D%GridBase - 1) > TOL) then + call SetErrStat(ErrID_Fatal, ' Height in the FF binary file does not match the tower file "'//TRIM(TwrFileName)//'."', & + ErrStat, ErrMsg, RoutineName) + end if + + ! Number of time steps doesn't match the tower file + if (header%NumOutSteps /= G3D%NSteps) then + call SetErrStat(ErrID_Fatal, ' Number of time steps in the FF binary file does not match the tower file.', & + ErrStat, ErrMsg, RoutineName) + end if + + ! If mean wind speed doesn't match tower file + if (ABS(header%UHub*G3D%InvMWS - 1) > TOL) then + call SetErrStat(ErrID_Fatal, ' Mean wind speed in the FF binary file does not match the tower file.', & + ErrStat, ErrMsg, RoutineName) + end if + + ! If any of the previous checks failed, or the number of tower grids is zero, + ! close the wind file and return + if (ErrStat >= AbortErrLev .or. header%NumZ == 0) then + close (UnitWind) + return + end if + + ! Set number of tower grids from header + G3D%NTGrids = header%NumZ + + ! Set turbulence intensity from header + TI = header%TI + + !---------------------------------------------------------------------------- + ! Allocate arrays for the tower points + !---------------------------------------------------------------------------- + + ! If tower array is allocated and the wrong size, deallocate + if (allocated(G3D%VelTower)) then + if (size(G3D%VelTower, 1) /= G3D%NComp .or. & + size(G3D%VelTower, 1) /= G3D%NTGrids .or. & + size(G3D%VelTower, 1) /= G3D%NSteps) then + deallocate (G3D%VelTower) + end if + end if + + ! If the tower array isn't allocated, allocate it + if (.not. ALLOCATED(G3D%VelTower)) then + call AllocAry(G3D%VelTower, G3D%NComp, G3D%NTGrids, G3D%NSteps, & + 'Tower wind data array.', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + ! Allocate space to read all data for a given time slice + allocate (raw_twr(G3D%NComp, G3D%NTGrids), STAT=TmpErrStat) + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating memory for '// & + TRIM(Num2LStr(G3D%NComp*G3D%NYGrids*G3D%NZGrids))// & + ' B2Ki in the raw data array.', ErrStat, ErrMsg, RoutineName) + return + end if + + !---------------------------------------------------------------------------- + ! Read the 16-bit time-series data and scale it to 32-bit reals + !---------------------------------------------------------------------------- + + ! Loop through time. + do IT = 1, G3D%NSteps + + ! Read wind compnents for this time slice. Can't use library read routines for this. + read (UnitWind, IOSTAT=TmpErrStat) raw_twr ! normalized wind-component, INT(2) + if (TmpErrStat /= 0) then + call SetErrStat(ErrID_Fatal, ' Error reading binary tower data file. it = '//TRIM(Num2LStr(it))// & + ', nffsteps = '//TRIM(Num2LStr(G3D%NSteps)), ErrStat, ErrMsg, RoutineName) + G3D%NTGrids = 0 + return + end if + + ! Loop through wind components and populate array after scaling to m/s + do IC = 1, G3D%NComp + G3D%VelTower(IC, :, IT) = real(G3D%MeanWS*(FF_Offset(IC) + 0.00001*TI(IC)*raw_twr(IC, :)), SiKi) + end do + end do + + !---------------------------------------------------------------------------- + ! Close the file + !---------------------------------------------------------------------------- + + close (UnitWind) + + call WrScr(NewLine//' Processed '//TRIM(Num2LStr(G3D%NSteps))//' time steps of '// & + TRIM(Num2LStr(G3D%NTGrids))//'x1 tower data grids.') + +end subroutine Bladed_ReadTower + +subroutine Grid3DField_PopulateWindFileDat(Grid3DField, FileName, WindType, HasTower, FileDat) + + type(Grid3DFieldType), intent(in) :: Grid3DField + character(*), intent(in) :: FileName + integer(IntKi), intent(in) :: WindType + logical, intent(in) :: HasTower + type(WindFileDat), intent(out) :: FileDat + + FileDat%FileName = FileName + FileDat%WindType = WindType + FileDat%RefHt = Grid3DField%RefHeight + FileDat%RefHt_Set = .true. + FileDat%DT = Grid3DField%DTime + FileDat%NumTSteps = Grid3DField%NSteps + FileDat%ConstantDT = .true. + + if (Grid3DField%Periodic) then + FileDat%TRange = [0.0_ReKi, Grid3DField%TotalTime] + FileDat%TRange_Limited = .false. + else ! Shift the time range to compensate for the shifting of the wind grid + FileDat%TRange = [0.0_ReKi, Grid3DField%TotalTime] - Grid3DField%InitXPosition*Grid3DField%InvMWS + FileDat%TRange_Limited = .true. + end if + + FileDat%YRange = [-Grid3DField%YHWid, Grid3DField%YHWid] + FileDat%YRange_Limited = .true. ! Hard boundaries enforced in y-direction + + ! If has tower data + if (HasTower) then + FileDat%ZRange = [0.0_Reki, Grid3DField%RefHeight + Grid3DField%ZHWid] + else + FileDat%ZRange = [Grid3DField%GridBase, Grid3DField%GridBase + Grid3DField%ZHWid*2.0] + end if + + FileDat%ZRange_Limited = .true. + FileDat%BinaryFormat = Grid3DField%WindFileFormat + FileDat%IsBinary = .true. + FileDat%MWS = Grid3DField%MeanWS + + FileDat%TI = 0.0_ReKi + FileDat%TI_listed = .false. + +end subroutine + +subroutine Grid3DField_AddMeanVelocity(InitInp, G3D) + + type(Grid3DInitInputType), intent(in) :: InitInp !< Initialization input data passed to the module + type(Grid3DFieldType), intent(inout) :: G3D !< Initialization input data passed to the module + + real(ReKi) :: Z ! height + real(ReKi) :: Y ! distance from centre in horizontal direction + real(ReKi) :: U ! mean wind speed + integer(IntKi) :: iz, iy ! loop counter + integer(IntKi) :: centre_y ! index of centre in y direction + + ! Loop through grid elevations + do iz = 1, G3D%NZGrids + + ! calculate height + Z = G3D%GridBase + (iz - 1)/G3D%InvDZ + if (Z <= 0.0_ReKi) cycle + + ! Calculate wind speed to add based on profile + select case (G3D%WindProfileType) + + case (WindProfileType_PL) + U = G3D%MeanWS*(Z/G3D%RefHeight)**G3D%PLExp ! [IEC 61400-1 6.3.1.2 (10)] + + case (WindProfileType_Log) + if (.not. EqualRealNos(G3D%RefHeight, G3D%Z0) .and. Z > 0.0_ReKi) then + U = G3D%MeanWS*(LOG(Z/G3D%Z0))/(LOG(G3D%RefHeight/G3D%Z0)) + else + U = 0.0_ReKi + end if + + case (WindProfileType_Constant) + U = G3D%MeanWS + + case DEFAULT + U = 0.0_ReKi + + end select + + ! Add vertical linear shear, if nonzero + if (InitInp%VLinShr /= 0.0_ReKi) then + U = U + G3D%MeanWS*InitInp%VLinShr*(Z - G3D%RefHeight)/G3D%RefLength + end if + + ! Add velocity + G3D%Vel(1, :, iz, :) = real(G3D%Vel(1, :, iz, :) + U, SiKi) + + end do + + ! Add horizontal linear shear, if nonzero + if (InitInp%HLinShr /= 0.0_ReKi) then + + ! find the center point of the grid (if we don't have an odd number of grid points, we'll pick the point closest to the center) + centre_y = (G3D%NYGrids + 1)/2 ! integer division + + ! Loop through grid Y coordinates + do iy = 1, G3D%NYGrids + Y = (iy - centre_y)/G3D%InvDY + U = G3D%MeanWS*InitInp%HLinShr*Y/G3D%RefLength + G3D%Vel(1, iy, :, :) = real(G3D%Vel(1, iy, :, :) + U, SiKi) + end do + end if + +end subroutine Grid3DField_AddMeanVelocity + +subroutine ScaleTurbulence(InitInp, Vel, ScaleFactors, ErrStat, ErrMsg) + + type(Grid3DInitInputType), intent(IN) :: InitInp !< Initialization input data passed to the module + real(SiKi), intent(INOUT) :: Vel(:, :, :, :) !< full-field wind inflow data + real(ReKi), intent(OUT) :: ScaleFactors(3) !< scaling factors that were used + integer(IntKi), intent(OUT) :: ErrStat !< determines if an error has been encountered + character(*), intent(OUT) :: ErrMsg !< Message about errors + + ! Local Variables: + ! note that the variables used to compute statistics use double precision: + character(*), parameter :: RoutineName = 'ScaleTurbulence' + real(DbKi) :: v(3) ! instanteanous wind speed at target position + real(DbKi) :: vMean(3) ! average wind speeds over time at target position + real(DbKi) :: vSum(3) ! sum over time of wind speeds at target position + real(DbKi) :: vSum2(3) ! sum of wind speeds squared + real(ReKi) :: ActualSigma(3) ! computed standard deviation + + integer :: ic ! Loop counter for wind component + integer :: it ! Loop counter for t + integer :: iy ! Loop counter for y + integer :: iz ! Loop counter for z + + integer :: nc ! number of FF wind components + integer :: nt ! size of x (or t) dimension of turbulence box + integer :: ny ! size of y dimension of turbulence box + integer :: nz ! size of z dimension of turbulence box + + ErrStat = ErrID_None + ErrMsg = "" + + nz = size(Vel, 1) + ny = size(Vel, 2) + nc = size(Vel, 3) + nt = size(Vel, 4) + + ! If scaling method is none, set factors to 1 and return (no scaling) + if (InitInp%ScaleMethod == ScaleMethod_None) then + ScaleFactors = 1.0_ReKi + return + end if + + !---------------------------------------------------------------------------- + ! Determine the scaling factors: + !---------------------------------------------------------------------------- + + ! Use the scaling factors specified in the input file + if (InitInp%ScaleMethod == ScaleMethod_Direct) then + ScaleFactors = InitInp%sf + + else ! compute the scaling factors to get requested sigma: + + ! find the center point of the grid (if we don't have an odd number of grid points, we'll pick the point closest to the center) + iz = (nz + 1)/2 ! integer division + iy = (ny + 1)/2 ! integer division + + ! compute the actual sigma at the point specified by (iy,iz). (This sigma should be close to 1.) + vSum = sum(Vel(:, iy, iz, :), dim=2) + vSum2 = sum(Vel(:, iy, iz, :)**2, dim=2) + vMean = vSum/nt + ActualSigma = real(SQRT(ABS((vSum2/nt) - vMean**2)), ReKi) + + ! check that the ActualSigma isn't 0 + ! InitOut%sf = InitInp%SigmaF / ActualSigma ! factor = Target / actual + do ic = 1, nc + if (EqualRealNos(ActualSigma(ic), 0.0_ReKi)) then + ScaleFactors(ic) = 0.0_ReKi + if (.not. EqualRealNos(InitInp%SigmaF(ic), 0.0_ReKi)) then + call SetErrStat(ErrID_Fatal, "Computed standard deviation is zero; cannot scale to achieve target non-zero standard deviation.", & + ErrStat, ErrMsg, RoutineName) + end if + else + ScaleFactors(ic) = InitInp%SigmaF(ic)/ActualSigma(ic) + end if + end do + + end if + + !---------------------------------------------------------------------------- + ! scale the data using our scaling factors: + !---------------------------------------------------------------------------- + + do ic = 1, nc + Vel(ic, :, :, :) = real(ScaleFactors(ic)*Vel(ic, :, :, :), SiKi) + end do + +end subroutine ScaleTurbulence + +subroutine Grid3DField_ValidateInput(InitInp, NComp, ErrStat, ErrMsg) + + type(Grid3DInitInputType), intent(IN) :: InitInp !< Initialization input data passed to the module + integer(IntKi), intent(IN) :: NComp !< number of full-field wind components (normally 3) + + character(*), parameter :: RoutineName = 'Grid3DField_ValidateInput' + integer(intki) :: ic ! loop counter + integer(IntKi), intent(OUT) :: ErrStat !< determines if an error has been encountered + character(*), intent(OUT) :: ErrMsg !< Message about errors + + ErrStat = ErrID_None + ErrMsg = "" + + if (InitInp%RefHt < 0.0_ReKi .or. EqualRealNos(InitInp%RefHt, 0.0_ReKi)) call SetErrStat(ErrID_Fatal, 'The grid reference height must be larger than 0.', ErrStat, ErrMsg, RoutineName) + + if (InitInp%ScaleMethod == ScaleMethod_Direct) then + if (any(InitInp%sf < 0.0_ReKi)) call SetErrStat(ErrID_Fatal, 'Turbulence scaling factors must not be negative.', ErrStat, ErrMsg, RoutineName) + elseif (InitInp%ScaleMethod == ScaleMethod_StdDev) then + if (any(InitInp%sigmaf < 0.0_ReKi)) call SetErrStat(ErrID_Fatal, 'Turbulence standard deviations must not be negative.', ErrStat, ErrMsg, RoutineName) + elseif (InitInp%ScaleMethod /= ScaleMethod_None) then + call SetErrStat(ErrID_Fatal, 'Turbulence scaling method must be 0 (none), 1 (direct scaling factors), or 2 (target standard deviation).', ErrStat, ErrMsg, RoutineName) + end if + + if (InitInp%WindProfileType == WindProfileType_Log) then + if (InitInp%z0 < 0.0_ReKi .or. EqualRealNos(InitInp%z0, 0.0_ReKi)) & + call SetErrStat(ErrID_Fatal, 'The surface roughness length, Z0, must be greater than zero', ErrStat, ErrMsg, RoutineName) + elseif (InitInp%WindProfileType < WindProfileType_Constant .or. InitInp%WindProfileType > WindProfileType_PL) then + call SetErrStat(ErrID_Fatal, 'The WindProfile type must be 0 (constant), 1 (logarithmic) or 2 (power law).', ErrStat, ErrMsg, RoutineName) + end if + + if (InitInp%URef < 0.0_ReKi) call SetErrStat(ErrID_Fatal, 'The reference wind speed must not be negative.', ErrStat, ErrMsg, RoutineName) + + if (EqualRealNos(InitInp%RefLength, 0.0_ReKi) .or. InitInp%RefLength < 0.0_ReKi) then + if (InitInp%VLinShr /= 0.0_ReKi .or. InitInp%HLinShr /= 0.0_ReKi) then + call SetErrStat(ErrID_Fatal, 'The reference length must be a positive number when vertical or horizontal linear shear is used.', ErrStat, ErrMsg, RoutineName) + end if + end if -! subroutine Read_Bladed_Native(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) - -! ! Passed Variables: -! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters -! type(IfW_Interp_InitInputType), intent(inout) :: InitInp !< Initialization inputs -! type(IfW_Interp_InitOutputType), intent(out) :: InitOut !< Initialization outputs -! integer(IntKi), intent(in) :: WindFileUnit !< unit number for the wind file -! integer(IntKi), intent(in) :: SumFileUnit !< unit number for the summary file -! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) -! character(*), intent(out) :: ErrMsg !< message about the error encountered - -! ! Local Parameters: -! character(*), parameter :: RoutineName = "Read_Bladed_Native" - -! ! Local Variables: -! character(1024) :: WindFileName -! logical :: NativeFormat !< file is in native bladed format -! logical :: TowerFileExist !< tower file exists -! character(1024) :: BinFileName -! character(1024) :: PriPath -! character(1028) :: SumFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. -! character(1028) :: TwrFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. - -! integer(IntKi) :: ScaleMethod ! Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] -! real(ReKi) :: NatTI(3), TI ! Turbulence scaling factor for each direction [ScaleMethod=1] -! real(ReKi) :: SF(3) ! Turbulence scaling factor for each direction [ScaleMethod=1] -! real(ReKi) :: SigmaF(3) ! Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] - -! real(ReKi) :: FFXDelt, FFYDelt, FFZDelt -! real(ReKi) :: XOffset -! real(ReKi) :: UBar -! real(ReKi) :: ZCenter - -! logical :: CWise -! logical :: LHR ! Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) -! logical :: exists - -! integer(B2Ki) :: FileFormat -! integer(IntKi) :: TmpErrStat ! temporary error status -! character(ErrMsgLen) :: TmpErrMsg ! temporary error message - -! ! Wind file is specified directly in input file -! WindFileName = InitInp%WindFileNames(1) - -! ! No tower file is used -! TowerFileExist = .false. - -! ! Read the native bladed summary file -! call Read_Bladed_Native_Summary( & -! WindFileName, p%MeanFFWS, p%RefHt, InitOut%TI, InitOut%PropagationDir, & -! InitOut%VFlowAngle, BinFileName, p%PLExp, p%InitXPosition, ErrStat, ErrMsg) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) return - -! ! Binary file will be relative to the path where the primary input file is located. -! if (pathIsRelative(BinFileName)) then -! call GetPath(WindFileName, PriPath) -! BinFileName = TRIM(PriPath)//TRIM(BinFileName) -! end if - -! ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data -! if (InitInp%FixedWindFileRootName) then -! if (InitInp%TurbineID == 0) then -! ! .TRUE. for the FAST.Farm low-resolution domain -! BinFileName = TRIM(BinFileName)//TRIM(PathSep)//'Low' -! else -! ! FAST.Farm high-resolution domain(s) -! BinFileName = TRIM(BinFileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) -! end if -! end if - -! p%WindProfileType = WindProfileType_PL -! p%Periodic = .true. - -! InitInp%ScaleMethod = ScaleMethod_StdDev -! InitInp%SigmaF = InitOut%TI*p%MeanFFWS -! InitInp%SF = InitInp%SigmaF - -! InitInp%RefHt = p%RefHt -! InitInp%URef = p%MeanFFWS -! InitInp%WindProfileType = WindProfileType_PL - -! CWise = .false. -! ZCenter = p%RefHt -! TI = 100.0_ReKi -! UBar = 0.0_ReKi -! LHR = .true. - -! end subroutine - -! !> Read_Bladed reads the bladed full-field wind file. -! subroutine Read_Bladed_Binary(p, InitInp, InitOut, WindFileUnit, SumFileUnit, ErrStat, ErrMsg) - -! ! Passed Variables: -! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters -! type(IfW_Interp_InitInputType), intent(inout) :: InitInp !< Initialization inputs -! type(IfW_Interp_InitOutputType), intent(out) :: InitOut !< Initialization outputs -! integer(IntKi), intent(in) :: WindFileUnit !< unit number for the wind file -! integer(IntKi), intent(in) :: SumFileUnit !< unit number for the summary file -! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) -! character(*), intent(out) :: ErrMsg !< message about the error encountered - -! ! Local Parameters: -! character(*), parameter :: RoutineName = "Read_Bladed_Binary" -! logical, parameter :: NativeFormat = .false. - -! ! Local Variables: -! character(1024) :: WindFileName -! logical :: TowerFileExist !< tower file exists -! character(1024) :: BinFileName -! character(1024) :: PriPath -! character(1028) :: SumFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. -! character(1028) :: TwrFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. - -! integer(IntKi) :: ScaleMethod ! Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] - -! real(ReKi) :: TI(3) ! Turbulence scaling factor for each direction [ScaleMethod=1] -! real(ReKi) :: SF(3) ! Turbulence scaling factor for each direction [ScaleMethod=1] -! real(ReKi) :: SigmaF(3) ! Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] - -! real(ReKi) :: XOffset -! real(ReKi) :: UBar -! real(ReKi) :: ZCenter - -! logical :: CWise -! logical :: LHR ! Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) -! logical :: exists - -! integer(IntKi) :: TmpErrStat ! temporary error status -! character(ErrMsgLen) :: TmpErrMsg ! temporary error message - -! !---------------------------------------------------------------------------- -! ! Initialize variables -! !---------------------------------------------------------------------------- - -! ErrStat = ErrID_None -! ErrMsg = "" - -! InitOut%PropagationDir = 0.0_ReKi -! InitOut%VFlowAngle = 0.0_ReKi -! BinFileName = InitInp%WindFileNames(1) - -! ! Create summary and tower file paths from bin file path -! call GetRoot(BinFileName, SumFile) -! TwrFile = TRIM(SumFile)//'.twr' -! SumFile = TRIM(SumFile)//'.sum' - -! ! Read the summary file to get necessary scaling information -! call Read_Bladed_TurbSim_Summary(WindFileUnit, SumFile, CWise, ZCenter, TI, UBar, & -! p%RefHt, p%Periodic, LHR, TmpErrStat, TmpErrMsg) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) return - -! ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data -! if (InitInp%FixedWindFileRootName) then -! if (InitInp%TurbineID == 0) then -! ! .TRUE. for the FAST.Farm low-resolution domain -! WindFileName = TRIM(WindFileName)//TRIM(PathSep)//'Low' -! else -! ! FAST.Farm high-resolution domain(s) -! WindFileName = TRIM(WindFileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) -! end if -! end if - -! WindFileName = TRIM(WindFileName)//'.wnd' - -! InitOut%PropagationDir = 0.0_ReKi -! InitOut%VFlowAngle = 0.0_ReKi -! BinFileName = WindFileName - -! !---------------------------------------------------------------------------- -! ! Write the summary file -! !---------------------------------------------------------------------------- - -! if (SumFileUnit > 0) then -! write (SumFileUnit, '(A)') -! write (SumFileUnit, '(A)') 'Bladed-style wind type. Read by InflowWind sub-module '// & -! TRIM(IfW_Interp_Ver%Name)//' '//TRIM(IfW_Interp_Ver%Ver) -! write (SumFileUnit, '(A)') TRIM(TmpErrMsg) -! write (SumFileUnit, '(A)') ' FileName: '//TRIM(InitInp%WindFileNames(1)) -! write (SumFileUnit, '(A34,I3)') ' Binary file format id: ', p%WindFileFormat -! write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', p%RefHt -! write (SumFileUnit, '(A34,G12.4)') ' Timestep (s): ', p%FFDTime -! write (SumFileUnit, '(A34,I12)') ' Number of timesteps: ', p%NSteps -! write (SumFileUnit, '(A34,G12.4)') ' Mean windspeed (m/s): ', p%MeanFFWS -! write (SumFileUnit, '(A)') ' Characteristic TI: [ '// & -! TRIM(Num2LStr(TI(1)))//', '//TRIM(Num2LStr(TI(2)))//', '//TRIM(Num2LStr(TI(3)))//' ] ' -! write (SumFileUnit, '(A34,L1)') ' Windfile is periodic: ', p%Periodic -! write (SumFileUnit, '(A34,L1)') ' Windfile includes tower: ', p%NTGrids > 0 - -! if (p%Periodic) then -! write (SumFileUnit, '(A)') ' Time range (s): [ '// & -! TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(p%TotalTime))//' ]' -! else ! Shift the time range to compensate for the shifting of the wind grid -! write (SumFileUnit, '(A)') ' Time range (s): [ '// & -! TRIM(Num2LStr(-p%InitXPosition*p%InvMFFWS))//' : '// & -! TRIM(Num2LStr(p%TotalTime - p%InitXPosition*p%InvMFFWS))//' ]' -! end if - -! write (SumFileUnit, '(A)') ' Y range (m): [ '// & -! TRIM(Num2LStr(-p%FFYHWid))//' : '//TRIM(Num2LStr(p%FFYHWid))//' ]' - -! if (p%NTGrids > 0) then -! write (SumFileUnit, '(A)') ' Z range (m): [ '// & -! TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(p%RefHt + p%FFZHWid))//' ]' -! else -! write (SumFileUnit, '(A)') ' Z range (m): [ '// & -! TRIM(Num2LStr(p%RefHt - p%FFZHWid))//' : '//TRIM(Num2LStr(p%RefHt + p%FFZHWid))//' ]' -! end if - -! end if - -! end subroutine - -! subroutine Read_Bladed_Wind_File(p, WindFileUnit, BinFileName, NativeFormat, UBar, ZCenter, TI, ErrStat, ErrMsg) - -! ! Passed Variables: -! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters -! integer(IntKi), intent(in) :: WindFileUnit !< unit number for the wind file -! character(*), intent(in) :: BinFileName -! logical, intent(in) :: NativeFormat -! real(ReKi), intent(in) :: UBar -! real(ReKi), intent(in) :: ZCenter -! real(ReKi), intent(inout) :: TI(3) -! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) -! character(*), intent(out) :: ErrMsg !< message about the error encountered - -! ! Local Parameters: -! character(*), parameter :: RoutineName = "Read_Bladed_Wind_File" - -! ! Local Variables: -! integer(B2Ki) :: FileFormat -! real(ReKi) :: FFXDelt, FFYDelt, FFZDelt -! real(ReKi) :: BinTI(3) ! Turbulence scaling factor for each direction [ScaleMethod=1] -! integer(IntKi) :: TmpErrStat ! temporary error status -! character(ErrMsgLen) :: TmpErrMsg ! temporary error message - -! !---------------------------------------------------------------------------- -! ! Open the binary file and read contents -! !---------------------------------------------------------------------------- - -! ! Open the wind file -! call OpenBInpFile(WindFileUnit, TRIM(BinFileName), TmpErrStat, TmpErrMsg) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) return - -! ! Read the first binary integer from the file to get info on the type. -! ! Cannot use library read routines since this is a 2-byte integer. -! read (WindFileUnit, IOSTAT=TmpErrStat) FileFormat -! if (TmpErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading first binary integer from file "' & -! //TRIM(BinFileName)//'."', ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Save file format in parameters struct -! p%WindFileFormat = FileFormat - -! ! Read file headers -! select case (p%WindFileFormat) -! case (-1, -2, -3) -! call Read_Bladed_FF_Header0(p, WindFileUnit, NativeFormat, FFXDelt, FFYDelt, FFZDelt, TmpErrStat, TmpErrMsg) -! case (-99) -! call Read_Bladed_FF_Header1(p, WindFileUnit, NativeFormat, BinTI, FFXDelt, FFYDelt, FFZDelt, TmpErrStat, TmpErrMsg) -! where (BinTI > 0) TI = BinTI -! case default -! call SetErrStat(ErrID_Fatal, ' This is not a bladed-style binary wind file (binary format identifier: '// & -! TRIM(Num2LStr(p%WindFileFormat))//'. This might be a TurbSim binary wind file.', & -! ErrStat, ErrMsg, RoutineName) -! end select -! if (ErrStat >= AbortErrLev) return - -! ! If not native format and mean wind speed is different from summary file -! if ((.not. NativeFormat) .and. (ABS(UBar - p%MeanFFWS) > 0.1)) then -! call SetErrStat(ErrID_Fatal, ' Error: Incompatible mean hub-height wind speeds in FF wind files. '// & -! '(Check that the .sum and .wnd files were generated together.)', ErrStat, ErrMsg, RoutineName) -! close (WindFileUnit) -! return -! end if - -! ! Calculate the height of the bottom of the grid (meters), error if less than zero -! p%GridBase = ZCenter - p%FFZHWid -! if (p%GridBase < 0.0_ReKi) then -! call SetErrStat(ErrID_Severe, 'WARNING: The bottom of the grid is located at a height of '// & -! TRIM(Num2LStr(p%GridBase))//' meters, which is below the ground.'// & -! ' Winds below the ground will be set to 0.', ErrStat, ErrMsg, RoutineName) -! end if - -! ! Read binary grid data -! call Read_Bladed_Grids(p, WindFileUnit, LHR, TI, CWise, NativeFormat, p, TmpErrStat, TmpErrMsg) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! close (WindFileUnit) -! if (ErrStat >= AbortErrLev) return - -! !---------------------------------------------------------------------------- -! ! Read tower data if requested -! !---------------------------------------------------------------------------- - -! ! If a tower file was specified -! if (TowerFileExist) then - -! inquire (FILE=TRIM(TwrFile), EXIST=Exists) - -! ! Double check that the tower file exists and read it. If it was requested but doesn't exist, -! ! throw fatal error and exit. -! if (Exists) then -! call Read_Bladed_Tower() -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) then -! close (WindFileUnit) -! return -! end if -! else -! call SetErrStat(ErrID_Fatal, ' Tower file '//TRIM(TwrFile)//' specified for Bladed full-field '// & -! 'wind files does not exist.', ErrStat, ErrMsg, RoutineName) -! close (WindFileUnit) -! return -! end if -! else -! p%NTGrids = 0 -! end if - -! ! Report native turbulence intensities in percent -! if (NativeFormat) TI = TI*100.0_ReKi - -! end subroutine - -! !> Read_Bladed_TurbSim_Summary reads the summary file generated by TurbSim -! !! to get the normalizing parameters needed to read the bladed binary file -! !! which was genered by TurbSim. -! subroutine Read_Bladed_TurbSim_Summary(WindFileUnit, FileName, CWise, ZCenter, TI, UBar, RefHt, Periodic, LHR, ErrStat, ErrMsg) - -! integer(IntKi), intent(IN) :: WindFileUnit !< unit number for the file to open -! character(*), intent(IN) :: FileName !< name of the summary file -! logical, intent(OUT) :: CWise !< rotation (for reading the order of the binary data) -! real(ReKi), intent(OUT) :: ZCenter !< the height at the center of the grid -! real(ReKi), intent(OUT) :: TI(3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI -! real(ReKi), intent(OUT) :: UBar !< mean (advection) wind speed -! real(ReKi), intent(OUT) :: RefHt !< Reference height -! logical, intent(OUT) :: Periodic !< rotation (for reading the order of the binary data) -! logical, intent(OUT) :: LHR !< Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) -! integer(IntKi), intent(OUT) :: ErrStat !< returns 0 if no error encountered in the subroutine -! character(*), intent(OUT) :: ErrMsg !< holds the error messages - -! character(*), parameter :: RoutineName = "Read_Bladed_TurbSim_Summary" - -! real(ReKi) :: ZGOffset ! The vertical offset of the turbine on rectangular grid (allows turbulence not centered on turbine hub) -! integer(IntKi) :: I, J ! Counters -! character(1024) :: Line ! temporary storage for reading a line from the file -! integer(IntKi) :: ContentSize ! summary file size -! character(:), allocatable :: FileContents ! summary file contents -! integer(IntKi) :: TmpErrStat ! temporary error status -! character(ErrMsgLen) :: TmpErrMsg ! temporary error message - -! !------------------------------------------------------------------------- -! ! Initialize variables -! !------------------------------------------------------------------------- - -! ErrStat = ErrID_None -! ErrMsg = '' - -! !------------------------------------------------------------------------- -! ! Read summary file contents -! !------------------------------------------------------------------------- - -! call OpenBInpFile(WindFileUnit, FileName, TmpErrStat, TmpErrMsg) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) return - -! inquire (WindFileUnit, size=ContentSize) -! allocate (character(ContentSize) :: FileContents) -! read (WindFileUnit, IOSTAT=TmpErrStat) FileContents -! close (WindFileUnit) - -! if (TmpErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading TurbSim summary file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Convert file contents to uppercase -! call Conv2UC(FileContents) - -! ! Find 'CLOCKWISE' in file -! i = index(FileContents, 'CLOCKWISE') -! if (i > 0) then - -! ! Find beginning of line where clockwise appears -! j = index(FileContents(:i), NewLine, back=.true.) + 1 - -! ! Get line with leading spaces removed -! line = adjustl(FileContents(j:i)) - -! ! Get value from beginning of line -! select case (line(1:1)) -! case ("T", "Y") -! CWise = .true. -! case ("F", "N") -! CWise = .false. -! end select -! else -! CWise = .false. -! end if - -! ! Find 'HUB HEIGHT' or 'ZHUB' in file -! i = index(FileContents, 'HUB HEIGHT') -! if (i == 0) i = index(FileContents, 'ZHUB') -! if (i == 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading hub height from FF summary file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Find beginning of line where 'HUB HEIGHT' or 'ZHUB' occur -! j = index(FileContents(:i), NewLine, back=.true.) + 1 - -! ! Read value from line -! read (FileContents(j:), *, IOSTAT=TmpErrStat) RefHt -! if (TmpErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading hub height from FF summary file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Find the mean speed -! i = index(FileContents, 'UBAR') -! if (i == 0) then -! call SetErrStat(ErrID_Fatal, ' Error find UBar in FF summary file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Get index of next equal sign -! i = index(FileContents(i:), '=') + i + 1 -! read (FileContents(i:), *, IOSTAT=TmpErrStat) UBar -! if (TmpErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading UBar from FF summary file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Read turbulence intensities on lines after mean speed -! do j = 1, 3 -! i = INDEX(FileContents(i:), '=') + i + 1 -! read (FileContents(i:), *, IOSTAT=TmpErrStat) TI(j) -! if (TmpErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading TI('//TRIM(Num2LStr(j))// & -! ') from FF summary file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if -! end do - -! ! Find the grid "HEIGHT OFFSET" (optional, default to zero) -! i = index(FileContents, "HEIGHT OFFSET") -! if (i > 0) then -! i = INDEX(FileContents(i:), '=') + i + 1 -! read (FileContents(i:), *, IOSTAT=TmpErrStat) ZGOffset -! if (TmpErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading height offset from FF summary file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if -! else -! ZGOffset = 0.0_ReKi -! end if - -! ! Calculate the height of the grid center -! ZCenter = RefHt - ZGOffset - -! ! If "PERIODIC" is in summary, then file is periodic -! Periodic = index(FileContents(i:), 'PERIODIC') > 0 - -! ! If "BLADED LEFT-HAND RULE" is in file, then file uses LHR -! LHR = index(FileContents(i:), 'BLADED LEFT-HAND RULE') > 0 - -! end subroutine Read_Bladed_TurbSim_Summary - -! !> This subroutine reads the text summary file to get normalizing parameters, the location of the -! !! grid, and the direction the grid was written to the binary file -! subroutine Read_Bladed_Native_Summary(SumFileName, UBar, RefHt, TI, PropagationDir, & -! VFlowAngle, BinFileName, PLExp, XOffset, ErrStat, ErrMsg) - -! character(*), intent(in) :: SumFileName !< Summary file name -! real(ReKi), intent(out) :: UBar -! real(ReKi), intent(out) :: RefHt -! real(ReKi), intent(out) :: TI(3) ! turbulenc -! real(ReKi), intent(out) :: PropagationDir -! real(ReKi), intent(out) :: VFlowAngle -! character(1024), intent(out) :: BinFileName -! real(ReKi), intent(out) :: PLExp -! real(ReKi), intent(out) :: XOffset -! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) -! character(*), intent(out) :: ErrMsg !< message about the error encountered - -! character(*), parameter :: RoutineName = "Read_Bladed_Native_Summary" -! integer(IntKi), parameter :: UnEc = -1 ! echo file unit number (set to something else > 0 for debugging) - -! type(FileInfoType) :: FileInfo ! The derived type for holding the file information. -! integer(IntKi) :: CurLine ! Current line to parse in FileInfo data structure -! integer(IntKi) :: TmpErrStat ! temporary error status -! character(ErrMsgLen) :: TmpErrMsg ! temporary error message - -! ! Initialize error variables -! ErrStat = ErrID_None -! ErrMsg = '' - -! !------------------------------------------------------------------------- -! ! Open and read the summary file; store data in FileInfo structure. -! !------------------------------------------------------------------------- - -! call ProcessComFile(SumFileName, FileInfo, TmpErrStat, TmpErrMsg) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) return - -! !------------------------------------------------------------------------- -! ! Process the lines stored in FileInfo -! !------------------------------------------------------------------------- - -! CurLine = 1 - -! call ParseVar(FileInfo, CurLine, 'UBAR', UBar, TmpErrStat, TmpErrMsg, UnEc) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - -! call ParseVar(FileInfo, CurLine, 'REFHT', RefHt, TmpErrStat, TmpErrMsg, UnEc) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - -! call ParseVar(FileInfo, CurLine, 'TI', TI(1), TmpErrStat, TmpErrMsg, UnEc) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - -! call ParseVar(FileInfo, CurLine, 'TI_V', TI(2), TmpErrStat, TmpErrMsg, UnEc) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - -! call ParseVar(FileInfo, CurLine, 'TI_W', TI(3), TmpErrStat, TmpErrMsg, UnEc) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - -! call ParseVar(FileInfo, CurLine, 'WDIR', PropagationDir, TmpErrStat, TmpErrMsg, UnEc) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! PropagationDir = R2D*PropagationDir - -! call ParseVar(FileInfo, CurLine, 'FLINC', VFlowAngle, TmpErrStat, TmpErrMsg, UnEc) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! VFlowAngle = R2D*VFlowAngle ! convert to degrees - -! call ParseVar(FileInfo, CurLine, 'WINDF', BinFileName, TmpErrStat, TmpErrMsg, UnEc) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - -! call ParseVar(FileInfo, CurLine, 'WSHEAR', PLExp, TmpErrStat, TmpErrMsg, UnEc) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - -! if (ErrStat >= AbortErrLev) return - -! call ParseVar(FileInfo, CurLine, 'XOffset', XOffset, TmpErrStat, TmpErrMsg, UnEc) -! if (TmpErrStat /= ErrID_None) then -! XOffset = 0.0_ReKi ! this will be the default if offset is not in the file -! end if - -! end subroutine Read_Bladed_Native_Summary - -! subroutine Read_Bladed_FF_Header0(p, WindFileUnit, NativeFormat, FFXDelt, FFYDelt, FFZDelt, ErrStat, ErrMsg) - -! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters -! integer(IntKi), intent(IN) :: WindFileUnit !< unit number for the file to open -! logical, intent(in) :: NativeFormat -! real(ReKi), intent(out) :: FFXDelt -! real(ReKi), intent(out) :: FFYDelt -! real(ReKi), intent(out) :: FFZDelt -! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) -! character(*), intent(out) :: ErrMsg !< message about the error encountered - -! character(*), parameter :: RoutineName = "Read_Bladed_FF_Header0" - -! integer(IntKi) :: TmpErrStat ! temporary error status -! character(ErrMsgLen) :: TmpErrMsg ! temporary error message - -! type :: HeaderType -! integer(B2Ki) :: DeltaZ, DeltaY, DeltaX -! integer(B2Ki) :: NumTimeStepsHalf, MFFWS10 -! integer(B2Ki) :: zLu, yLu, xLu, dummy, rnd -! integer(B2Ki) :: nz1000, ny1000 -! end type - -! type(HeaderType) :: header -! integer(B2Ki) :: dummy(6) - -! ! Read header -! read (WindFileUnit, IOSTAT=ErrStat) header -! if (ErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading header 0 from binary FF file.', ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Number of full-field velocity components -! p%NFFComp = -1*p%WindFileFormat - -! ! Grid Deltas -! FFZDelt = 0.001_ReKi*real(header%DeltaZ, ReKi) -! p%InvFFZD = 1.0_ReKi/FFZDelt -! FFYDelt = 0.001_ReKi*real(header%DeltaY, ReKi) -! p%InvFFYD = 1.0_ReKi/FFYDelt -! FFXDelt = 0.001_ReKi*real(header%DeltaX, ReKi) - -! ! Number of time steps -! p%NSteps = 2*header%NumTimeStepsHalf - -! ! Mean full field wind speed -! if (.not. NativeFormat) p%MeanFFWS = 0.1*header%MFFWS10 -! p%InvMFFWS = 1.0/p%MeanFFWS -! p%FFDTime = FFXDelt/p%MeanFFWS -! p%FFRate = 1.0/p%FFDTime - -! ! Z and Y Grid size -! p%NZGrids = header%nz1000/1000 -! p%FFZHWid = 0.5*FFZDelt*(p%NZGrids - 1) -! p%NYGrids = header%ny1000/1000 -! p%FFYHWid = 0.5*FFYDelt*(p%NYGrids - 1) - -! ! Read dummy variables (zLv, yLv, xLv, zLw, yLw, xLw) -! if (p%NFFComp == 3) then -! read (WindFileUnit, IOSTAT=TmpErrStat) dummy -! if (TmpErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading header 0 from binary FF file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if -! end if - -! end subroutine Read_Bladed_FF_Header0 - -! subroutine Read_Bladed_FF_Header1(p, WindFileUnit, NativeFormat, TI, FFXDelt, FFYDelt, FFZDelt, ErrStat, ErrMsg) - -! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters -! integer(IntKi), intent(IN) :: WindFileUnit !< unit number for the file to open -! logical, intent(in) :: NativeFormat -! real(ReKi), intent(out) :: TI(3) !< turbulence intensities -! real(ReKi), intent(out) :: FFXDelt -! real(ReKi), intent(out) :: FFYDelt -! real(ReKi), intent(out) :: FFZDelt -! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) -! character(*), intent(out) :: ErrMsg !< message about the error encountered - -! character(*), parameter :: RoutineName = "Read_Bladed_FF_Header1" - -! integer(B2Ki) :: TurbType -! integer(IntKi) :: i - -! type :: Turb4Type -! integer(B4Ki) :: NComp -! real(SiKi) :: Latitude, RoughLen, RefHeight, TurbInt(3) -! end type - -! type :: Turb78Type -! integer(B4Ki) :: HeaderSize, NComp -! end type - -! type :: Turb7Type -! real(SiKi) :: CoherenceDecay, CoherenceScale -! end type - -! type :: Turb8Type -! real(SiKi) :: dummy1(6) -! integer(B4Ki) :: dummy2(3) -! real(SiKi) :: dummy3(2) -! integer(B4Ki) :: dummy4(3) -! real(SiKi) :: dummy5(2) -! end type - -! type :: Sub1Type -! real(SiKi) :: DeltaZ, DeltaY, DeltaX -! integer(B4Ki) :: NumTimeStepsHalf -! real(SiKi) :: MFFWS, zLu, yLu, xLu -! integer(B4Ki) :: dummy, rnd, nz, ny -! end type - -! type :: Sub2Type -! real(SiKi) :: zLv, yLv, xLv, zLw, yLw, xLw -! end type - -! type(Turb4Type) :: Turb4 -! type(Turb78Type) :: Turb78 -! type(Sub1Type) :: Sub1 -! type(Sub2Type) :: Sub2 -! type(Turb7Type) :: Turb7 -! type(Turb8Type) :: Turb8 - -! ! Read turbulence type (int16) -! read (WindFileUnit, IOSTAT=ErrStat) TurbType -! if (ErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading header 0 from binary FF file.', ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Switch based on turbulence type -! select case (TurbType) - -! case (1, 2) ! 1-component Von Karman (1) or Kaimal (2) -! p%NFFComp = 1 - -! case (3, 5) ! 3-component Von Karman (3) or IEC-2 Kaimal (5) -! p%NFFComp = 3 - -! case (4) ! Improved Von Karman -! read (WindFileUnit, IOSTAT=ErrStat) Turb4 -! if (ErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading header for TurbType=4 from binary FF file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Number of components (should be 3) -! p%NFFComp = Turb4%NComp - -! ! Turbulence intensity -! where (Turb4%TurbInt > 0) TI = Turb4%TurbInt - -! case (7, 8) ! General Kaimal (7) or Mann model (8) -! read (WindFileUnit, IOSTAT=ErrStat) Turb78 -! if (ErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading header for TurbType=7,8 from binary FF file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Number of components -! p%NFFComp = Turb78%NComp - -! case default ! Unknown turbulence type -! call SetErrStat(ErrID_Warn, ' InflowWind does not recognize the full-field turbulence file type ='// & -! TRIM(Num2LStr(int(TurbType, IntKi)))//'.', ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) return -! end select - -! ! Read header sub 1 -! read (WindFileUnit, IOSTAT=ErrStat) Sub1 -! if (ErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading header for Sub1 from binary FF file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! FFZDelt = Sub1%DeltaZ -! p%InvFFZD = 1/FFZDelt -! FFYDelt = Sub1%DeltaY -! p%InvFFYD = 1/FFYDelt -! FFXDelt = Sub1%DeltaX - -! if (.not. NativeFormat) p%MeanFFWS = Sub1%MFFWS -! p%InvMFFWS = 1.0/p%MeanFFWS -! p%FFDTime = FFXDelt/p%MeanFFWS -! p%FFRate = 1.0/p%FFDTime - -! p%NZGrids = Sub1%nz -! p%FFZHWid = 0.5*FFZDelt*(p%NZGrids - 1) -! p%NYGrids = Sub1%ny -! p%FFYHWid = 0.5*FFYDelt*(p%NYGrids - 1) - -! if (p%NFFComp == 3) then -! read (WindFileUnit, IOSTAT=ErrStat) Sub2 -! if (ErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading header for Sub2 from binary FF file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if -! end if - -! ! Read additional parameters based on turbulence type -! select case (TurbType) -! case (7) -! read (WindFileUnit, IOSTAT=ErrStat) Turb7 -! if (ErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading header for Turb7 from binary FF file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if -! case (8) -! read (WindFileUnit, IOSTAT=ErrStat) Turb8 -! if (ErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading header for Turb8 from binary FF file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if -! end select - -! end subroutine - -! subroutine Read_Bladed_Grids(p, WindFileUnit, LHR, TI, NativeFormat, CWise, FFXDelt, FFYDelt, FFZDelt, ErrStat, ErrMsg) - -! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters -! integer(IntKi), intent(IN) :: WindFileUnit !< unit number for the file to open -! logical, intent(in) :: LHR -! real(ReKi), intent(out) :: TI(3) !< turbulence intensities -! logical, intent(in) :: NativeFormat -! logical, intent(in) :: Cwise -! real(ReKi), intent(out) :: FFXDelt -! real(ReKi), intent(out) :: FFYDelt -! real(ReKi), intent(out) :: FFZDelt -! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) -! character(*), intent(out) :: ErrMsg !< message about the error encountered - -! character(*), parameter :: RoutineName = "Read_Bladed_Grids" - -! real(ReKi) :: FF_Scale(3) !< used for "un-normalizing" the data -! real(ReKi) :: FF_Offset(3) !< used for "un-normalizing" the data -! integer(B2Ki), allocatable :: raw_ff(:, :, :) -! integer(IntKi) :: CFirst, CLast, CStep -! integer(IntKi) :: IC, IT -! integer(IntKi) :: TmpErrStat ! temporary error status -! character(ErrMsgLen) :: TmpErrMsg ! temporary error message - -! ! Initialize error variables -! ErrMsg = "" -! ErrStat = ErrID_None - -! ! Calculate wind scale and offset -! if (NativeFormat) then -! FF_Scale = 0.001_ReKi -! FF_Offset = 0.0_ReKi -! else -! FF_Scale = 0.001_ReKi*p%MeanFFWS*TI/100.0_ReKi -! FF_Offset = (/p%MeanFFWS, 0.0_ReKi, 0.0_ReKi/) -! end if - -! ! Bladed convention has positive V pointed along negative Y -! if (LHR) FF_Scale(2) = -FF_Scale(2) ! left-hand rule - -! ! Print message to inform user that wind file is being read (may take a while). -! call WrScr(NewLine//' Reading a '//TRIM(Num2LStr(p%NYGrids))// & -! 'x'//TRIM(Num2LStr(p%NZGrids))// & -! ' grid ('//TRIM(Num2LStr(p%FFYHWid*2))// & -! ' m wide, '//TRIM(Num2LStr(p%GridBase))// & -! ' m to '//TRIM(Num2LStr(p%GridBase + p%FFZHWid*2))// & -! ' m above ground) with a characteristic wind speed of '// & -! TRIM(Num2LStr(p%MeanFFWS))//' m/s. ') - -! !------------------------------------------------------------------------- -! ! Allocate space for the FF array -! !------------------------------------------------------------------------- - -! ! Add another step, just in case there is an odd number of steps. -! p%NSteps = p%NSteps + 1 - -! ! Allocate wind data -! call Allocate_FF_Wind_Data(p%FFData, p%NSteps, p%NFFComp, & -! p%NYGrids, p%NZGrids, TmpErrStat, TmpErrMsg) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) return - -! !------------------------------------------------------------------------- -! ! Initialize the data and set column indexing to account for -! ! direction of turbine rotation (CWise) -! !------------------------------------------------------------------------- - -! ! Initialize entire array -! p%FFData(:, :, :, :) = 0.0_SiKi ! we may have only one component - -! if (CWise) then -! CFirst = p%NYGrids -! CLast = 1 -! CStep = -1 -! else -! CFirst = 1 -! CLast = p%NYGrids -! CStep = 1 -! end if - -! !---------------------------------------------------------------------------- -! ! Loop through all the time steps, reading the data and converting to m/s -! !---------------------------------------------------------------------------- - -! ! Allocate raw full-field array to hold grid data for single time step -! allocate (raw_ff(p%NFFComp, p%NYGrids, p%NZGrids)) - -! ! Loop through time steps -! do IT = 1, p%NSteps - -! ! Read raw data (NFFComp,NYGrids,NZGrids) -! read (WindFileUnit, IOStat=TmpErrStat) raw_ff - -! ! If there was an error -! if (TmpErrStat /= 0) then - -! ! If there really were an even number of steps -! if (IT == p%NSteps) then -! p%NSteps = p%NSteps - 1 -! ErrStat = 0 -! exit -! end if - -! ! Error reading file -! call SetErrStat(ErrID_Fatal, ' Error reading binary data file. '// & -! ', it = '//TRIM(Num2LStr(it))// & -! ', nsteps = '//TRIM(Num2LStr(p%NSteps)), ErrStat, ErrMsg, RoutineName) -! return -! end if - -! ! Scale wind components and store in array -! do IC = 1, p%NFFComp -! p%FFData(IC, :, :, IT) = real(FF_Offset(IC) + FF_Scale(IC)*raw_ff(IC, CFirst:CLast:CStep, :), SiKi) -! end do - -! end do - -! if (p%Periodic) then -! call WrScr(NewLine//' Processed '//TRIM(Num2LStr(p%NSteps))//' time steps of '// & -! TRIM(Num2LStr(p%FFRate))//'-Hz full-field data (period of '// & -! TRIM(Num2LStr(p%FFDTime*p%NSteps))//' seconds).') - -! else -! call WrScr(NewLine//' Processed '//TRIM(Num2LStr(p%NSteps))//' time steps of '// & -! TRIM(Num2LStr(p%FFRate))//'-Hz full-field data ('// & -! TRIM(Num2LStr(p%FFDTime*(p%NSteps - 1)))//' seconds).') -! end if - -! end subroutine Read_Bladed_Grids - -! !> This subroutine reads the binary tower file that corresponds with the -! !! Bladed-style FF binary file. The FF grid must be read before this subroutine -! !! is called! (many checks are made to ensure the files belong together) -! subroutine Read_Bladed_Tower(p, ErrStat, ErrMsg) - -! type(IfW_Interp_ParameterType), intent(inout) :: p !< Parameters -! integer(IntKi), intent(out) :: ErrStat !< error status return value (0=no error; non-zero is error) -! character(*), intent(out) :: ErrMsg !< message about the error encountered - -! type :: HeaderType -! real(SiKi) :: dz, dx, Zmax -! integer(B4Ki) :: NumOutSteps, NumZ -! real(SiKi) :: UHub, TI(3) -! end type - -! real(ReKi), parameter :: TOL = 1E-4 ! tolerence for wind file comparisons -! real(ReKi), parameter :: FF_Offset(3) = (/1.0, 0.0, 0.0/) ! used for "un-normalizing" the data - -! integer(IntKi) :: IC, IT ! loop counters -! integer(B2Ki), allocatable :: raw_twr(:, :) ! holds tower velocity for one timestep - -! type(HeaderType) :: header - -! !------------------------------------------------------------------------- -! ! Initialization -! !------------------------------------------------------------------------- - -! ErrMsg = '' -! ErrStat = ErrID_None - -! p%NTGrids = 0 - -! if (p%NFFComp /= 3) then -! call SetErrStat(ErrID_Fatal, ' Error: Tower binary files require 3 wind components.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! !------------------------------------------------------------------------- -! ! Open the file -! !------------------------------------------------------------------------- - -! call OpenBInpFile(WindFileUnit, TwrFile, TmpErrStat, TmpErrMsg) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) return - -! !------------------------------------------------------------------------- -! ! Read the header information and check that it's compatible with the FF Bladed-style binary -! ! parameters already read. -! !------------------------------------------------------------------------- - -! read (WindFileUnit, IOSTAT=TmpErrStat) header -! if (TmpErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, & -! ' Error reading header of the binary tower file "' & -! //TRIM(TwrFile)//'."', ErrStat, ErrMsg, RoutineName) -! return -! end if - -! if (ABS(header%dz*p%InvFFZD - 1) > TOL) then -! call SetErrStat(ErrID_Fatal, & -! ' Resolution in the FF binary file does not match the tower file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! if (ABS(header%dx*p%InvMFFWS/p%FFDTime - 1) > TOL) then -! call SetErrStat(ErrID_Fatal, & -! ' Time resolution in the FF binary file does not match the tower file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! if (ABS(header%Zmax/p%GridBase - 1) > TOL) then -! call SetErrStat(ErrID_Fatal, & -! ' Height in the FF binary file does not match the tower file "' & -! //TRIM(TwrFile)//'."', ErrStat, ErrMsg, RoutineName) -! return -! end if - -! if (header%NumOutSteps /= p%NSteps) then -! call SetErrStat(ErrID_Fatal, & -! ' Number of time steps in the FF binary file does not match the tower file.', & -! ErrStat, ErrMsg, RoutineName) -! return -! end if - -! p%NTGrids = header%NumZ - -! if (ABS(header%UHub*p%InvMFFWS - 1) > TOL) then -! call SetErrStat(ErrID_Fatal, & -! ' Mean wind speed in the FF binary file does not match the tower file.', & -! ErrStat, ErrMsg, RoutineName) -! p%NTGrids = 0 -! return -! end if - -! ! If number of tower grids is zero, close file and return -! if (p%NTGrids == 0) then -! close (WindFileUnit) -! return -! end if - -! !------------------------------------------------------------------------- -! ! Allocate arrays for the tower points -! !------------------------------------------------------------------------- - -! call Allocate_FF_Tower_Data(p%Tower, p%NSteps, p%NFFComp, & -! p%NTGrids, TmpErrStat, TmpErrMsg) -! call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) -! if (ErrStat >= AbortErrLev) return - -! !------------------------------------------------------------------------- -! ! Read the 16-bit time-series data and scale it to 32-bit reals -! !------------------------------------------------------------------------- - -! ! Loop through time. -! do IT = 1, p%NSteps - -! ! Read normalized wind-component, INT(2) for this timestep -! read (WindFileUnit, IOSTAT=TmpErrStat) raw_twr -! if (TmpErrStat /= 0) then -! call SetErrStat(ErrID_Fatal, ' Error reading binary tower data file. it = '//TRIM(Num2LStr(it))// & -! ', nsteps = '//TRIM(Num2LStr(p%NSteps)), ErrStat, ErrMsg, RoutineName) -! p%NTGrids = 0 -! return -! end if - -! ! Convert wind components to m/s -! do IC = 1, p%NFFComp -! p%Tower(IC, :, IT) = real(p%MeanFFWS*(FF_Offset(IC) + 0.00001*TI(IC)*raw_twr(IC, :)), SiKi) -! end do -! end do - -! !------------------------------------------------------------------------- -! ! Close the file -! !------------------------------------------------------------------------- - -! close (WindFileUnit) - -! TmpErrMsg = ' Processed '//TRIM(Num2LStr(p%NSteps))//' time steps of '// & -! TRIM(Num2LStr(p%NTGrids))//'x1 tower data grids.' - -! call WrScr(NewLine//TRIM(TmpErrMsg)) - -! end subroutine Read_Bladed_Tower +end subroutine Grid3DField_ValidateInput end module FlowField_IO diff --git a/modules/inflowwind/src/FlowField_IO.txt b/modules/inflowwind/src/FlowField_IO.txt index ea4ed00715..d5223aff59 100644 --- a/modules/inflowwind/src/FlowField_IO.txt +++ b/modules/inflowwind/src/FlowField_IO.txt @@ -7,7 +7,7 @@ #---------------------------------------------------------------------------------------------------------------------------------- include Registry_NWTC_Library.txt -usefrom FlowField.txt +usefrom IfW_FlowField.txt typedef FlowField_IO SteadyInitInputType ReKi HWindSpeed - - - "Horizontal wind speed" m/s typedef ^ ^ ReKi RefHt - - - "Reference height for horizontal wind speed" meters @@ -20,12 +20,26 @@ typedef ^ ^ ReKi Propagatio typedef ^ ^ logical UseInputFile - .true. - "Flag for toggling file based IO in wind type 2." - typedef ^ ^ FileInfoType PassedFileData - - - "Optional slot for wind type 2 data if file IO is not used." - +typedef ^ Grid3DInitInputType IntKi ScaleMethod - 0 - "Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation]" - +typedef ^ ^ ReKi SF 3 0 - "Turbulence scaling factor for each direction [ScaleMethod=1]" - +typedef ^ ^ ReKi SigmaF 3 0 - "Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2]" - +typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - +typedef ^ ^ ReKi RefHt - 0 - "Reference (hub) height of the grid" meters +typedef ^ ^ ReKi URef - 0 - "Mean u-component wind speed at the reference height" meters +typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - +typedef ^ ^ ReKi VLinShr - 0 - "Vertical linear wind shear coefficient (used for vertical linear wind profile type only)" - +typedef ^ ^ ReKi HLinShr - 0 - "Horizontal linear wind shear coefficient (used for horizontal wind profile type only)" - +typedef ^ ^ ReKi RefLength - 1 - "Reference (rotor) length of the grid (used for horizontal wind profile type only)" - +typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - +typedef ^ ^ ReKi XOffset - 0 - "distance offset for FF wind files" m + typedef ^ TurbSimInitInputType character(1024) WindFileName - - - "Name of the wind file to use" - typedef ^ BladedInitInputType character(1024) WindFileName - - - "Root filename" - typedef ^ ^ logical NativeBladedFmt - - - "Whether this is native Bladed (needs wind profile and TI scaling) or not" - typedef ^ ^ logical TowerFileExist - - - "Tower file exists" - typedef ^ ^ IntKi TurbineID - 0 - "Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm)" - +typedef ^ ^ logical FixedWindFileRootName - .false. - "Do the wind data files have a fixed (DEFAULT) file name? (used by FAST.Farm)" - typedef ^ BladedInitOutputType ReKi TI {3} - - "Turbulence intensity given in the file" - typedef ^ ^ ReKi PropagationDir - - - "Propogation direction from native Bladed format" degrees @@ -38,15 +52,7 @@ typedef ^ ^ IntKi nz typedef ^ ^ ReKi dx - 0 - "size of grids in the x direction (in the 3 files above)" - typedef ^ ^ ReKi dy - 0 - "size of grids in the y direction (in the 3 files above)" - typedef ^ ^ ReKi dz - 0 - "size of grids in the z direction (in the 3 files above)" - -typedef ^ ^ ReKi RefHt - 0 - "Reference (hub) height of the grid" meters -typedef ^ ^ IntKi ScaleMethod - 0 - "Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation]" - -typedef ^ ^ ReKi SF 3 0 - "Turbulence scaling factor for each direction [ScaleMethod=1]" - -typedef ^ ^ ReKi SigmaF 3 0 - "Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2]" - -typedef ^ ^ ReKi URef - 0 - "Mean u-component wind speed at the reference height" meters -typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - -typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - -typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - -typedef ^ ^ ReKi XOffset - 0 - "distance offset for FF wind files" meters +typedef ^ ^ Grid3DInitInputType G3D - - - "Grid3D initialization input" - typedef ^ UserInitInputType SiKi Dummy - - - "User field initialization input dummy value" - diff --git a/modules/inflowwind/src/FlowField_IO_Types.f90 b/modules/inflowwind/src/FlowField_IO_Types.f90 index f56f9d7a1d..ada6b8bc91 100644 --- a/modules/inflowwind/src/FlowField_IO_Types.f90 +++ b/modules/inflowwind/src/FlowField_IO_Types.f90 @@ -31,7 +31,7 @@ !! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. MODULE FlowField_IO_Types !--------------------------------------------------------------------------------------------------------------------------------- -USE FlowField_Types +USE IfW_FlowField_Types USE NWTC_Library IMPLICIT NONE ! ========= SteadyInitInputType ======= @@ -51,6 +51,22 @@ MODULE FlowField_IO_Types TYPE(FileInfoType) :: PassedFileData !< Optional slot for wind type 2 data if file IO is not used. [-] END TYPE UniformInitInputType ! ======================= +! ========= Grid3DInitInputType ======= + TYPE, PUBLIC :: Grid3DInitInputType + INTEGER(IntKi) :: ScaleMethod = 0 !< Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] [-] + REAL(ReKi) , DIMENSION(1:3) :: SF !< Turbulence scaling factor for each direction [ScaleMethod=1] [-] + REAL(ReKi) , DIMENSION(1:3) :: SigmaF !< Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] [-] + INTEGER(IntKi) :: WindProfileType = -1 !< Wind profile type (0=constant;1=logarithmic;2=power law) [-] + REAL(ReKi) :: RefHt = 0 !< Reference (hub) height of the grid [meters] + REAL(ReKi) :: URef = 0 !< Mean u-component wind speed at the reference height [meters] + REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] + REAL(ReKi) :: VLinShr = 0 !< Vertical linear wind shear coefficient (used for vertical linear wind profile type only) [-] + REAL(ReKi) :: HLinShr = 0 !< Horizontal linear wind shear coefficient (used for horizontal wind profile type only) [-] + REAL(ReKi) :: RefLength = 1 !< Reference (rotor) length of the grid (used for horizontal wind profile type only) [-] + REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] + REAL(ReKi) :: XOffset = 0 !< distance offset for FF wind files [m] + END TYPE Grid3DInitInputType +! ======================= ! ========= TurbSimInitInputType ======= TYPE, PUBLIC :: TurbSimInitInputType character(1024) :: WindFileName !< Name of the wind file to use [-] @@ -62,6 +78,7 @@ MODULE FlowField_IO_Types LOGICAL :: NativeBladedFmt !< Whether this is native Bladed (needs wind profile and TI scaling) or not [-] LOGICAL :: TowerFileExist !< Tower file exists [-] INTEGER(IntKi) :: TurbineID = 0 !< Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm) [-] + LOGICAL :: FixedWindFileRootName = .false. !< Do the wind data files have a fixed (DEFAULT) file name? (used by FAST.Farm) [-] END TYPE BladedInitInputType ! ======================= ! ========= BladedInitOutputType ======= @@ -80,15 +97,7 @@ MODULE FlowField_IO_Types REAL(ReKi) :: dx = 0 !< size of grids in the x direction (in the 3 files above) [-] REAL(ReKi) :: dy = 0 !< size of grids in the y direction (in the 3 files above) [-] REAL(ReKi) :: dz = 0 !< size of grids in the z direction (in the 3 files above) [-] - REAL(ReKi) :: RefHt = 0 !< Reference (hub) height of the grid [meters] - INTEGER(IntKi) :: ScaleMethod = 0 !< Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] [-] - REAL(ReKi) , DIMENSION(1:3) :: SF !< Turbulence scaling factor for each direction [ScaleMethod=1] [-] - REAL(ReKi) , DIMENSION(1:3) :: SigmaF !< Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] [-] - REAL(ReKi) :: URef = 0 !< Mean u-component wind speed at the reference height [meters] - INTEGER(IntKi) :: WindProfileType = -1 !< Wind profile type (0=constant;1=logarithmic;2=power law) [-] - REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] - REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] - REAL(ReKi) :: XOffset = 0 !< distance offset for FF wind files [meters] + TYPE(Grid3DInitInputType) :: G3D !< Grid3D initialization input [-] END TYPE HAWCInitInputType ! ======================= ! ========= UserInitInputType ======= @@ -563,6 +572,223 @@ SUBROUTINE FlowField_IO_UnPackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE FlowField_IO_UnPackUniformInitInputType + SUBROUTINE FlowField_IO_CopyGrid3DInitInputType( SrcGrid3DInitInputTypeData, DstGrid3DInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Grid3DInitInputType), INTENT(IN) :: SrcGrid3DInitInputTypeData + TYPE(Grid3DInitInputType), INTENT(INOUT) :: DstGrid3DInitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyGrid3DInitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstGrid3DInitInputTypeData%ScaleMethod = SrcGrid3DInitInputTypeData%ScaleMethod + DstGrid3DInitInputTypeData%SF = SrcGrid3DInitInputTypeData%SF + DstGrid3DInitInputTypeData%SigmaF = SrcGrid3DInitInputTypeData%SigmaF + DstGrid3DInitInputTypeData%WindProfileType = SrcGrid3DInitInputTypeData%WindProfileType + DstGrid3DInitInputTypeData%RefHt = SrcGrid3DInitInputTypeData%RefHt + DstGrid3DInitInputTypeData%URef = SrcGrid3DInitInputTypeData%URef + DstGrid3DInitInputTypeData%PLExp = SrcGrid3DInitInputTypeData%PLExp + DstGrid3DInitInputTypeData%VLinShr = SrcGrid3DInitInputTypeData%VLinShr + DstGrid3DInitInputTypeData%HLinShr = SrcGrid3DInitInputTypeData%HLinShr + DstGrid3DInitInputTypeData%RefLength = SrcGrid3DInitInputTypeData%RefLength + DstGrid3DInitInputTypeData%Z0 = SrcGrid3DInitInputTypeData%Z0 + DstGrid3DInitInputTypeData%XOffset = SrcGrid3DInitInputTypeData%XOffset + END SUBROUTINE FlowField_IO_CopyGrid3DInitInputType + + SUBROUTINE FlowField_IO_DestroyGrid3DInitInputType( Grid3DInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Grid3DInitInputType), INTENT(INOUT) :: Grid3DInitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyGrid3DInitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE FlowField_IO_DestroyGrid3DInitInputType + + SUBROUTINE FlowField_IO_PackGrid3DInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Grid3DInitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackGrid3DInitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! ScaleMethod + Re_BufSz = Re_BufSz + SIZE(InData%SF) ! SF + Re_BufSz = Re_BufSz + SIZE(InData%SigmaF) ! SigmaF + Int_BufSz = Int_BufSz + 1 ! WindProfileType + Re_BufSz = Re_BufSz + 1 ! RefHt + Re_BufSz = Re_BufSz + 1 ! URef + Re_BufSz = Re_BufSz + 1 ! PLExp + Re_BufSz = Re_BufSz + 1 ! VLinShr + Re_BufSz = Re_BufSz + 1 ! HLinShr + Re_BufSz = Re_BufSz + 1 ! RefLength + Re_BufSz = Re_BufSz + 1 ! Z0 + Re_BufSz = Re_BufSz + 1 ! XOffset + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%ScaleMethod + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%SF,1), UBOUND(InData%SF,1) + ReKiBuf(Re_Xferred) = InData%SF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%SigmaF,1), UBOUND(InData%SigmaF,1) + ReKiBuf(Re_Xferred) = InData%SigmaF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%WindProfileType + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%URef + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PLExp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VLinShr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HLinShr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Z0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%XOffset + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_IO_PackGrid3DInitInputType + + SUBROUTINE FlowField_IO_UnPackGrid3DInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Grid3DInitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackGrid3DInitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%ScaleMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%SF,1) + i1_u = UBOUND(OutData%SF,1) + DO i1 = LBOUND(OutData%SF,1), UBOUND(OutData%SF,1) + OutData%SF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%SigmaF,1) + i1_u = UBOUND(OutData%SigmaF,1) + DO i1 = LBOUND(OutData%SigmaF,1), UBOUND(OutData%SigmaF,1) + OutData%SigmaF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%WindProfileType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%URef = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PLExp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VLinShr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HLinShr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Z0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%XOffset = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE FlowField_IO_UnPackGrid3DInitInputType + SUBROUTINE FlowField_IO_CopyTurbSimInitInputType( SrcTurbSimInitInputTypeData, DstTurbSimInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(TurbSimInitInputType), INTENT(IN) :: SrcTurbSimInitInputTypeData TYPE(TurbSimInitInputType), INTENT(INOUT) :: DstTurbSimInitInputTypeData @@ -722,6 +948,7 @@ SUBROUTINE FlowField_IO_CopyBladedInitInputType( SrcBladedInitInputTypeData, Dst DstBladedInitInputTypeData%NativeBladedFmt = SrcBladedInitInputTypeData%NativeBladedFmt DstBladedInitInputTypeData%TowerFileExist = SrcBladedInitInputTypeData%TowerFileExist DstBladedInitInputTypeData%TurbineID = SrcBladedInitInputTypeData%TurbineID + DstBladedInitInputTypeData%FixedWindFileRootName = SrcBladedInitInputTypeData%FixedWindFileRootName END SUBROUTINE FlowField_IO_CopyBladedInitInputType SUBROUTINE FlowField_IO_DestroyBladedInitInputType( BladedInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -786,6 +1013,7 @@ SUBROUTINE FlowField_IO_PackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Ind Int_BufSz = Int_BufSz + 1 ! NativeBladedFmt Int_BufSz = Int_BufSz + 1 ! TowerFileExist Int_BufSz = Int_BufSz + 1 ! TurbineID + Int_BufSz = Int_BufSz + 1 ! FixedWindFileRootName IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -823,6 +1051,8 @@ SUBROUTINE FlowField_IO_PackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Ind Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%TurbineID Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FixedWindFileRootName, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE FlowField_IO_PackBladedInitInputType SUBROUTINE FlowField_IO_UnPackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -861,6 +1091,8 @@ SUBROUTINE FlowField_IO_UnPackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, O Int_Xferred = Int_Xferred + 1 OutData%TurbineID = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + OutData%FixedWindFileRootName = TRANSFER(IntKiBuf(Int_Xferred), OutData%FixedWindFileRootName) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE FlowField_IO_UnPackBladedInitInputType SUBROUTINE FlowField_IO_CopyBladedInitOutputType( SrcBladedInitOutputTypeData, DstBladedInitOutputTypeData, CtrlCode, ErrStat, ErrMsg ) @@ -1042,15 +1274,9 @@ SUBROUTINE FlowField_IO_CopyHAWCInitInputType( SrcHAWCInitInputTypeData, DstHAWC DstHAWCInitInputTypeData%dx = SrcHAWCInitInputTypeData%dx DstHAWCInitInputTypeData%dy = SrcHAWCInitInputTypeData%dy DstHAWCInitInputTypeData%dz = SrcHAWCInitInputTypeData%dz - DstHAWCInitInputTypeData%RefHt = SrcHAWCInitInputTypeData%RefHt - DstHAWCInitInputTypeData%ScaleMethod = SrcHAWCInitInputTypeData%ScaleMethod - DstHAWCInitInputTypeData%SF = SrcHAWCInitInputTypeData%SF - DstHAWCInitInputTypeData%SigmaF = SrcHAWCInitInputTypeData%SigmaF - DstHAWCInitInputTypeData%URef = SrcHAWCInitInputTypeData%URef - DstHAWCInitInputTypeData%WindProfileType = SrcHAWCInitInputTypeData%WindProfileType - DstHAWCInitInputTypeData%PLExp = SrcHAWCInitInputTypeData%PLExp - DstHAWCInitInputTypeData%Z0 = SrcHAWCInitInputTypeData%Z0 - DstHAWCInitInputTypeData%XOffset = SrcHAWCInitInputTypeData%XOffset + CALL FlowField_IO_Copygrid3dinitinputtype( SrcHAWCInitInputTypeData%G3D, DstHAWCInitInputTypeData%G3D, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE FlowField_IO_CopyHAWCInitInputType SUBROUTINE FlowField_IO_DestroyHAWCInitInputType( HAWCInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -1074,6 +1300,8 @@ SUBROUTINE FlowField_IO_DestroyHAWCInitInputType( HAWCInitInputTypeData, ErrStat DEALLOCATEpointers_local = .true. END IF + CALL FlowField_IO_Destroygrid3dinitinputtype( HAWCInitInputTypeData%G3D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE FlowField_IO_DestroyHAWCInitInputType SUBROUTINE FlowField_IO_PackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -1118,15 +1346,24 @@ SUBROUTINE FlowField_IO_PackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indat Re_BufSz = Re_BufSz + 1 ! dx Re_BufSz = Re_BufSz + 1 ! dy Re_BufSz = Re_BufSz + 1 ! dz - Re_BufSz = Re_BufSz + 1 ! RefHt - Int_BufSz = Int_BufSz + 1 ! ScaleMethod - Re_BufSz = Re_BufSz + SIZE(InData%SF) ! SF - Re_BufSz = Re_BufSz + SIZE(InData%SigmaF) ! SigmaF - Re_BufSz = Re_BufSz + 1 ! URef - Int_BufSz = Int_BufSz + 1 ! WindProfileType - Re_BufSz = Re_BufSz + 1 ! PLExp - Re_BufSz = Re_BufSz + 1 ! Z0 - Re_BufSz = Re_BufSz + 1 ! XOffset + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! G3D: size of buffers for each call to pack subtype + CALL FlowField_IO_Packgrid3dinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%G3D, ErrStat2, ErrMsg2, .TRUE. ) ! G3D + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! G3D + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! G3D + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! G3D + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1172,28 +1409,34 @@ SUBROUTINE FlowField_IO_PackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indat Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%dz Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%ScaleMethod - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%SF,1), UBOUND(InData%SF,1) - ReKiBuf(Re_Xferred) = InData%SF(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%SigmaF,1), UBOUND(InData%SigmaF,1) - ReKiBuf(Re_Xferred) = InData%SigmaF(i1) - Re_Xferred = Re_Xferred + 1 - END DO - ReKiBuf(Re_Xferred) = InData%URef - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%WindProfileType - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PLExp - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Z0 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%XOffset - Re_Xferred = Re_Xferred + 1 + CALL FlowField_IO_Packgrid3dinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%G3D, ErrStat2, ErrMsg2, OnlySize ) ! G3D + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF END SUBROUTINE FlowField_IO_PackHAWCInitInputType SUBROUTINE FlowField_IO_UnPackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1243,32 +1486,46 @@ SUBROUTINE FlowField_IO_UnPackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Out Re_Xferred = Re_Xferred + 1 OutData%dz = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - OutData%RefHt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%ScaleMethod = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%SF,1) - i1_u = UBOUND(OutData%SF,1) - DO i1 = LBOUND(OutData%SF,1), UBOUND(OutData%SF,1) - OutData%SF(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%SigmaF,1) - i1_u = UBOUND(OutData%SigmaF,1) - DO i1 = LBOUND(OutData%SigmaF,1), UBOUND(OutData%SigmaF,1) - OutData%SigmaF(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%URef = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%WindProfileType = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%PLExp = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Z0 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%XOffset = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL FlowField_IO_Unpackgrid3dinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%G3D, ErrStat2, ErrMsg2 ) ! G3D + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE FlowField_IO_UnPackHAWCInitInputType SUBROUTINE FlowField_IO_CopyUserInitInputType( SrcUserInitInputTypeData, DstUserInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/inflowwind/src/FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 similarity index 95% rename from modules/inflowwind/src/FlowField.f90 rename to modules/inflowwind/src/IfW_FlowField.f90 index 5cc2c6b95f..45d821d67a 100644 --- a/modules/inflowwind/src/FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -17,14 +17,14 @@ ! limitations under the License. !********************************************************************************************************************************** -module FlowField +module IfW_FlowField use NWTC_Library -use FlowField_Types +use IfW_FlowField_Types implicit none -public FlowField_GetVelAcc +public IfW_FlowField_GetVelAcc public UniformField_CalcAccel, Grid3DField_CalcAccel integer(IntKi), parameter :: WindProfileType_None = -1 !< don't add wind profile; already included in input @@ -36,9 +36,9 @@ module FlowField contains -!> FlowField_GetVelAcc gets the velocities (and accelerations) at the given point positions. +!> IfW_FlowField_GetVelAcc gets the velocities (and accelerations) at the given point positions. !! Accelerations are only calculated if the AccelUVW array is allocated. -subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, AccelUVW, ErrStat, ErrMsg) +subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, AccelUVW, ErrStat, ErrMsg) type(FlowFieldType), intent(in) :: FF !< FlowField data structure integer(IntKi), intent(in) :: IStart !< Start index for returning velocities for external field @@ -49,7 +49,7 @@ subroutine FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, Accel integer(IntKi), intent(out) :: ErrStat !< Error status character(*), intent(out) :: ErrMsg !< Error message - character(*), parameter :: RoutineName = "FlowField_GetVelAcc" + character(*), parameter :: RoutineName = "IfW_FlowField_GetVelAcc" integer(IntKi) :: i integer(IntKi) :: NumPoints logical :: OutputAccel @@ -721,7 +721,6 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, VelCell, AccCell, integer(IntKi) :: IT_Lo, IT_Hi logical :: OnGrid real(ReKi) :: TimeShifted - integer(IntKi) :: boundStat ErrStat = ErrID_None ErrMsg = "" @@ -1138,7 +1137,7 @@ subroutine Grid3DField_CalcAccel(G3D, ErrStat, ErrMsg) integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg integer(IntKi) :: ic, iy, iz - real(ReKi), allocatable :: b(:), u(:), dy2(:) + real(ReKi), allocatable :: u(:), dy2(:) ErrStat = ErrID_None ErrMsg = "" @@ -1150,10 +1149,11 @@ subroutine Grid3DField_CalcAccel(G3D, ErrStat, ErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return - ! Allocate storage for B used in cubic spline derivative calc - call AllocAry(B, G3D%NSteps, "storage for B", TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return + ! If number of time grids is 1 or 2, set all accelerations to zero, return + if (G3D%NTGrids < 3) then + G3D%Acc = 0.0_SiKi + return + end if ! Allocate storage for U used in cubic spline derivative calc call AllocAry(U, G3D%NSteps, "storage for U", TmpErrStat, TmpErrMsg) @@ -1165,29 +1165,32 @@ subroutine Grid3DField_CalcAccel(G3D, ErrStat, ErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return - ! Calculate acceleration at each grid point + ! Loop through grid points and calculate derivative using spline do iz = 1, G3D%NZGrids do iy = 1, G3D%NYGrids do ic = 1, G3D%NComp - call CalcCubicSplineDeriv(G3D%DTime, G3D%Vel(ic, iy, iz, :), G3D%Acc(ic, iy, iz, :)) + call CalcCubicSplineDeriv(G3D%NSteps, G3D%DTime, G3D%Vel(ic, iy, iz, :), G3D%Acc(ic, iy, iz, :)) end do end do end do - ! If grid field includes tower grids - if (G3D%NTGrids > 0) then + ! If grid field does not include tower grids, return + if (G3D%NTGrids == 0) return - ! Allocate storage for tower acceleration - call AllocAry(G3D%AccTower, size(G3D%VelTower, dim=1), & - size(G3D%VelTower, dim=2), size(G3D%VelTower, dim=3), & - 'tower wind acceleration data.', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return + ! Allocate storage for tower acceleration + call AllocAry(G3D%AccTower, size(G3D%VelTower, dim=1), & + size(G3D%VelTower, dim=2), size(G3D%VelTower, dim=3), & + 'tower wind acceleration data.', TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return - ! Loop through tower grid and calculate acceleration + ! If number of time grids is 1 or 2, set all accelerations to zero + if (G3D%NTGrids < 3) then + G3D%Acc = 0.0_SiKi + else ! Otherwise, calculate acceleration at each grid point do iz = 1, G3D%NTGrids do ic = 1, G3D%NComp - call CalcCubicSplineDeriv(G3D%DTime, G3D%VelTower(ic, iz, :), G3D%AccTower(ic, iz, :)) + call CalcCubicSplineDeriv(G3D%NSteps, G3D%DTime, G3D%VelTower(ic, iz, :), G3D%AccTower(ic, iz, :)) end do end do end if @@ -1198,51 +1201,44 @@ subroutine Grid3DField_CalcAccel(G3D, ErrStat, ErrMsg) !! spaced a constant 'h' apart. It then calculates the corresponding !! derivative of y with respect to x at the same x values and returns it !! in the dy array. - subroutine CalcCubicSplineDeriv(h, y, dy) - real(ReKi), intent(in) :: h - real(SiKi), intent(in) :: y(:) - real(SiKi), intent(out) :: dy(:) + subroutine CalcCubicSplineDeriv(n, h, y, dy) + integer(IntKi), intent(in) :: n ! number of points + real(ReKi), intent(in) :: h ! delta time + real(SiKi), intent(in) :: y(:) ! value at each time + real(SiKi), intent(out) :: dy(:) ! value derivative at each time - integer(IntKi) :: i, n + integer(IntKi) :: i real(ReKi) :: p, un - ! Get size of arrays - n = size(y) - - ! If 1 or 2 points, set derivatives to zero and return - if (n < 3) then - do i = 1, n - dy(i) = 0.0_ReKi - end do - return + ! If periodic function, set beginning and end to have same slope + if (G3D%Periodic) then + dy(1) = real((y(2) - y(n - 1))/(2.0_ReKi*h), SiKi) + dy(n) = dy(1) + else + dy(1) = 0.0_ReKi + dy(n) = 0.0_ReKi end if - ! First derivative is zero at lower boundary condition + ! Apply first derivative at lower boundary condition dy2(1) = -0.5_ReKi - u(1) = 3.0_ReKi*(y(2) - y(1))/h**2 - - ! Calculate slopes - do i = 1, n - 1 - b(i) = (y(i + 1) - y(i))/h - end do + u(1) = 3.0_ReKi*((y(2) - y(1))/h - dy(1))/h ! Decomposition do i = 2, n - 1 p = 0.5_ReKi*dy2(i - 1) + 2.0_ReKi dy2(i) = -0.5_ReKi/p - u(i) = (6.*((y(i + 1) - y(i))/h - (y(i) - y(i - 1))/h)/(2.0_ReKi*h) - 0.5_ReKi*u(i - 1))/p + u(i) = (6.*((y(i + 1) - 2.0_ReKi*y(i) + y(i - 1))/h)/(2.0_ReKi*h) - 0.5_ReKi*u(i - 1))/p end do - ! First derviative is zero at upper boundary condition - un = -3.0_ReKi*(y(n) - y(n - 1))/h**2 + ! Apply first derviative at upper boundary condition + un = 3.0_ReKi*(dy(n) - (y(n) - y(n - 1))/h)/h dy2(n) = (un - 0.5_ReKi*u(n - 1))/(0.5_ReKi*dy2(n - 1) + 1.0_ReKi) ! Back substitution and derivative calculation do i = n - 1, 1, -1 dy2(i) = dy2(i)*dy2(i + 1) + u(i) - dy(i) = real(b(i) - h*(dy2(i)/3.0_ReKi + dy2(i + 1)/6.0_ReKi), SiKi) + dy(i) = real((y(i + 1) - y(i))/h - h*(dy2(i)/3.0_ReKi + dy2(i + 1)/6.0_ReKi), SiKi) end do - dy(n) = 0.0_ReKi end subroutine diff --git a/modules/inflowwind/src/IfW_FlowField.txt b/modules/inflowwind/src/IfW_FlowField.txt new file mode 100644 index 0000000000..3549a91431 --- /dev/null +++ b/modules/inflowwind/src/IfW_FlowField.txt @@ -0,0 +1,116 @@ +#---------------------------------------------------------------------------------------------------------------------------------- +# Data structures for representing flow fields. +#---------------------------------------------------------------------------------------------------------------------------------- +# +#---------------------------------------------------------------------------------------------------------------------------------- + +param IfW_FlowField - IntKi Undef_FieldType - 0 - "This is the code for an undefined FieldType" - +param ^ - IntKi Uniform_FieldType - 1 - "Uniform FieldType from SteadyWind or Uniform Wind" - +param ^ - IntKi Grid3D_FieldType - 2 - "3D Grid FieldType from TurbSim, Bladed, HAWC" - +param ^ - IntKi Grid4D_FieldType - 3 - "4D Grid FieldType from FAST.Farm" - +param ^ - IntKi Point_FieldType - 4 - "Points FieldType from ExtInflow" - +param ^ - IntKi User_FieldType - 5 - "User FieldType configured by the user" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ UniformFieldType ReKi RefHeight - - - "reference height; used to center the wind" meters +typedef ^ ^ ReKi RefLength - - - "reference length used to scale the linear shear" meters +typedef ^ ^ IntKi DataSize - - - "size of data in HH file" +typedef ^ ^ ReKi Time : - - "HH time array" seconds +typedef ^ ^ ReKi VelH : - - "HH horizontal wind speed" meters/sec +typedef ^ ^ ReKi VelHDot : - - "Derivative of HH horizontal wind speed wrt time" meters/sec +typedef ^ ^ ReKi VelV : - - "HH vertical wind speed, including tower shadow" meters/sec +typedef ^ ^ ReKi VelVDot : - - "Derivative of HH vertical wind speed wrt time" meters/sec +typedef ^ ^ ReKi VelGust : - - "HH wind gust speed" - +typedef ^ ^ ReKi VelGustDot : - - "Derivative of HH wind gust speed wrt time" - +typedef ^ ^ ReKi AngleH : - - "HH wind direction angle" degrees +typedef ^ ^ ReKi AngleHDot : - - "Derivative of HH wind direction angle wrt time" degrees +typedef ^ ^ ReKi AngleV : - - "HH upflow angle" degrees +typedef ^ ^ ReKi AngleVDot : - - "Derivative of HH upflow angle wrt time" degrees +typedef ^ ^ ReKi ShrH : - - "HH horizontal linear shear" - +typedef ^ ^ ReKi ShrHDot : - - "Derivative of HH horizontal linear shear wrt time" - +typedef ^ ^ ReKi ShrV : - - "HH vertical shear exponent" - +typedef ^ ^ ReKi ShrVDot : - - "Derivative of HH vertical shear exponent wrt time" - +typedef ^ ^ ReKi LinShrV : - - "HH vertical linear shear" seconds +typedef ^ ^ ReKi LinShrVDot : - - "Derivative of HH vertical linear shear wrt time" seconds + +typedef ^ UniformField_Interp ReKi VelH - - - "HH horizontal wind speed" meters/sec +typedef ^ ^ ReKi VelHDot - - - "derivative of HH horizontal wind speed wrt Time" meters/sec +typedef ^ ^ ReKi VelV - - - "HH vertical wind speed, including tower shadow" meters/sec +typedef ^ ^ ReKi VelVDot - - - "derivative of HH vertical wind speed wrt Time" meters/sec +typedef ^ ^ ReKi VelGust - - - "HH wind gust speed" - +typedef ^ ^ ReKi VelGustDot - - - "derivative of HH wind gust speed wrt Time" - +typedef ^ ^ ReKi AngleH - - - "HH wind direction angle" degrees +typedef ^ ^ ReKi AngleHDot - - - "derivative of HH wind direction angle wrt Time" degrees +typedef ^ ^ ReKi AngleV - - - "HH upflow angle" degrees +typedef ^ ^ ReKi AngleVDot - - - "derivative of HH upflow angle wrt Time" degrees +typedef ^ ^ ReKi ShrH - - - "HH horizontal linear shear" - +typedef ^ ^ ReKi ShrHDot - - - "derivative of HH horizontal linear shear wrt Time" - +typedef ^ ^ ReKi ShrV - - - "HH vertical shear exponent" - +typedef ^ ^ ReKi ShrVDot - - - "derivative of HH vertical shear exponent wrt Time" - +typedef ^ ^ ReKi LinShrV - - - "HH vertical linear shear" seconds +typedef ^ ^ ReKi LinShrVDot - - - "derivative of HH vertical linear shear wrt Time" seconds +typedef ^ ^ ReKi CosAngleH - - - "Horizontal angle components" - +typedef ^ ^ ReKi SinAngleH - - - "Horizontal angle components" - +typedef ^ ^ ReKi CosAngleV - - - "Vertical angle components" - +typedef ^ ^ ReKi SinAngleV - - - "Vertical angle components" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ Grid3DFieldType IntKi WindFileFormat - - - "Binary file format description number" - +typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - +typedef ^ ^ Logical Periodic - .false. - "Flag to indicate if the wind file is periodic" - +typedef ^ ^ Logical InterpTower - .false. - "Flag to indicate if we should interpolate wind speeds below the tower" - +typedef ^ ^ Logical AddMeanAfterInterp - .false. - "Add the mean wind speed after interpolating at a given height?" - +typedef ^ ^ ReKi RefHeight - 0 - "Reference (hub) height of the grid" meters +typedef ^ ^ ReKi RefLength - 1.0_ReKi - "Reference (rotor) length of the grid (used for horizontal wind profile type only)" - +typedef ^ ^ SiKi Vel :::: - - "Array of field velocities" - +typedef ^ ^ SiKi Acc :::: - - "Array of field accelerations" - +typedef ^ ^ SiKi VelTower ::: - - "Array of tower velocities" - +typedef ^ ^ SiKi AccTower ::: - - "Array of tower accelerations" - +typedef ^ ^ ReKi DTime - 0 - "Delta time" seconds +typedef ^ ^ ReKi Rate - 0 - "Data rate (1/FFDTime)" Hertz +typedef ^ ^ ReKi YHWid - 0 - "Half the grid width" meters +typedef ^ ^ ReKi ZHWid - 0 - "Half the grid height" meters +typedef ^ ^ ReKi GridBase - 0 - "the height of the bottom of the grid" meters +typedef ^ ^ ReKi InitXPosition - 0 - "the initial x position of grid (distance in FF is offset)" meters +typedef ^ ^ ReKi InvDY - 0 - "reciprocal of delta y" 1/meters +typedef ^ ^ ReKi InvDZ - 0 - "reciprocal of delta z" 1/meters +typedef ^ ^ ReKi MeanWS - 0 - "Mean wind speed (as defined in FF file), not necessarily of the portion used" meters/second +typedef ^ ^ ReKi InvMWS - 0 - "reciprocal of mean wind speed (MeanFFWS)" seconds/meter +typedef ^ ^ ReKi TotalTime - 0 - "The total time of the simulation" seconds +typedef ^ ^ IntKi NComp - 3 - "Number of wind components" - +typedef ^ ^ IntKi NYGrids - 0 - "Number of points in the lateral (y) direction of the grids" - +typedef ^ ^ IntKi NZGrids - 0 - "Number of points in the vertical (z) direction of the grids" - +typedef ^ ^ IntKi NTGrids - 0 - "Number of points in the vertical (z) direction on the tower (below the grids)" - +typedef ^ ^ IntKi NSteps - 0 - "Number of time steps in the FF array" - +typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - +typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ UserFieldType SiKi Dummy - - - "" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ Grid4DFieldType IntKi n 4 - - "number of evenly-spaced grid points in the x, y, z, and t directions" - +typedef ^ ^ ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" +typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" +typedef ^ ^ SiKi Vel ::::: - - "this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt]" - +typedef ^ ^ ReKi TimeStart - - - "this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1))" s + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ PointsFieldType ReKi Vel :: - - "Point velocities populated by external driver [uvw,point]" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ FlowFieldType IntKi FieldType - 0 - "Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External}" - +typedef ^ ^ logical Enabled - .true. - "" - +typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters +typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians +typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" radians +typedef ^ ^ logical VelInterpCubic - .false. - "Velocity interpolation order in time (1=linear; 3=cubic) [Used with WindType=2,3,4,5,7]" - +typedef ^ ^ logical RotateWindBox - .false. - "flag indicating if the wind will be rotated" - +typedef ^ ^ logical AccFieldValid - .false. - "flag indicating that acceleration field has been calculated" - +typedef ^ ^ ReKi RotToWind {3}{3} - - "Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X')" - +typedef ^ ^ ReKi RotFromWind {3}{3} - - "Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind)" - +typedef ^ ^ UniformFieldType Uniform - - - "Uniform Flow Data" +typedef ^ ^ PointsFieldType Points - - - "External Point Flow Data" +typedef ^ ^ Grid3DFieldType Grid3D - - - "Grid Field Wind Data" +typedef ^ ^ Grid4DFieldType Grid4D - - - "External Grid Flow Data" +typedef ^ ^ UserFieldType User - - - "User Field Wind Data" diff --git a/modules/inflowwind/src/FlowField_Types.f90 b/modules/inflowwind/src/IfW_FlowField_Types.f90 similarity index 92% rename from modules/inflowwind/src/FlowField_Types.f90 rename to modules/inflowwind/src/IfW_FlowField_Types.f90 index 42eee1ec60..80de64b1fb 100644 --- a/modules/inflowwind/src/FlowField_Types.f90 +++ b/modules/inflowwind/src/IfW_FlowField_Types.f90 @@ -1,13 +1,13 @@ -!STARTOFREGISTRYGENERATEDFILE 'FlowField_Types.f90' +!STARTOFREGISTRYGENERATEDFILE 'IfW_FlowField_Types.f90' ! ! WARNING This file is generated automatically by the FAST registry. ! Do not edit. Your changes to this file will be lost. ! ! FAST Registry !********************************************************************************************************************************* -! FlowField_Types +! IfW_FlowField_Types !................................................................................................................................. -! This file is part of FlowField. +! This file is part of IfW_FlowField. ! ! Copyright (C) 2012-2016 National Renewable Energy Laboratory ! @@ -27,9 +27,9 @@ ! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. ! !********************************************************************************************************************************* -!> This module contains the user-defined types needed in FlowField. It also contains copy, destroy, pack, and +!> This module contains the user-defined types needed in IfW_FlowField. It also contains copy, destroy, pack, and !! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE FlowField_Types +MODULE IfW_FlowField_Types !--------------------------------------------------------------------------------------------------------------------------------- USE NWTC_Library IMPLICIT NONE @@ -95,6 +95,7 @@ MODULE FlowField_Types LOGICAL :: InterpTower = .false. !< Flag to indicate if we should interpolate wind speeds below the tower [-] LOGICAL :: AddMeanAfterInterp = .false. !< Add the mean wind speed after interpolating at a given height? [-] REAL(ReKi) :: RefHeight = 0 !< Reference (hub) height of the grid [meters] + REAL(ReKi) :: RefLength = 1.0_ReKi !< Reference (rotor) length of the grid (used for horizontal wind profile type only) [-] REAL(SiKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Vel !< Array of field velocities [-] REAL(SiKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Acc !< Array of field accelerations [-] REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: VelTower !< Array of tower velocities [-] @@ -158,7 +159,7 @@ MODULE FlowField_Types END TYPE FlowFieldType ! ======================= CONTAINS - SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(UniformFieldType), INTENT(IN) :: SrcUniformFieldTypeData TYPE(UniformFieldType), INTENT(INOUT) :: DstUniformFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -173,7 +174,7 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyUniformFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyUniformFieldType' ! ErrStat = ErrID_None ErrMsg = "" @@ -384,9 +385,9 @@ SUBROUTINE FlowField_CopyUniformFieldType( SrcUniformFieldTypeData, DstUniformFi END IF DstUniformFieldTypeData%LinShrVDot = SrcUniformFieldTypeData%LinShrVDot ENDIF - END SUBROUTINE FlowField_CopyUniformFieldType + END SUBROUTINE IfW_FlowField_CopyUniformFieldType - SUBROUTINE FlowField_DestroyUniformFieldType( UniformFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE IfW_FlowField_DestroyUniformFieldType( UniformFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(UniformFieldType), INTENT(INOUT) :: UniformFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -396,7 +397,7 @@ SUBROUTINE FlowField_DestroyUniformFieldType( UniformFieldTypeData, ErrStat, Err LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyUniformFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyUniformFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -458,9 +459,9 @@ SUBROUTINE FlowField_DestroyUniformFieldType( UniformFieldTypeData, ErrStat, Err IF (ALLOCATED(UniformFieldTypeData%LinShrVDot)) THEN DEALLOCATE(UniformFieldTypeData%LinShrVDot) ENDIF - END SUBROUTINE FlowField_DestroyUniformFieldType + END SUBROUTINE IfW_FlowField_DestroyUniformFieldType - SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE IfW_FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -479,7 +480,7 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackUniformFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackUniformFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -871,9 +872,9 @@ SUBROUTINE FlowField_PackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Re_Xferred = Re_Xferred + 1 END DO END IF - END SUBROUTINE FlowField_PackUniformFieldType + END SUBROUTINE IfW_FlowField_PackUniformFieldType - SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -893,7 +894,7 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackUniformFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackUniformFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1216,9 +1217,9 @@ SUBROUTINE FlowField_UnPackUniformFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Re_Xferred = Re_Xferred + 1 END DO END IF - END SUBROUTINE FlowField_UnPackUniformFieldType + END SUBROUTINE IfW_FlowField_UnPackUniformFieldType - SUBROUTINE FlowField_CopyUniformField_Interp( SrcUniformField_InterpData, DstUniformField_InterpData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_CopyUniformField_Interp( SrcUniformField_InterpData, DstUniformField_InterpData, CtrlCode, ErrStat, ErrMsg ) TYPE(UniformField_Interp), INTENT(IN) :: SrcUniformField_InterpData TYPE(UniformField_Interp), INTENT(INOUT) :: DstUniformField_InterpData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -1228,7 +1229,7 @@ SUBROUTINE FlowField_CopyUniformField_Interp( SrcUniformField_InterpData, DstUni INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyUniformField_Interp' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyUniformField_Interp' ! ErrStat = ErrID_None ErrMsg = "" @@ -1252,9 +1253,9 @@ SUBROUTINE FlowField_CopyUniformField_Interp( SrcUniformField_InterpData, DstUni DstUniformField_InterpData%SinAngleH = SrcUniformField_InterpData%SinAngleH DstUniformField_InterpData%CosAngleV = SrcUniformField_InterpData%CosAngleV DstUniformField_InterpData%SinAngleV = SrcUniformField_InterpData%SinAngleV - END SUBROUTINE FlowField_CopyUniformField_Interp + END SUBROUTINE IfW_FlowField_CopyUniformField_Interp - SUBROUTINE FlowField_DestroyUniformField_Interp( UniformField_InterpData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE IfW_FlowField_DestroyUniformField_Interp( UniformField_InterpData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(UniformField_Interp), INTENT(INOUT) :: UniformField_InterpData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1264,7 +1265,7 @@ SUBROUTINE FlowField_DestroyUniformField_Interp( UniformField_InterpData, ErrSta LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyUniformField_Interp' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyUniformField_Interp' ErrStat = ErrID_None ErrMsg = "" @@ -1275,9 +1276,9 @@ SUBROUTINE FlowField_DestroyUniformField_Interp( UniformField_InterpData, ErrSta DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE FlowField_DestroyUniformField_Interp + END SUBROUTINE IfW_FlowField_DestroyUniformField_Interp - SUBROUTINE FlowField_PackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE IfW_FlowField_PackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -1296,7 +1297,7 @@ SUBROUTINE FlowField_PackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Indata LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackUniformField_Interp' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackUniformField_Interp' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1399,9 +1400,9 @@ SUBROUTINE FlowField_PackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Indata Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%SinAngleV Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_PackUniformField_Interp + END SUBROUTINE IfW_FlowField_PackUniformField_Interp - SUBROUTINE FlowField_UnPackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_UnPackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -1416,7 +1417,7 @@ SUBROUTINE FlowField_UnPackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Outd INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackUniformField_Interp' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackUniformField_Interp' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1467,9 +1468,9 @@ SUBROUTINE FlowField_UnPackUniformField_Interp( ReKiBuf, DbKiBuf, IntKiBuf, Outd Re_Xferred = Re_Xferred + 1 OutData%SinAngleV = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_UnPackUniformField_Interp + END SUBROUTINE IfW_FlowField_UnPackUniformField_Interp - SUBROUTINE FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(Grid3DFieldType), INTENT(IN) :: SrcGrid3DFieldTypeData TYPE(Grid3DFieldType), INTENT(INOUT) :: DstGrid3DFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -1483,7 +1484,7 @@ SUBROUTINE FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DField INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyGrid3DFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyGrid3DFieldType' ! ErrStat = ErrID_None ErrMsg = "" @@ -1493,6 +1494,7 @@ SUBROUTINE FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DField DstGrid3DFieldTypeData%InterpTower = SrcGrid3DFieldTypeData%InterpTower DstGrid3DFieldTypeData%AddMeanAfterInterp = SrcGrid3DFieldTypeData%AddMeanAfterInterp DstGrid3DFieldTypeData%RefHeight = SrcGrid3DFieldTypeData%RefHeight + DstGrid3DFieldTypeData%RefLength = SrcGrid3DFieldTypeData%RefLength IF (ALLOCATED(SrcGrid3DFieldTypeData%Vel)) THEN i1_l = LBOUND(SrcGrid3DFieldTypeData%Vel,1) i1_u = UBOUND(SrcGrid3DFieldTypeData%Vel,1) @@ -1579,9 +1581,9 @@ SUBROUTINE FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DField DstGrid3DFieldTypeData%NSteps = SrcGrid3DFieldTypeData%NSteps DstGrid3DFieldTypeData%PLExp = SrcGrid3DFieldTypeData%PLExp DstGrid3DFieldTypeData%Z0 = SrcGrid3DFieldTypeData%Z0 - END SUBROUTINE FlowField_CopyGrid3DFieldType + END SUBROUTINE IfW_FlowField_CopyGrid3DFieldType - SUBROUTINE FlowField_DestroyGrid3DFieldType( Grid3DFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE IfW_FlowField_DestroyGrid3DFieldType( Grid3DFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(Grid3DFieldType), INTENT(INOUT) :: Grid3DFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -1591,7 +1593,7 @@ SUBROUTINE FlowField_DestroyGrid3DFieldType( Grid3DFieldTypeData, ErrStat, ErrMs LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyGrid3DFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyGrid3DFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -1614,9 +1616,9 @@ SUBROUTINE FlowField_DestroyGrid3DFieldType( Grid3DFieldTypeData, ErrStat, ErrMs IF (ALLOCATED(Grid3DFieldTypeData%AccTower)) THEN DEALLOCATE(Grid3DFieldTypeData%AccTower) ENDIF - END SUBROUTINE FlowField_DestroyGrid3DFieldType + END SUBROUTINE IfW_FlowField_DestroyGrid3DFieldType - SUBROUTINE FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE IfW_FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -1635,7 +1637,7 @@ SUBROUTINE FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackGrid3DFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackGrid3DFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1657,6 +1659,7 @@ SUBROUTINE FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er Int_BufSz = Int_BufSz + 1 ! InterpTower Int_BufSz = Int_BufSz + 1 ! AddMeanAfterInterp Re_BufSz = Re_BufSz + 1 ! RefHeight + Re_BufSz = Re_BufSz + 1 ! RefLength Int_BufSz = Int_BufSz + 1 ! Vel allocated yes/no IF ( ALLOCATED(InData%Vel) ) THEN Int_BufSz = Int_BufSz + 2*4 ! Vel upper/lower bounds for each dimension @@ -1734,6 +1737,8 @@ SUBROUTINE FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er Int_Xferred = Int_Xferred + 1 ReKiBuf(Re_Xferred) = InData%RefHeight Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefLength + Re_Xferred = Re_Xferred + 1 IF ( .NOT. ALLOCATED(InData%Vel) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -1880,9 +1885,9 @@ SUBROUTINE FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%Z0 Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_PackGrid3DFieldType + END SUBROUTINE IfW_FlowField_PackGrid3DFieldType - SUBROUTINE FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -1901,7 +1906,7 @@ SUBROUTINE FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackGrid3DFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackGrid3DFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -1924,6 +1929,8 @@ SUBROUTINE FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Int_Xferred = Int_Xferred + 1 OutData%RefHeight = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%RefLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vel not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -2082,9 +2089,9 @@ SUBROUTINE FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Re_Xferred = Re_Xferred + 1 OutData%Z0 = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_UnPackGrid3DFieldType + END SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType - SUBROUTINE FlowField_CopyUserFieldType( SrcUserFieldTypeData, DstUserFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_CopyUserFieldType( SrcUserFieldTypeData, DstUserFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(UserFieldType), INTENT(IN) :: SrcUserFieldTypeData TYPE(UserFieldType), INTENT(INOUT) :: DstUserFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -2094,14 +2101,14 @@ SUBROUTINE FlowField_CopyUserFieldType( SrcUserFieldTypeData, DstUserFieldTypeDa INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyUserFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyUserFieldType' ! ErrStat = ErrID_None ErrMsg = "" DstUserFieldTypeData%Dummy = SrcUserFieldTypeData%Dummy - END SUBROUTINE FlowField_CopyUserFieldType + END SUBROUTINE IfW_FlowField_CopyUserFieldType - SUBROUTINE FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE IfW_FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(UserFieldType), INTENT(INOUT) :: UserFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2111,7 +2118,7 @@ SUBROUTINE FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, D LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyUserFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyUserFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -2122,9 +2129,9 @@ SUBROUTINE FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, D DEALLOCATEpointers_local = .true. END IF - END SUBROUTINE FlowField_DestroyUserFieldType + END SUBROUTINE IfW_FlowField_DestroyUserFieldType - SUBROUTINE FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE IfW_FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -2143,7 +2150,7 @@ SUBROUTINE FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackUserFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackUserFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2189,9 +2196,9 @@ SUBROUTINE FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ReKiBuf(Re_Xferred) = InData%Dummy Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_PackUserFieldType + END SUBROUTINE IfW_FlowField_PackUserFieldType - SUBROUTINE FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -2206,7 +2213,7 @@ SUBROUTINE FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E INTEGER(IntKi) :: i INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackUserFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackUserFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2219,9 +2226,9 @@ SUBROUTINE FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Xferred = 1 OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_UnPackUserFieldType + END SUBROUTINE IfW_FlowField_UnPackUserFieldType - SUBROUTINE FlowField_CopyGrid4DFieldType( SrcGrid4DFieldTypeData, DstGrid4DFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_CopyGrid4DFieldType( SrcGrid4DFieldTypeData, DstGrid4DFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(Grid4DFieldType), INTENT(IN) :: SrcGrid4DFieldTypeData TYPE(Grid4DFieldType), INTENT(INOUT) :: DstGrid4DFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -2236,7 +2243,7 @@ SUBROUTINE FlowField_CopyGrid4DFieldType( SrcGrid4DFieldTypeData, DstGrid4DField INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyGrid4DFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyGrid4DFieldType' ! ErrStat = ErrID_None ErrMsg = "" @@ -2264,9 +2271,9 @@ SUBROUTINE FlowField_CopyGrid4DFieldType( SrcGrid4DFieldTypeData, DstGrid4DField DstGrid4DFieldTypeData%Vel = SrcGrid4DFieldTypeData%Vel ENDIF DstGrid4DFieldTypeData%TimeStart = SrcGrid4DFieldTypeData%TimeStart - END SUBROUTINE FlowField_CopyGrid4DFieldType + END SUBROUTINE IfW_FlowField_CopyGrid4DFieldType - SUBROUTINE FlowField_DestroyGrid4DFieldType( Grid4DFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE IfW_FlowField_DestroyGrid4DFieldType( Grid4DFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(Grid4DFieldType), INTENT(INOUT) :: Grid4DFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2276,7 +2283,7 @@ SUBROUTINE FlowField_DestroyGrid4DFieldType( Grid4DFieldTypeData, ErrStat, ErrMs LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyGrid4DFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyGrid4DFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -2290,9 +2297,9 @@ SUBROUTINE FlowField_DestroyGrid4DFieldType( Grid4DFieldTypeData, ErrStat, ErrMs IF (ALLOCATED(Grid4DFieldTypeData%Vel)) THEN DEALLOCATE(Grid4DFieldTypeData%Vel) ENDIF - END SUBROUTINE FlowField_DestroyGrid4DFieldType + END SUBROUTINE IfW_FlowField_DestroyGrid4DFieldType - SUBROUTINE FlowField_PackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE IfW_FlowField_PackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -2311,7 +2318,7 @@ SUBROUTINE FlowField_PackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackGrid4DFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackGrid4DFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2412,9 +2419,9 @@ SUBROUTINE FlowField_PackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er END IF ReKiBuf(Re_Xferred) = InData%TimeStart Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_PackGrid4DFieldType + END SUBROUTINE IfW_FlowField_PackGrid4DFieldType - SUBROUTINE FlowField_UnPackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_UnPackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -2434,7 +2441,7 @@ SUBROUTINE FlowField_UnPackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackGrid4DFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackGrid4DFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2503,9 +2510,9 @@ SUBROUTINE FlowField_UnPackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, END IF OutData%TimeStart = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_UnPackGrid4DFieldType + END SUBROUTINE IfW_FlowField_UnPackGrid4DFieldType - SUBROUTINE FlowField_CopyPointsFieldType( SrcPointsFieldTypeData, DstPointsFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_CopyPointsFieldType( SrcPointsFieldTypeData, DstPointsFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(PointsFieldType), INTENT(IN) :: SrcPointsFieldTypeData TYPE(PointsFieldType), INTENT(INOUT) :: DstPointsFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -2517,7 +2524,7 @@ SUBROUTINE FlowField_CopyPointsFieldType( SrcPointsFieldTypeData, DstPointsField INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyPointsFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyPointsFieldType' ! ErrStat = ErrID_None ErrMsg = "" @@ -2535,9 +2542,9 @@ SUBROUTINE FlowField_CopyPointsFieldType( SrcPointsFieldTypeData, DstPointsField END IF DstPointsFieldTypeData%Vel = SrcPointsFieldTypeData%Vel ENDIF - END SUBROUTINE FlowField_CopyPointsFieldType + END SUBROUTINE IfW_FlowField_CopyPointsFieldType - SUBROUTINE FlowField_DestroyPointsFieldType( PointsFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE IfW_FlowField_DestroyPointsFieldType( PointsFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(PointsFieldType), INTENT(INOUT) :: PointsFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2547,7 +2554,7 @@ SUBROUTINE FlowField_DestroyPointsFieldType( PointsFieldTypeData, ErrStat, ErrMs LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyPointsFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyPointsFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -2561,9 +2568,9 @@ SUBROUTINE FlowField_DestroyPointsFieldType( PointsFieldTypeData, ErrStat, ErrMs IF (ALLOCATED(PointsFieldTypeData%Vel)) THEN DEALLOCATE(PointsFieldTypeData%Vel) ENDIF - END SUBROUTINE FlowField_DestroyPointsFieldType + END SUBROUTINE IfW_FlowField_DestroyPointsFieldType - SUBROUTINE FlowField_PackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE IfW_FlowField_PackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -2582,7 +2589,7 @@ SUBROUTINE FlowField_PackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackPointsFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackPointsFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2650,9 +2657,9 @@ SUBROUTINE FlowField_PackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Er END DO END DO END IF - END SUBROUTINE FlowField_PackPointsFieldType + END SUBROUTINE IfW_FlowField_PackPointsFieldType - SUBROUTINE FlowField_UnPackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_UnPackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -2669,7 +2676,7 @@ SUBROUTINE FlowField_UnPackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackPointsFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackPointsFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2703,9 +2710,9 @@ SUBROUTINE FlowField_UnPackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, END DO END DO END IF - END SUBROUTINE FlowField_UnPackPointsFieldType + END SUBROUTINE IfW_FlowField_UnPackPointsFieldType - SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(FlowFieldType), INTENT(IN) :: SrcFlowFieldTypeData TYPE(FlowFieldType), INTENT(INOUT) :: DstFlowFieldTypeData INTEGER(IntKi), INTENT(IN ) :: CtrlCode @@ -2717,7 +2724,7 @@ SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeDa INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_CopyFlowFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyFlowFieldType' ! ErrStat = ErrID_None ErrMsg = "" @@ -2731,24 +2738,24 @@ SUBROUTINE FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeDa DstFlowFieldTypeData%AccFieldValid = SrcFlowFieldTypeData%AccFieldValid DstFlowFieldTypeData%RotToWind = SrcFlowFieldTypeData%RotToWind DstFlowFieldTypeData%RotFromWind = SrcFlowFieldTypeData%RotFromWind - CALL FlowField_Copyuniformfieldtype( SrcFlowFieldTypeData%Uniform, DstFlowFieldTypeData%Uniform, CtrlCode, ErrStat2, ErrMsg2 ) + CALL IfW_FlowField_Copyuniformfieldtype( SrcFlowFieldTypeData%Uniform, DstFlowFieldTypeData%Uniform, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_Copypointsfieldtype( SrcFlowFieldTypeData%Points, DstFlowFieldTypeData%Points, CtrlCode, ErrStat2, ErrMsg2 ) + CALL IfW_FlowField_Copypointsfieldtype( SrcFlowFieldTypeData%Points, DstFlowFieldTypeData%Points, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_Copygrid3dfieldtype( SrcFlowFieldTypeData%Grid3D, DstFlowFieldTypeData%Grid3D, CtrlCode, ErrStat2, ErrMsg2 ) + CALL IfW_FlowField_Copygrid3dfieldtype( SrcFlowFieldTypeData%Grid3D, DstFlowFieldTypeData%Grid3D, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_Copygrid4dfieldtype( SrcFlowFieldTypeData%Grid4D, DstFlowFieldTypeData%Grid4D, CtrlCode, ErrStat2, ErrMsg2 ) + CALL IfW_FlowField_Copygrid4dfieldtype( SrcFlowFieldTypeData%Grid4D, DstFlowFieldTypeData%Grid4D, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_Copyuserfieldtype( SrcFlowFieldTypeData%User, DstFlowFieldTypeData%User, CtrlCode, ErrStat2, ErrMsg2 ) + CALL IfW_FlowField_Copyuserfieldtype( SrcFlowFieldTypeData%User, DstFlowFieldTypeData%User, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE FlowField_CopyFlowFieldType + END SUBROUTINE IfW_FlowField_CopyFlowFieldType - SUBROUTINE FlowField_DestroyFlowFieldType( FlowFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + SUBROUTINE IfW_FlowField_DestroyFlowFieldType( FlowFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) TYPE(FlowFieldType), INTENT(INOUT) :: FlowFieldTypeData INTEGER(IntKi), INTENT( OUT) :: ErrStat CHARACTER(*), INTENT( OUT) :: ErrMsg @@ -2758,7 +2765,7 @@ SUBROUTINE FlowField_DestroyFlowFieldType( FlowFieldTypeData, ErrStat, ErrMsg, D LOGICAL :: DEALLOCATEpointers_local INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_DestroyFlowFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyFlowFieldType' ErrStat = ErrID_None ErrMsg = "" @@ -2769,19 +2776,19 @@ SUBROUTINE FlowField_DestroyFlowFieldType( FlowFieldTypeData, ErrStat, ErrMsg, D DEALLOCATEpointers_local = .true. END IF - CALL FlowField_Destroyuniformfieldtype( FlowFieldTypeData%Uniform, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL IfW_FlowField_Destroyuniformfieldtype( FlowFieldTypeData%Uniform, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_Destroypointsfieldtype( FlowFieldTypeData%Points, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL IfW_FlowField_Destroypointsfieldtype( FlowFieldTypeData%Points, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_Destroygrid3dfieldtype( FlowFieldTypeData%Grid3D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL IfW_FlowField_Destroygrid3dfieldtype( FlowFieldTypeData%Grid3D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_Destroygrid4dfieldtype( FlowFieldTypeData%Grid4D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL IfW_FlowField_Destroygrid4dfieldtype( FlowFieldTypeData%Grid4D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_Destroyuserfieldtype( FlowFieldTypeData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL IfW_FlowField_Destroyuserfieldtype( FlowFieldTypeData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE FlowField_DestroyFlowFieldType + END SUBROUTINE IfW_FlowField_DestroyFlowFieldType - SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + SUBROUTINE IfW_FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) @@ -2800,7 +2807,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_PackFlowFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackFlowFieldType' ! buffers to store subtypes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -2828,7 +2835,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Re_BufSz = Re_BufSz + SIZE(InData%RotFromWind) ! RotFromWind ! Allocate buffers for subtypes, if any (we'll get sizes from these) Int_BufSz = Int_BufSz + 3 ! Uniform: size of buffers for each call to pack subtype - CALL FlowField_Packuniformfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, .TRUE. ) ! Uniform + CALL IfW_FlowField_Packuniformfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, .TRUE. ) ! Uniform CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2845,7 +2852,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! Points: size of buffers for each call to pack subtype - CALL FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, .TRUE. ) ! Points + CALL IfW_FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, .TRUE. ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2862,7 +2869,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! Grid3D: size of buffers for each call to pack subtype - CALL FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid3D + CALL IfW_FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid3D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2879,7 +2886,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! Grid4D: size of buffers for each call to pack subtype - CALL FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid4D + CALL IfW_FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2896,7 +2903,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! User: size of buffers for each call to pack subtype - CALL FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, .TRUE. ) ! User + CALL IfW_FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, .TRUE. ) ! User CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2969,7 +2976,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS Re_Xferred = Re_Xferred + 1 END DO END DO - CALL FlowField_Packuniformfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, OnlySize ) ! Uniform + CALL IfW_FlowField_Packuniformfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, OnlySize ) ! Uniform CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2997,7 +3004,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, OnlySize ) ! Points + CALL IfW_FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, OnlySize ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3025,7 +3032,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, OnlySize ) ! Grid3D + CALL IfW_FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, OnlySize ) ! Grid3D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3053,7 +3060,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, OnlySize ) ! Grid4D + CALL IfW_FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, OnlySize ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3081,7 +3088,7 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, OnlySize ) ! User + CALL IfW_FlowField_Packuserfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, OnlySize ) ! User CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3109,9 +3116,9 @@ SUBROUTINE FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrS ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - END SUBROUTINE FlowField_PackFlowFieldType + END SUBROUTINE IfW_FlowField_PackFlowFieldType - SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + SUBROUTINE IfW_FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) @@ -3128,7 +3135,7 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_UnPackFlowFieldType' + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackFlowFieldType' ! buffers to store meshes, if any REAL(ReKi), ALLOCATABLE :: Re_Buf(:) REAL(DbKi), ALLOCATABLE :: Db_Buf(:) @@ -3212,7 +3219,7 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackuniformfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Uniform, ErrStat2, ErrMsg2 ) ! Uniform + CALL IfW_FlowField_Unpackuniformfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Uniform, ErrStat2, ErrMsg2 ) ! Uniform CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3252,7 +3259,7 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Points, ErrStat2, ErrMsg2 ) ! Points + CALL IfW_FlowField_Unpackpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Points, ErrStat2, ErrMsg2 ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3292,7 +3299,7 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid3D, ErrStat2, ErrMsg2 ) ! Grid3D + CALL IfW_FlowField_Unpackgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid3D, ErrStat2, ErrMsg2 ) ! Grid3D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3332,7 +3339,7 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid4D, ErrStat2, ErrMsg2 ) ! Grid4D + CALL IfW_FlowField_Unpackgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid4D, ErrStat2, ErrMsg2 ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3372,14 +3379,14 @@ SUBROUTINE FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, E Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackuserfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%User, ErrStat2, ErrMsg2 ) ! User + CALL IfW_FlowField_Unpackuserfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%User, ErrStat2, ErrMsg2 ) ! User CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE FlowField_UnPackFlowFieldType + END SUBROUTINE IfW_FlowField_UnPackFlowFieldType -END MODULE FlowField_Types +END MODULE IfW_FlowField_Types !ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 6396722a4f..675aef5461 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -336,24 +336,24 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, case (TSFF_WindNumber) FlowField_InitData%TurbSim%WindFileName = InputFileData%TSFF_FileName - case (BladedFF_WindNumber, BladedFF_Shr_WindNumber) + case (BladedFF_WindNumber) FlowField_InitData%Bladed%TurbineID = InitInp%TurbineID - if (InputFileData%WindType /= BladedFF_Shr_WindNumber) then - IF ( InitInp%FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data - IF ( InitInp%TurbineID == 0 ) THEN ! .TRUE. for the FAST.Farm low-resolution domain - InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'Low' - ELSE ! FAST.Farm high-resolution domain(s) - InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) - ENDIF + IF ( InitInp%FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data + IF ( InitInp%TurbineID == 0 ) THEN ! .TRUE. for the FAST.Farm low-resolution domain + InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'Low' + ELSE ! FAST.Farm high-resolution domain(s) + InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) ENDIF - FlowField_InitData%Bladed%WindFileName = TRIM(InputFileData%BladedFF_FileName)//'.wnd' - FlowField_InitData%Bladed%TowerFileExist = InputFileData%BladedFF_TowerFile - FlowField_InitData%Bladed%NativeBladedFmt = .false. - else - FlowField_InitData%Bladed%WindFileName = InputFileData%BladedFF_FileName - FlowField_InitData%Bladed%TowerFileExist = .false. - FlowField_InitData%Bladed%NativeBladedFmt = .true. - end if + ENDIF + FlowField_InitData%Bladed%WindFileName = TRIM(InputFileData%BladedFF_FileName)//'.wnd' + FlowField_InitData%Bladed%TowerFileExist = InputFileData%BladedFF_TowerFile + FlowField_InitData%Bladed%NativeBladedFmt = .false. + + case (BladedFF_Shr_WindNumber) + FlowField_InitData%Bladed%TurbineID = InitInp%TurbineID + FlowField_InitData%Bladed%WindFileName = InputFileData%BladedFF_FileName + FlowField_InitData%Bladed%TowerFileExist = .false. + FlowField_InitData%Bladed%NativeBladedFmt = .true. case (HAWC_WindNumber) FlowField_InitData%HAWC%WindFileName(1) = InputFileData%HAWC_FileName_u @@ -365,15 +365,15 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, FlowField_InitData%HAWC%dx = InputFileData%HAWC_dx FlowField_InitData%HAWC%dy = InputFileData%HAWC_dy FlowField_InitData%HAWC%dz = InputFileData%HAWC_dz - FlowField_InitData%HAWC%RefHt = InputFileData%FF%RefHt - FlowField_InitData%HAWC%ScaleMethod = InputFileData%FF%ScaleMethod - FlowField_InitData%HAWC%SF = InputFileData%FF%SF - FlowField_InitData%HAWC%SigmaF = InputFileData%FF%SigmaF - FlowField_InitData%HAWC%URef = InputFileData%FF%URef - FlowField_InitData%HAWC%WindProfileType = InputFileData%FF%WindProfileType - FlowField_InitData%HAWC%PLExp = InputFileData%FF%PLExp - FlowField_InitData%HAWC%Z0 = InputFileData%FF%Z0 - FlowField_InitData%HAWC%XOffset = InputFileData%FF%XOffset + FlowField_InitData%HAWC%G3D%RefHt = InputFileData%FF%RefHt + FlowField_InitData%HAWC%G3D%ScaleMethod = InputFileData%FF%ScaleMethod + FlowField_InitData%HAWC%G3D%SF = InputFileData%FF%SF + FlowField_InitData%HAWC%G3D%SigmaF = InputFileData%FF%SigmaF + FlowField_InitData%HAWC%G3D%URef = InputFileData%FF%URef + FlowField_InitData%HAWC%G3D%WindProfileType = InputFileData%FF%WindProfileType + FlowField_InitData%HAWC%G3D%PLExp = InputFileData%FF%PLExp + FlowField_InitData%HAWC%G3D%Z0 = InputFileData%FF%Z0 + FlowField_InitData%HAWC%G3D%XOffset = InputFileData%FF%XOffset case (User_WindNumber) ! Add user wind initialization data here diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 955d0d14c6..3f0b89c1af 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -7,7 +7,7 @@ # keyword ################################################################################################################################### -usefrom FlowField.txt +usefrom IfW_FlowField.txt usefrom IfW_UniformWind.txt usefrom IfW_TSFFWind.txt usefrom IfW_FFWind_Base.txt @@ -151,7 +151,7 @@ typedef ^ ^ ReKi ReferenceHe typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters typedef ^ ^ IntKi NWindVel - - - "Number of points in the wind velocity list" - typedef ^ ^ ReKi WindViXYZ :: - - "List of XYZ coordinates for wind velocity measurements, 3xNWindVel" meters -typedef ^ ^ FlowFieldType FlowField - - - "Parameters from Full-Field" - +typedef ^ ^ FlowFieldType FlowField - - - "Parameters from Full-Field" - typedef ^ ^ IfW_UniformWind_ParameterType UniformWind - - - "Parameters from UniformWind" - typedef ^ ^ IfW_TSFFWind_ParameterType TSFFWind - - - "Parameters from TSFFWind -- TurbSim full-field format" - typedef ^ ^ IfW_BladedFFWind_ParameterType BladedFFWind - - - "Parameters from BladedFFWind -- Bladed-style full-field format" - diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index 16c91a6c21..33725b839c 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -30,7 +30,7 @@ PROGRAM InflowWind_Driver USE InflowWind_Types USE InflowWind_Driver_Types ! Contains types and routines for handling the input arguments USE InflowWind_Driver_Subs ! Contains subroutines for the driver program - USE FlowField + USE IfW_FlowField USE InflowWind_Subs, only: CalculateOutput IMPLICIT NONE diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index 62e655f9d3..969651e2b2 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -1458,7 +1458,7 @@ END SUBROUTINE InflowWind_CloseSumFile SUBROUTINE CalculateOutput( Time, InputData, p, x, xd, z, OtherStates, y, m, FillWrOut, ErrStat, ErrMsg ) - USE FlowField, only: FlowField_GetVelAcc + USE IfW_FlowField, only: IfW_FlowField_GetVelAcc IMPLICIT NONE @@ -1503,14 +1503,14 @@ SUBROUTINE CalculateOutput( Time, InputData, p, x, xd, z, OtherStates, y, m, Fil !----------------------------------------------------------------------- if (p%FlowField%Enabled) then - CALL FlowField_GetVelAcc(p%FlowField, 0, Time, InputData%PositionXYZ, & + CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, InputData%PositionXYZ, & y%VelocityUVW, y%AccelUVW, TmpErrStat, TmpErrMsg) CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev ) RETURN ! Call IfW_UniformWind_CalcOutput again in order to get the values needed for the OutList -- note that we do not report errors from this IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - CALL FlowField_GetVelAcc(p%FlowField, 0, Time, p%WindViXYZ, & + CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, p%WindViXYZ, & m%WindViUVW, m%WindAiUVW, TmpErrStat, TmpErrMsg) ENDIF return diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index a56750358b..5031018ab8 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -31,7 +31,7 @@ !! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. MODULE InflowWind_Types !--------------------------------------------------------------------------------------------------------------------------------- -USE FlowField_Types +USE IfW_FlowField_Types USE IfW_UniformWind_Types USE IfW_TSFFWind_Types USE IfW_BladedFFWind_Types @@ -2505,7 +2505,7 @@ SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, END IF DstParamData%WindViXYZ = SrcParamData%WindViXYZ ENDIF - CALL FlowField_Copyflowfieldtype( SrcParamData%FlowField, DstParamData%FlowField, CtrlCode, ErrStat2, ErrMsg2 ) + CALL IfW_FlowField_Copyflowfieldtype( SrcParamData%FlowField, DstParamData%FlowField, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN CALL IfW_UniformWind_CopyParam( SrcParamData%UniformWind, DstParamData%UniformWind, CtrlCode, ErrStat2, ErrMsg2 ) @@ -2603,7 +2603,7 @@ SUBROUTINE InflowWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointe IF (ALLOCATED(ParamData%WindViXYZ)) THEN DEALLOCATE(ParamData%WindViXYZ) ENDIF - CALL FlowField_Destroyflowfieldtype( ParamData%FlowField, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL IfW_FlowField_Destroyflowfieldtype( ParamData%FlowField, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL IfW_UniformWind_DestroyParam( ParamData%UniformWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2693,7 +2693,7 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END IF ! Allocate buffers for subtypes, if any (we'll get sizes from these) Int_BufSz = Int_BufSz + 3 ! FlowField: size of buffers for each call to pack subtype - CALL FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, .TRUE. ) ! FlowField + CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, .TRUE. ) ! FlowField CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2965,7 +2965,7 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END DO END DO END IF - CALL FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, OnlySize ) ! FlowField + CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, OnlySize ) ! FlowField CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3427,7 +3427,7 @@ SUBROUTINE InflowWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL FlowField_Unpackflowfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%FlowField, ErrStat2, ErrMsg2 ) ! FlowField + CALL IfW_FlowField_Unpackflowfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%FlowField, ErrStat2, ErrMsg2 ) ! FlowField CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN From b370ab7c1f70805dc08e692dfaf238a37ac7d4d4 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 25 Aug 2021 14:40:22 -0600 Subject: [PATCH 15/51] IfW: add flags for handling wind grid exceedence points (only for OLAF) --- modules/inflowwind/src/IfW_BladedFFWind.f90 | 29 +++++ modules/inflowwind/src/IfW_BladedFFWind.txt | 2 +- .../inflowwind/src/IfW_BladedFFWind_Types.f90 | 92 +++++++++++++++ modules/inflowwind/src/IfW_FFWind_Base.f90 | 59 ++++++++++ modules/inflowwind/src/IfW_FFWind_Base.txt | 5 + .../inflowwind/src/IfW_FFWind_Base_Types.f90 | 106 ++++++++++++++++++ modules/inflowwind/src/IfW_HAWCWind.f90 | 29 +++++ modules/inflowwind/src/IfW_HAWCWind.txt | 2 +- modules/inflowwind/src/IfW_HAWCWind_Types.f90 | 2 +- modules/inflowwind/src/IfW_TSFFWind.f90 | 28 +++++ modules/inflowwind/src/IfW_TSFFWind.txt | 5 +- modules/inflowwind/src/IfW_TSFFWind_Types.f90 | 92 +++++++++++++++ modules/inflowwind/src/InflowWind.f90 | 21 ++++ modules/inflowwind/src/InflowWind.txt | 2 + modules/inflowwind/src/InflowWind_Types.f90 | 14 +++ 15 files changed, 483 insertions(+), 5 deletions(-) diff --git a/modules/inflowwind/src/IfW_BladedFFWind.f90 b/modules/inflowwind/src/IfW_BladedFFWind.f90 index c2e54892a4..fc655af876 100644 --- a/modules/inflowwind/src/IfW_BladedFFWind.f90 +++ b/modules/inflowwind/src/IfW_BladedFFWind.f90 @@ -137,6 +137,20 @@ SUBROUTINE IfW_BladedFFWind_Init(InitInp, ParamData, MiscVars, InitOutData, ErrS END IF + !------------------------------------------------------------------------------------------------- + ! Set box exceedence averaging grid + !------------------------------------------------------------------------------------------------- + + ParamData%FF%BoxExceedAllowF = InitInp%FF%BoxExceedAllowF + ParamData%FF%BoxExceedAllowIdx = InitInp%FF%BoxExceedAllowIdx + + if ( ParamData%FF%BoxExceedAllowF ) then + call GenMeanGridProfileTimeSeries( ParamData%FF, TmpErrStat, TmpErrMsg ) + call SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if ( ErrStat >= AbortErrLev ) return + endif + + !------------------------------------------------------------------------------------------------- ! Set the InitOutput information !------------------------------------------------------------------------------------------------- @@ -186,6 +200,21 @@ SUBROUTINE IfW_BladedFFWind_Init(InitInp, ParamData, MiscVars, InitOutData, ErrS TRIM(Num2LStr(ParamData%FF%RefHt - ParamData%FF%FFZHWid))//' : '//TRIM(Num2LStr(ParamData%FF%RefHt + ParamData%FF%FFZHWid))//' ]' ENDIF + IF ( ParamData%FF%BoxExceedAllowF ) THEN + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Wind grid exceedence allowed: '// & + 'True -- Only for points requested by OLAF free vortex wake, or LidarSim module' + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' '// & + ' Out of bounds values are linearly interpolated to mean at Z loction for' + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' '// & + ' given timestep and X,T value. Values above grid are held to top of wind' + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' '// & + ' grid value' + ELSE + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Wind grid exceedence allowed: '// & + 'False' + ENDIF + + ! We are assuming that if the last line was written ok, then all of them were. IF (TmpErrStat /= 0_IntKi) THEN diff --git a/modules/inflowwind/src/IfW_BladedFFWind.txt b/modules/inflowwind/src/IfW_BladedFFWind.txt index 76a57b1b5f..7e622e6630 100644 --- a/modules/inflowwind/src/IfW_BladedFFWind.txt +++ b/modules/inflowwind/src/IfW_BladedFFWind.txt @@ -19,7 +19,7 @@ typedef ^ ^ IntKi typedef ^ ^ Logical NativeBladedFmt - - - "Whether this is native Bladed (needs wind profile and TI scaling) or not" - typedef ^ ^ IntKi TurbineID - 0 - "Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm)" - typedef ^ ^ LOGICAL FixedWindFileRootName - .FALSE. - "Do the wind data files have a fixed (DEFAULT) file name? (used by FAST.Farm)" - -#typedef ^ ^ IfW_FFWind_InitInputType FF - - - "scaling data (provided for native Bladed format)" - +typedef ^ ^ IfW_FFWind_InitInputType FF - - - "scaling data and wind box exceedence flags" - # Init Output diff --git a/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 b/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 index 4f0ea3b994..b540ee2f78 100644 --- a/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 +++ b/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 @@ -42,6 +42,7 @@ MODULE IfW_BladedFFWind_Types LOGICAL :: NativeBladedFmt !< Whether this is native Bladed (needs wind profile and TI scaling) or not [-] INTEGER(IntKi) :: TurbineID = 0 !< Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm) [-] LOGICAL :: FixedWindFileRootName = .FALSE. !< Do the wind data files have a fixed (DEFAULT) file name? (used by FAST.Farm) [-] + TYPE(IfW_FFWind_InitInputType) :: FF !< scaling data and wind box exceedence flags [-] END TYPE IfW_BladedFFWind_InitInputType ! ======================= ! ========= IfW_BladedFFWind_InitOutputType ======= @@ -84,6 +85,9 @@ SUBROUTINE IfW_BladedFFWind_CopyInitInput( SrcInitInputData, DstInitInputData, C DstInitInputData%NativeBladedFmt = SrcInitInputData%NativeBladedFmt DstInitInputData%TurbineID = SrcInitInputData%TurbineID DstInitInputData%FixedWindFileRootName = SrcInitInputData%FixedWindFileRootName + CALL IfW_FFWind_CopyInitInput( SrcInitInputData%FF, DstInitInputData%FF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE IfW_BladedFFWind_CopyInitInput SUBROUTINE IfW_BladedFFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -107,6 +111,8 @@ SUBROUTINE IfW_BladedFFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DE DEALLOCATEpointers_local = .true. END IF + CALL IfW_FFWind_DestroyInitInput( InitInputData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE IfW_BladedFFWind_DestroyInitInput SUBROUTINE IfW_BladedFFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -150,6 +156,24 @@ SUBROUTINE IfW_BladedFFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Int_BufSz = Int_BufSz + 1 ! NativeBladedFmt Int_BufSz = Int_BufSz + 1 ! TurbineID Int_BufSz = Int_BufSz + 1 ! FixedWindFileRootName + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype + CALL IfW_FFWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -191,6 +215,34 @@ SUBROUTINE IfW_BladedFFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, E Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%FixedWindFileRootName, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 + CALL IfW_FFWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF END SUBROUTINE IfW_BladedFFWind_PackInitInput SUBROUTINE IfW_BladedFFWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -234,6 +286,46 @@ SUBROUTINE IfW_BladedFFWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata Int_Xferred = Int_Xferred + 1 OutData%FixedWindFileRootName = TRANSFER(IntKiBuf(Int_Xferred), OutData%FixedWindFileRootName) Int_Xferred = Int_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FFWind_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE IfW_BladedFFWind_UnPackInitInput SUBROUTINE IfW_BladedFFWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/inflowwind/src/IfW_FFWind_Base.f90 b/modules/inflowwind/src/IfW_FFWind_Base.f90 index 365feed37d..f9db8ce937 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base.f90 +++ b/modules/inflowwind/src/IfW_FFWind_Base.f90 @@ -1200,6 +1200,65 @@ SUBROUTINE ConvertFFWind_toVTK(FileRootName, p, ErrStat, ErrMsg) END SUBROUTINE ConvertFFWind_toVTK +!==================================================================================================== +!> This subroutine generates the mean wind vector timeseries for each height above the ground. This +!! is essentially compressing the Y dimension of the wind box leaving a Z-T plane of vectors. The +!! resulting dimensions will be (NZGrids, NYGrids, NFFComp, NFFSteps) +subroutine GenMeanGridProfileTimeSeries( p, ErrStat, ErrMsg ) + type(IfW_FFWind_ParameterType), intent(inout) :: p !< Parameters + integer(IntKi), intent( out) :: ErrStat !< Error status of the operation + character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables + integer :: i + integer :: iy + integer :: iz + integer :: it + + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'GenMeanProfileTimeSeries' + + ErrStat = ErrID_None + ErrMsg = "" + + if ( .not. p%BoxExceedAllowF ) return + if ( p%BoxExceedAllowIdx <= 0_IntKi ) return ! Index too low, so skip + if ( .not. allocated( p%FFData ) ) then + ErrStat = ErrID_Fatal + ErrMSg = "Call before data has been read or allocated." + return + endif + + ! Allocate array + if ( .not. allocated( p%FFAvgData ) ) then + CALL AllocAry( p%FFAvgData, p%NZGrids, p%NFFComp, p%NFFSteps, & + 'Full-field average wind profile timeseries data array.', ErrStat2, ErrMsg2 ) + if (Failed()) return + p%FFAvgData = 0.0_SiKi + endif + + + ! Populate array based on FFData (we don't consider any tower info -- we can get that from the tower interp later) + ! NOTE: this looping structure may be a bit slow. We are averaging across an intermediate dimension + do it=1,p%NFFSteps + do i=1,p%NFFComp + do iz=1,p%NZGrids + do iy=1,p%NYGrids + p%FFAvgData(iz,i,it) = p%FFAvgData(iz,i,it) + p%FFData(iz,iy,i,it) + enddo + p%FFAvgData(iz,i,it) = p%FFAvgData(iz,i,it) / real(p%NYGrids, SiKi) + enddo + enddo + enddo + +contains + logical function Failed() + CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + Failed = ErrStat >= AbortErrLev + end function Failed + +end subroutine GenMeanGridProfileTimeSeries !==================================================================================================== END MODULE IfW_FFWind_Base diff --git a/modules/inflowwind/src/IfW_FFWind_Base.txt b/modules/inflowwind/src/IfW_FFWind_Base.txt index 1febd8d685..622c057307 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base.txt +++ b/modules/inflowwind/src/IfW_FFWind_Base.txt @@ -22,6 +22,8 @@ typedef ^ ^ ReKi HLinSh typedef ^ ^ ReKi RefLength - 1.0_ReKi - "Reference (rotor) length of the grid (used for horizontal wind profile type only)" - typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - typedef ^ ^ ReKi XOffset - 0 - "distance offset for FF wind files" m +typedef ^ ^ IntKi BoxExceedAllowIdx - - - "Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim)" - +typedef ^ ^ LOGICAL BoxExceedAllowF - - - "Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim)" - # ..... Parameters ................................................................................................................ @@ -31,6 +33,7 @@ typedef ^ ParameterType Logical Period typedef ^ ParameterType Logical InterpTower - .FALSE. - "Flag to indicate if we should interpolate wind speeds below the tower" - typedef ^ ^ SiKi FFData :::: - - "Array of FF data" - typedef ^ ^ SiKi FFTower ::: - - "Array of data along tower, below FF array" - +typedef ^ ^ SiKi FFAvgData ::: - - "Average velocity profile by Z and time" - typedef ^ ^ ReKi FFDTime - 0 - "Delta time" seconds typedef ^ ^ ReKi FFRate - 0 - "Data rate (1/FFDTime)" Hertz typedef ^ ^ ReKi FFYHWid - 0 - "Half the grid width" meters @@ -56,4 +59,6 @@ typedef ^ ^ ReKi Z0 typedef ^ ^ ReKi VLinShr - 0 - "Vertical linear wind shear coefficient (used for vertical linear wind profile type only)" - typedef ^ ^ ReKi HLinShr - 0 - "Horizontal linear wind shear coefficient (used for horizontal wind profile type only)" - typedef ^ ^ ReKi RefLength - 1.0_ReKi - "Reference (rotor) length of the grid (used for horizontal wind profile type only)" - +typedef ^ ^ LOGICAL BoxExceedAllowF - .FALSE. - "Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim)" - +typedef ^ ^ IntKi BoxExceedAllowIdx - -1 - "Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim)" - diff --git a/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 b/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 index 9f5c55c5d2..7a05fdc08c 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 +++ b/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 @@ -47,6 +47,8 @@ MODULE IfW_FFWind_Base_Types REAL(ReKi) :: RefLength = 1.0_ReKi !< Reference (rotor) length of the grid (used for horizontal wind profile type only) [-] REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] REAL(ReKi) :: XOffset = 0 !< distance offset for FF wind files [m] + INTEGER(IntKi) :: BoxExceedAllowIdx !< Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim) [-] + LOGICAL :: BoxExceedAllowF !< Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim) [-] END TYPE IfW_FFWind_InitInputType ! ======================= ! ========= IfW_FFWind_ParameterType ======= @@ -55,6 +57,7 @@ MODULE IfW_FFWind_Base_Types LOGICAL :: InterpTower = .FALSE. !< Flag to indicate if we should interpolate wind speeds below the tower [-] REAL(SiKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: FFData !< Array of FF data [-] REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: FFTower !< Array of data along tower, below FF array [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: FFAvgData !< Average velocity profile by Z and time [-] REAL(ReKi) :: FFDTime = 0 !< Delta time [seconds] REAL(ReKi) :: FFRate = 0 !< Data rate (1/FFDTime) [Hertz] REAL(ReKi) :: FFYHWid = 0 !< Half the grid width [meters] @@ -80,6 +83,8 @@ MODULE IfW_FFWind_Base_Types REAL(ReKi) :: VLinShr = 0 !< Vertical linear wind shear coefficient (used for vertical linear wind profile type only) [-] REAL(ReKi) :: HLinShr = 0 !< Horizontal linear wind shear coefficient (used for horizontal wind profile type only) [-] REAL(ReKi) :: RefLength = 1.0_ReKi !< Reference (rotor) length of the grid (used for horizontal wind profile type only) [-] + LOGICAL :: BoxExceedAllowF = .FALSE. !< Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim) [-] + INTEGER(IntKi) :: BoxExceedAllowIdx = -1 !< Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim) [-] END TYPE IfW_FFWind_ParameterType ! ======================= CONTAINS @@ -113,6 +118,8 @@ SUBROUTINE IfW_FFWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCod DstInitInputData%RefLength = SrcInitInputData%RefLength DstInitInputData%Z0 = SrcInitInputData%Z0 DstInitInputData%XOffset = SrcInitInputData%XOffset + DstInitInputData%BoxExceedAllowIdx = SrcInitInputData%BoxExceedAllowIdx + DstInitInputData%BoxExceedAllowF = SrcInitInputData%BoxExceedAllowF END SUBROUTINE IfW_FFWind_CopyInitInput SUBROUTINE IfW_FFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -185,6 +192,8 @@ SUBROUTINE IfW_FFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Re_BufSz = Re_BufSz + 1 ! RefLength Re_BufSz = Re_BufSz + 1 ! Z0 Re_BufSz = Re_BufSz + 1 ! XOffset + Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowIdx + Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -240,6 +249,10 @@ SUBROUTINE IfW_FFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%XOffset Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BoxExceedAllowIdx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedAllowF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE IfW_FFWind_PackInitInput SUBROUTINE IfW_FFWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -304,6 +317,10 @@ SUBROUTINE IfW_FFWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS Re_Xferred = Re_Xferred + 1 OutData%XOffset = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%BoxExceedAllowIdx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BoxExceedAllowF = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedAllowF) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE IfW_FFWind_UnPackInitInput SUBROUTINE IfW_FFWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) @@ -359,6 +376,22 @@ SUBROUTINE IfW_FFWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, END IF END IF DstParamData%FFTower = SrcParamData%FFTower +ENDIF +IF (ALLOCATED(SrcParamData%FFAvgData)) THEN + i1_l = LBOUND(SrcParamData%FFAvgData,1) + i1_u = UBOUND(SrcParamData%FFAvgData,1) + i2_l = LBOUND(SrcParamData%FFAvgData,2) + i2_u = UBOUND(SrcParamData%FFAvgData,2) + i3_l = LBOUND(SrcParamData%FFAvgData,3) + i3_u = UBOUND(SrcParamData%FFAvgData,3) + IF (.NOT. ALLOCATED(DstParamData%FFAvgData)) THEN + ALLOCATE(DstParamData%FFAvgData(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FFAvgData.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%FFAvgData = SrcParamData%FFAvgData ENDIF DstParamData%FFDTime = SrcParamData%FFDTime DstParamData%FFRate = SrcParamData%FFRate @@ -385,6 +418,8 @@ SUBROUTINE IfW_FFWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, DstParamData%VLinShr = SrcParamData%VLinShr DstParamData%HLinShr = SrcParamData%HLinShr DstParamData%RefLength = SrcParamData%RefLength + DstParamData%BoxExceedAllowF = SrcParamData%BoxExceedAllowF + DstParamData%BoxExceedAllowIdx = SrcParamData%BoxExceedAllowIdx END SUBROUTINE IfW_FFWind_CopyParam SUBROUTINE IfW_FFWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -413,6 +448,9 @@ SUBROUTINE IfW_FFWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointe ENDIF IF (ALLOCATED(ParamData%FFTower)) THEN DEALLOCATE(ParamData%FFTower) +ENDIF +IF (ALLOCATED(ParamData%FFAvgData)) THEN + DEALLOCATE(ParamData%FFAvgData) ENDIF END SUBROUTINE IfW_FFWind_DestroyParam @@ -462,6 +500,11 @@ SUBROUTINE IfW_FFWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er IF ( ALLOCATED(InData%FFTower) ) THEN Int_BufSz = Int_BufSz + 2*3 ! FFTower upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%FFTower) ! FFTower + END IF + Int_BufSz = Int_BufSz + 1 ! FFAvgData allocated yes/no + IF ( ALLOCATED(InData%FFAvgData) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! FFAvgData upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%FFAvgData) ! FFAvgData END IF Re_BufSz = Re_BufSz + 1 ! FFDTime Re_BufSz = Re_BufSz + 1 ! FFRate @@ -488,6 +531,8 @@ SUBROUTINE IfW_FFWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_BufSz = Re_BufSz + 1 ! VLinShr Re_BufSz = Re_BufSz + 1 ! HLinShr Re_BufSz = Re_BufSz + 1 ! RefLength + Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowF + Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowIdx IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -573,6 +618,31 @@ SUBROUTINE IfW_FFWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END DO END DO END DO + END IF + IF ( .NOT. ALLOCATED(InData%FFAvgData) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FFAvgData,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFAvgData,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FFAvgData,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFAvgData,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%FFAvgData,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFAvgData,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%FFAvgData,3), UBOUND(InData%FFAvgData,3) + DO i2 = LBOUND(InData%FFAvgData,2), UBOUND(InData%FFAvgData,2) + DO i1 = LBOUND(InData%FFAvgData,1), UBOUND(InData%FFAvgData,1) + ReKiBuf(Re_Xferred) = InData%FFAvgData(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO END IF ReKiBuf(Re_Xferred) = InData%FFDTime Re_Xferred = Re_Xferred + 1 @@ -624,6 +694,10 @@ SUBROUTINE IfW_FFWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%RefLength Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedAllowF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BoxExceedAllowIdx + Int_Xferred = Int_Xferred + 1 END SUBROUTINE IfW_FFWind_PackParam SUBROUTINE IfW_FFWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -720,6 +794,34 @@ SUBROUTINE IfW_FFWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, END DO END DO END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FFAvgData not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%FFAvgData)) DEALLOCATE(OutData%FFAvgData) + ALLOCATE(OutData%FFAvgData(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FFAvgData.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%FFAvgData,3), UBOUND(OutData%FFAvgData,3) + DO i2 = LBOUND(OutData%FFAvgData,2), UBOUND(OutData%FFAvgData,2) + DO i1 = LBOUND(OutData%FFAvgData,1), UBOUND(OutData%FFAvgData,1) + OutData%FFAvgData(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO END IF OutData%FFDTime = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 @@ -771,6 +873,10 @@ SUBROUTINE IfW_FFWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = Re_Xferred + 1 OutData%RefLength = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%BoxExceedAllowF = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedAllowF) + Int_Xferred = Int_Xferred + 1 + OutData%BoxExceedAllowIdx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE IfW_FFWind_UnPackParam END MODULE IfW_FFWind_Base_Types diff --git a/modules/inflowwind/src/IfW_HAWCWind.f90 b/modules/inflowwind/src/IfW_HAWCWind.f90 index c903ee66a6..a8f6b3aa82 100644 --- a/modules/inflowwind/src/IfW_HAWCWind.f90 +++ b/modules/inflowwind/src/IfW_HAWCWind.f90 @@ -145,6 +145,21 @@ SUBROUTINE IfW_HAWCWind_Init(InitInp, p, MiscVars, Interval, InitOut, ErrStat, E if (InitInp%FF%ScaleMethod /= ScaleMethod_None) call SubtractMeanVelocity(p%FF%FFData) if (.not. p%FF%AddMeanAfterInterp) call AddMeanVelocity(InitInp%FF, p%FF%GridBase, 1.0_ReKi/p%FF%InvFFZD, 1.0_ReKi/p%FF%InvFFYD, p%FF%FFData) + + !------------------------------------------------------------------------------------------------- + ! Set box exceedence averaging grid + !------------------------------------------------------------------------------------------------- + + p%FF%BoxExceedAllowF = InitInp%FF%BoxExceedAllowF + p%FF%BoxExceedAllowIdx = InitInp%FF%BoxExceedAllowIdx + + if ( p%FF%BoxExceedAllowF ) then + call GenMeanGridProfileTimeSeries( p%FF, TmpErrStat, TmpErrMsg ) + call SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if ( ErrStat >= AbortErrLev ) return + endif + + !------------------------------------------------------------------------------------------------- ! write info to summary file, if necessary !------------------------------------------------------------------------------------------------- @@ -165,6 +180,20 @@ SUBROUTINE IfW_HAWCWind_Init(InitInp, p, MiscVars, Interval, InitOut, ErrStat, E TRIM(Num2LStr(-p%FF%FFYHWid))//' : '//TRIM(Num2LStr(p%FF%FFYHWid))//' ]' WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Z range (m): [ '// & TRIM(Num2LStr(p%FF%GridBase))//' : '//TRIM(Num2LStr(p%FF%GridBase + p%FF%FFZHWid*2.0))//' ]' + + IF ( p%FF%BoxExceedAllowF ) THEN + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Wind grid exceedence allowed: '// & + 'True -- Only for points requested by OLAF free vortex wake, or LidarSim module' + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' '// & + ' Out of bounds values are linearly interpolated to mean at Z loction for' + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' '// & + ' given timestep and X,T value. Values above grid are held to top of wind' + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' '// & + ' grid value' + ELSE + WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Wind grid exceedence allowed: '// & + 'False' + ENDIF WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) 'Scaling factors used:' WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' u v w ' diff --git a/modules/inflowwind/src/IfW_HAWCWind.txt b/modules/inflowwind/src/IfW_HAWCWind.txt index 1d45291817..41fa813893 100644 --- a/modules/inflowwind/src/IfW_HAWCWind.txt +++ b/modules/inflowwind/src/IfW_HAWCWind.txt @@ -22,7 +22,7 @@ typedef ^ ^ IntKi typedef ^ ^ ReKi dx - 0 - "size of grids in the x direction (in the 3 files above)" - typedef ^ ^ ReKi dy - 0 - "size of grids in the y direction (in the 3 files above)" - typedef ^ ^ ReKi dz - 0 - "size of grids in the z direction (in the 3 files above)" - -typedef ^ ^ IfW_FFWind_InitInputType FF - - - "scaling data" - +typedef ^ ^ IfW_FFWind_InitInputType FF - - - "scaling data and wind box exceedence flags" - # Init Output diff --git a/modules/inflowwind/src/IfW_HAWCWind_Types.f90 b/modules/inflowwind/src/IfW_HAWCWind_Types.f90 index 126947f674..cbbadbd6d7 100644 --- a/modules/inflowwind/src/IfW_HAWCWind_Types.f90 +++ b/modules/inflowwind/src/IfW_HAWCWind_Types.f90 @@ -44,7 +44,7 @@ MODULE IfW_HAWCWind_Types REAL(ReKi) :: dx = 0 !< size of grids in the x direction (in the 3 files above) [-] REAL(ReKi) :: dy = 0 !< size of grids in the y direction (in the 3 files above) [-] REAL(ReKi) :: dz = 0 !< size of grids in the z direction (in the 3 files above) [-] - TYPE(IfW_FFWind_InitInputType) :: FF !< scaling data [-] + TYPE(IfW_FFWind_InitInputType) :: FF !< scaling data and wind box exceedence flags [-] END TYPE IfW_HAWCWind_InitInputType ! ======================= ! ========= IfW_HAWCWind_InitOutputType ======= diff --git a/modules/inflowwind/src/IfW_TSFFWind.f90 b/modules/inflowwind/src/IfW_TSFFWind.f90 index 77bcf5c4c8..9be1015599 100644 --- a/modules/inflowwind/src/IfW_TSFFWind.f90 +++ b/modules/inflowwind/src/IfW_TSFFWind.f90 @@ -169,6 +169,20 @@ SUBROUTINE IfW_TSFFWind_Init(InitData, ParamData, MiscVars, InitOutData, ErrStat ENDIF + !------------------------------------------------------------------------------------------------- + ! Set box exceedence averaging grid + !------------------------------------------------------------------------------------------------- + + ParamData%FF%BoxExceedAllowF = InitData%FF%BoxExceedAllowF + ParamData%FF%BoxExceedAllowIdx = InitData%FF%BoxExceedAllowIdx + + if ( ParamData%FF%BoxExceedAllowF ) then + call GenMeanGridProfileTimeSeries( ParamData%FF, TmpErrStat, TmpErrMsg ) + call SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + if ( ErrStat >= AbortErrLev ) return + endif + + !------------------------------------------------------------------------------------------------- ! Set the InitOutput information !------------------------------------------------------------------------------------------------- @@ -561,6 +575,20 @@ SUBROUTINE Read_TurbSim_FF(UnitWind, ErrStat, ErrMsg) TRIM(Num2LStr(ParamData%FF%RefHt - ParamData%FF%FFZHWid))//' : '//TRIM(Num2LStr(ParamData%FF%RefHt + ParamData%FF%FFZHWid))//' ]' ENDIF + IF ( ParamData%FF%BoxExceedAllowF ) THEN + WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Wind grid exceedence allowed: '// & + 'True -- Only for points requested by OLAF free vortex wake, or LidarSim module' + WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' '// & + ' Out of bounds values are linearly interpolated to mean at Z loction for' + WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' '// & + ' given timestep and X,T value. Values above grid are held to top of wind' + WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' '// & + ' grid value' + ELSE + WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Wind grid exceedence allowed: '// & + 'False' + ENDIF + ! We are assuming that if the last line was written ok, then all of them were. IF (TmpErrStat /= 0_IntKi) THEN diff --git a/modules/inflowwind/src/IfW_TSFFWind.txt b/modules/inflowwind/src/IfW_TSFFWind.txt index 71b9e9c753..2d5e88d81a 100644 --- a/modules/inflowwind/src/IfW_TSFFWind.txt +++ b/modules/inflowwind/src/IfW_TSFFWind.txt @@ -13,8 +13,9 @@ usefrom IfW_FFWind_Base.txt ######################### -typedef IfW_TSFFWind/IfW_TSFFWind InitInputType CHARACTER(1024) WindFileName - - - "Name of the wind file to use" - -typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - +typedef IfW_TSFFWind/IfW_TSFFWind InitInputType CHARACTER(1024) WindFileName - - - "Name of the wind file to use" - +typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - +typedef ^ ^ IfW_FFWind_InitInputType FF - - - "scaling data and wind box exceedence flags" - # Init Output diff --git a/modules/inflowwind/src/IfW_TSFFWind_Types.f90 b/modules/inflowwind/src/IfW_TSFFWind_Types.f90 index 5f52f9c1c9..b142f61a67 100644 --- a/modules/inflowwind/src/IfW_TSFFWind_Types.f90 +++ b/modules/inflowwind/src/IfW_TSFFWind_Types.f90 @@ -38,6 +38,7 @@ MODULE IfW_TSFFWind_Types TYPE, PUBLIC :: IfW_TSFFWind_InitInputType CHARACTER(1024) :: WindFileName !< Name of the wind file to use [-] INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file (-1 for none). Provided by IfW. [-] + TYPE(IfW_FFWind_InitInputType) :: FF !< scaling data and wind box exceedence flags [-] END TYPE IfW_TSFFWind_InitInputType ! ======================= ! ========= IfW_TSFFWind_InitOutputType ======= @@ -72,6 +73,9 @@ SUBROUTINE IfW_TSFFWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlC ErrMsg = "" DstInitInputData%WindFileName = SrcInitInputData%WindFileName DstInitInputData%SumFileUnit = SrcInitInputData%SumFileUnit + CALL IfW_FFWind_CopyInitInput( SrcInitInputData%FF, DstInitInputData%FF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE IfW_TSFFWind_CopyInitInput SUBROUTINE IfW_TSFFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -95,6 +99,8 @@ SUBROUTINE IfW_TSFFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLO DEALLOCATEpointers_local = .true. END IF + CALL IfW_FFWind_DestroyInitInput( InitInputData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE IfW_TSFFWind_DestroyInitInput SUBROUTINE IfW_TSFFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -134,6 +140,24 @@ SUBROUTINE IfW_TSFFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt Int_BufSz = 0 Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName Int_BufSz = Int_BufSz + 1 ! SumFileUnit + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype + CALL IfW_FFWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -167,6 +191,34 @@ SUBROUTINE IfW_TSFFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSt END DO ! I IntKiBuf(Int_Xferred) = InData%SumFileUnit Int_Xferred = Int_Xferred + 1 + CALL IfW_FFWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF END SUBROUTINE IfW_TSFFWind_PackInitInput SUBROUTINE IfW_TSFFWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -201,6 +253,46 @@ SUBROUTINE IfW_TSFFWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Er END DO ! I OutData%SumFileUnit = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FFWind_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE IfW_TSFFWind_UnPackInitInput SUBROUTINE IfW_TSFFWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 3932cced26..1e91ccc9cb 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -482,6 +482,13 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, TSFF_InitData%WindFileName = InputFileData%TSFF_FileName TSFF_InitData%SumFileUnit = SumFileUnit + ! Set flags for box exceedence (FVW and Lidar only) + TSFF_InitData%FF%BoxExceedAllowF = InitInp%BoxExceedAllowF + TSFF_InitData%FF%BoxExceedAllowIdx = huge(1_IntKi) + if (InitInp%BoxExceedAllowF .and. ( InitInp%BoxExceedAllowIdx <= InitInp%NumWindPoints )) then + TSFF_InitData%FF%BoxExceedAllowIdx = InitInp%BoxExceedAllowIdx + endif + ! Initialize the TSFFWind module CALL IfW_TSFFWind_Init(TSFF_InitData, p%TSFFWind, & m%TSFFWind, TSFF_InitOutData, TmpErrStat, TmpErrMsg) @@ -523,6 +530,13 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, BladedFF_InitData%NativeBladedFmt = .true. !call IfW_FFWind_CopyInitInput( InputFileData%FF, BladedFF_InitData%FF, MESH_NEWCOPY, TmpErrStat, TmpErrMsg) end if + + ! Set flags for box exceedence (FVW and Lidar only) + BladedFF_InitData%FF%BoxExceedAllowF = InitInp%BoxExceedAllowF + BladedFF_InitData%FF%BoxExceedAllowIdx = huge(1_IntKi) + if (InitInp%BoxExceedAllowF .and. ( InitInp%BoxExceedAllowIdx <= InitInp%NumWindPoints )) then + BladedFF_InitData%FF%BoxExceedAllowIdx = InitInp%BoxExceedAllowIdx + endif ! Initialize the BladedFFWind module CALL IfW_BladedFFWind_Init(BladedFF_InitData, p%BladedFFWind, m%BladedFFWind, & @@ -565,6 +579,13 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, HAWC_InitData%dy = InputFileData%HAWC_dy HAWC_InitData%dz = InputFileData%HAWC_dz + ! Set flags for box exceedence (FVW and Lidar only) + HAWC_InitData%FF%BoxExceedAllowF = InitInp%BoxExceedAllowF + HAWC_InitData%FF%BoxExceedAllowIdx = huge(1_IntKi) + if (InitInp%BoxExceedAllowF .and. ( InitInp%BoxExceedAllowIdx <= InitInp%NumWindPoints )) then + HAWC_InitData%FF%BoxExceedAllowIdx = InitInp%BoxExceedAllowIdx + endif + call IfW_FFWind_CopyInitInput( InputFileData%FF, HAWC_InitData%FF, MESH_NEWCOPY, TmpErrStat, TmpErrMsg) diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 7223cb9c89..5576c8fc24 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -114,6 +114,8 @@ typedef ^ ^ FileInfoType WindType2Da typedef ^ ^ Lidar_InitInputType lidar - - - "InitInput for lidar data" - typedef ^ ^ IfW_4Dext_InitInputType FDext - - - "InitInput for 4D external wind data" - typedef ^ ^ ReKi RadAvg - - - "Radius (from hub) used for averaging wind speed" - +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)" - # Init Output diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index 1e4eb17aa1..9732eb36a9 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -130,6 +130,8 @@ MODULE InflowWind_Types TYPE(Lidar_InitInputType) :: lidar !< InitInput for lidar data [-] TYPE(IfW_4Dext_InitInputType) :: FDext !< InitInput for 4D external wind data [-] REAL(ReKi) :: RadAvg !< Radius (from hub) used for averaging wind speed [-] + 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) [-] END TYPE InflowWind_InitInputType ! ======================= ! ========= InflowWind_InitOutputType ======= @@ -1206,6 +1208,8 @@ SUBROUTINE InflowWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCod CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN DstInitInputData%RadAvg = SrcInitInputData%RadAvg + DstInitInputData%BoxExceedAllowIdx = SrcInitInputData%BoxExceedAllowIdx + DstInitInputData%BoxExceedAllowF = SrcInitInputData%BoxExceedAllowF END SUBROUTINE InflowWind_CopyInitInput SUBROUTINE InflowWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -1353,6 +1357,8 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat DEALLOCATE(Int_Buf) END IF Re_BufSz = Re_BufSz + 1 ! RadAvg + Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowIdx + Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1516,6 +1522,10 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat ENDIF ReKiBuf(Re_Xferred) = InData%RadAvg Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BoxExceedAllowIdx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedAllowF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_PackInitInput SUBROUTINE InflowWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1728,6 +1738,10 @@ SUBROUTINE InflowWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) OutData%RadAvg = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%BoxExceedAllowIdx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%BoxExceedAllowF = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedAllowF) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_UnPackInitInput SUBROUTINE InflowWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) From 23f8a1cc955474830851de97f3b02f78a8f310c0 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 1 Sep 2021 18:34:31 -0600 Subject: [PATCH 16/51] IfW: rearrange FFWind_Interp routine Needed to simplify the routine a bit for adding the GridExceedence options --- modules/inflowwind/src/IfW_FFWind_Base.f90 | 433 ++++++++++----------- 1 file changed, 205 insertions(+), 228 deletions(-) diff --git a/modules/inflowwind/src/IfW_FFWind_Base.f90 b/modules/inflowwind/src/IfW_FFWind_Base.f90 index f9db8ce937..959003f421 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base.f90 +++ b/modules/inflowwind/src/IfW_FFWind_Base.f90 @@ -179,8 +179,8 @@ FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) REAL(ReKi) :: ZGRID REAL(ReKi) :: N(8) ! array for holding scaling factors for the interpolation algorithm REAL(ReKi) :: u(8) ! array for holding the corner values for the interpolation algorithm across a cubic volume - REAL(ReKi) :: M(4) ! array for holding scaling factors for the interpolation algorithm - REAL(ReKi) :: v(4) ! array for holding the corner values for the interpolation algorithm across an area + REAL(ReKi) :: M(4) ! array for holding scaling factors for the interpolation algorithm -- 4 point method for tower interp + REAL(ReKi) :: v(4) ! array for holding the corner values for the interpolation algorithm across an area -- 4 point method for tower interp INTEGER(IntKi) :: IDIM INTEGER(IntKi) :: ITHI @@ -200,175 +200,32 @@ FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" - - - !------------------------------------------------------------------------------------------------- - ! By definition, wind below the ground is always zero (no turbulence, either). - !------------------------------------------------------------------------------------------------- - IF ( Position(3) <= 0.0_ReKi ) THEN - FFWind_Interp = 0.0_ReKi - RETURN - END IF - + !------------------------------------------------------------------------------------------------- - ! Find the bounding time slices. + ! By definition, wind below the ground is always zero (no turbulence, either). !------------------------------------------------------------------------------------------------- - - ! Perform the time shift. At time=0, a point half the grid width downstream (p%FFYHWid) will index into the zero time slice. - ! If we did not do this, any point downstream of the tower at the beginning of the run would index outside of the array. - ! This all assumes the grid width is at least as large as the rotor. If it isn't, then the interpolation will not work. - - - TimeShifted = TIME + ( p%InitXPosition - Position(1) )*p%InvMFFWS ! in distance, X: InputInfo%Position(1) - p%InitXPosition - TIME*p%MeanFFWS - - - IF ( p%Periodic ) THEN ! translate TimeShifted to ( 0 <= TimeShifted < p%TotalTime ) - - TimeShifted = MODULO( TimeShifted, p%TotalTime ) - ! If TimeShifted is a very small negative number, modulo returns the incorrect value due to internal rounding errors. - ! See bug report #471 - IF (TimeShifted == p%TotalTime) TimeShifted = 0.0_ReKi - - TGRID = TimeShifted*p%FFRate - ITLO = INT( TGRID ) ! convert REAL to INTEGER (add 1 later because our grids start at 1, not 0) - T = 2.0_ReKi * ( TGRID - REAL(ITLO, ReKi) ) - 1.0_ReKi ! a value between -1 and 1 that indicates a relative position between ITLO and ITHI - - ITLO = ITLO + 1 - IF ( ITLO == p%NFFSteps ) THEN - ITHI = 1 - ELSE - IF (ITLO > p%NFFSteps) ITLO = 1 - ITHI = ITLO + 1 - ENDIF - - - ELSE - - TGRID = TimeShifted*p%FFRate - ITLO = INT( TGRID ) ! convert REAL to INTEGER (add 1 later because our grids start at 1, not 0) - T = 2.0_ReKi * ( TGRID - REAL(ITLO, ReKi) ) - 1.0_ReKi ! a value between -1 and 1 that indicates a relative position between ITLO and ITHI - - ITLO = ITLO + 1 ! add one since our grids start at 1, not 0 - ITHI = ITLO + 1 - - IF ( ITLO >= p%NFFSteps .OR. ITLO < 1 ) THEN - IF ( ITLO == p%NFFSteps ) THEN - ITHI = ITLO - IF ( T <= TOL ) THEN ! we're on the last point - T = -1.0_ReKi - ELSE ! We'll extrapolate one dt past the last value in the file - ITLO = ITHI - 1 - ENDIF - ELSE - ErrMsg = ' Error: FF wind array was exhausted at '//TRIM( Num2LStr( REAL( TIME, ReKi ) ) )// & - ' seconds (trying to access data at '//TRIM( Num2LStr( REAL( TimeShifted, ReKi ) ) )//' seconds).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ENDIF - - ENDIF + IF ( Position(3) <= 0.0_ReKi ) RETURN !------------------------------------------------------------------------------------------------- - ! Find the bounding rows for the Z position. [The lower-left corner is (1,1) when looking upwind.] + ! get the bounding limits for T and Z !------------------------------------------------------------------------------------------------- + call GetTBounds(); if (ErrStat >= AbortErrLev) return + call GetZBounds(); if (ErrStat >= AbortErrLev) return - ZGRID = ( Position(3) - p%GridBase )*p%InvFFZD - - IF (ZGRID > -1*TOL) THEN - OnGrid = .TRUE. - - ! Index for start and end slices - IZLO = INT( ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - IZHI = IZLO + 1 - - ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. - ! Subtract 1_IntKi from Z since the indices are starting at 1, not 0 - Z = 2.0_ReKi * (ZGRID - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi - - IF ( IZLO < 1 ) THEN - IF ( IZLO == 0 .AND. Z >= 1.0-TOL ) THEN - Z = -1.0_ReKi - IZLO = 1 - ELSE - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& - TRIM(Num2LStr(Position(3)))//' m is below the grid).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ELSEIF ( IZLO >= p%NZGrids ) THEN - IF ( IZLO == p%NZGrids .AND. Z <= TOL ) THEN - Z = -1.0_ReKi - IZHI = IZLO ! We're right on the last point, which is still okay - ELSE - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& - TRIM(Num2LStr(Position(3)))//' m is above the grid).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ENDIF - - ELSE - - OnGrid = .FALSE. ! this is on the tower - - IF (p%InterpTower) then - - ! get Z between ground and bottom of grid - ZGRID = Position(3)/p%GridBase - Z = 2.0_ReKi * ZGRID - 1.0_ReKi - IZHI = 1 - IZLO = 0 - - IF ( ZGRID < 0.0_ReKi ) THEN - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & - '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the ground).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - - ELSE - - IF ( p%NTGrids < 1) THEN - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & - '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - - IZLO = INT( -1.0*ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - - - IF ( IZLO >= p%NTGrids ) THEN !our dz is the difference between the bottom tower point and the ground - IZLO = p%NTGrids - - ! Check that this isn't zero. Value between -1 and 1 corresponding to the relative position. - Z = 1.0_ReKi - 2.0_ReKi * (Position(3) / (p%GridBase - REAL(IZLO - 1_IntKi, ReKi)/p%InvFFZD)) - - ELSE - - ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. Used in the interpolation. - Z = 2.0_ReKi * (ABS(ZGRID) - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi - - ENDIF - IZHI = IZLO + 1 - - ENDIF - - END IF + !------------------------------------------------------------------------------------------------- + ! Calculate the value + !------------------------------------------------------------------------------------------------- IF ( OnGrid ) THEN ! The tower points don't use this - CALL GetInterpValues(); if (ErrStat/=ErrID_None) return - - !------------------------------------------------------------------------------------------------- - ! Interpolate on the grid - !------------------------------------------------------------------------------------------------- + call GetYBounds(); if (ErrStat >= AbortErrLev) return + call GetInterpWeights3D(); + !-------------------------------------------------------- + ! Interpolate on the grid DO IDIM=1,p%NFFComp ! all the components - u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) u(2) = p%FFData( IZHI, IYHI, IDIM, ITLO ) u(3) = p%FFData( IZLO, IYHI, IDIM, ITLO ) @@ -377,54 +234,36 @@ FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) u(6) = p%FFData( IZHI, IYHI, IDIM, ITHI ) u(7) = p%FFData( IZLO, IYHI, IDIM, ITHI ) u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) - - FFWind_Interp(IDIM) = SUM ( N * u ) - + FFWind_Interp(IDIM) = SUM ( N * u ) END DO !IDIM ELSE IF (p%InterpTower) THEN - - CALL GetInterpValues(); if (ErrStat >= AbortErrLev) return - - !------------------------------------------------------------------------------------------------- - ! Interpolate on the bottom of the grid to the ground - !------------------------------------------------------------------------------------------------- + !----------------------------------------------------- + ! Interpolate on the bottom of the grid to the ground + ! ground points set to zero + call GetYBounds(); if (ErrStat >= AbortErrLev) return + call GetInterpWeights3D(); DO IDIM=1,p%NFFComp ! all the components - u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) u(2) = p%FFData( IZHI, IYHI, IDIM, ITLO ) - u(3) = 0.0_ReKi !p%FFData( IZLO, IYHI, IDIM, ITLO ) - u(4) = 0.0_ReKi !p%FFData( IZLO, IYLO, IDIM, ITLO ) + u(3) = 0.0_ReKi ! ground + u(4) = 0.0_ReKi ! ground u(5) = p%FFData( IZHI, IYLO, IDIM, ITHI ) u(6) = p%FFData( IZHI, IYHI, IDIM, ITHI ) - u(7) = 0.0_ReKi !p%FFData( IZLO, IYHI, IDIM, ITHI ) - u(8) = 0.0_ReKi !p%FFData( IZLO, IYLO, IDIM, ITHI ) - - FFWind_Interp(IDIM) = SUM ( N * u ) - - END DO !IDIM - + u(7) = 0.0_ReKi ! ground + u(8) = 0.0_ReKi ! ground + FFWind_Interp(IDIM) = SUM ( N * u ) + END DO !IDIM ELSE - - !------------------------------------------------------------------------------------------------- - ! Interpolate on the tower array - !------------------------------------------------------------------------------------------------- - ! Setup the scaling factors. Set the unused portion of the array to zero - M(1) = ( 1.0_ReKi + Z )*( 1.0_ReKi - T ) - M(2) = ( 1.0_ReKi + Z )*( 1.0_ReKi + T ) - M(3) = ( 1.0_ReKi - Z )*( 1.0_ReKi - T ) - M(4) = ( 1.0_ReKi - Z )*( 1.0_ReKi + T ) - M = M / 4.0_ReKi ! normalize - + !----------------------------------------------------- + ! Interpolate on the tower array (no y bounds) + call GetInterpWeightsPlane(); DO IDIM=1,p%NFFComp ! all the components - - !---------------------------------------------------------------------------------------------- ! Interpolate between the two times using an area interpolation. - !---------------------------------------------------------------------------------------------- IF (IZHI > p%NTGrids) THEN v(1) = 0.0_ReKi ! on the ground @@ -433,57 +272,185 @@ FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) v(1) = p%FFTower( IDIM, IZHI, ITLO ) v(2) = p%FFTower( IDIM, IZHI, ITHI ) END IF - + v(3) = p%FFTower( IDIM, IZLO, ITLO ) v(4) = p%FFTower( IDIM, IZLO, ITHI ) - - FFWind_Interp(IDIM) = SUM ( M * v ) - + FFWind_Interp(IDIM) = SUM ( M * v ) END DO !IDIM - END IF ! Interpolate below the grid - ENDIF ! OnGrid + RETURN -CONTAINS - SUBROUTINE GetInterpValues() - - !------------------------------------------------------------------------------------------------- - ! Find the bounding columns for the Y position. [The lower-left corner is (1,1) when looking upwind.] - !------------------------------------------------------------------------------------------------- +CONTAINS - YGRID = ( Position(2) + p%FFYHWid )*p%InvFFYD ! really, it's (Position(2) - -1.0*p%FFYHWid) + !------------------------------------------------------------------------------------------------- + !> Find the bounding time slices. + !! Perform the time shift. At time=0, a point half the grid width downstream (p%FFYHWid) will index into the zero time slice. + !! If we did not do this, any point downstream of the tower at the beginning of the run would index outside of the array. + !! This all assumes the grid width is at least as large as the rotor. If it isn't, then the interpolation will not work. + SUBROUTINE GetTBounds() - IYLO = INT( YGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - IYHI = IYLO + 1 + TimeShifted = TIME + ( p%InitXPosition - Position(1) )*p%InvMFFWS ! in distance, X: InputInfo%Position(1) - p%InitXPosition - TIME*p%MeanFFWS - ! Set Y as a value between -1 and 1 for the relative location between IYLO and IYHI. Used in the interpolation. - ! Subtract 1_IntKi from IYLO since grids start at index 1, not 0 - Y = 2.0_ReKi * (YGRID - REAL(IYLO - 1_IntKi, ReKi)) - 1.0_ReKi + IF ( p%Periodic ) THEN ! translate TimeShifted to ( 0 <= TimeShifted < p%TotalTime ) - IF ( IYLO >= p%NYGrids .OR. IYLO < 1 ) THEN - IF ( IYLO == 0 .AND. Y >= 1.0-TOL ) THEN - Y = -1.0_ReKi - IYLO = 1 - ELSE IF ( IYLO == p%NYGrids .AND. Y <= TOL ) THEN - Y = -1.0_ReKi - IYHI = IYLO ! We're right on the last point, which is still okay + TimeShifted = MODULO( TimeShifted, p%TotalTime ) + ! If TimeShifted is a very small negative number, modulo returns the incorrect value due to internal rounding errors. + IF (TimeShifted == p%TotalTime) TimeShifted = 0.0_ReKi + + TGRID = TimeShifted*p%FFRate + ITLO = INT( TGRID ) ! convert REAL to INTEGER (add 1 later because our grids start at 1, not 0) + T = 2.0_ReKi * ( TGRID - REAL(ITLO, ReKi) ) - 1.0_ReKi ! a value between -1 and 1 that indicates a relative position between ITLO and ITHI + + ITLO = ITLO + 1 + IF ( ITLO == p%NFFSteps ) THEN + ITHI = 1 + ELSE + IF (ITLO > p%NFFSteps) ITLO = 1 + ITHI = ITLO + 1 + ENDIF + + ELSE + + TGRID = TimeShifted*p%FFRate + ITLO = INT( TGRID ) ! convert REAL to INTEGER (add 1 later because our grids start at 1, not 0) + T = 2.0_ReKi * ( TGRID - REAL(ITLO, ReKi) ) - 1.0_ReKi ! a value between -1 and 1 that indicates a relative position between ITLO and ITHI + + ITLO = ITLO + 1 ! add one since our grids start at 1, not 0 + ITHI = ITLO + 1 + + IF ( ITLO >= p%NFFSteps .OR. ITLO < 1 ) THEN + IF ( ITLO == p%NFFSteps ) THEN + ITHI = ITLO + IF ( T <= TOL ) THEN ! we're on the last point + T = -1.0_ReKi + ELSE ! We'll extrapolate one dt past the last value in the file + ITLO = ITHI - 1 + ENDIF ELSE - ErrMsg = ' FF wind array boundaries violated: Grid too small in Y direction. Y='// & - TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*p%FFYHWid))// & - ', '//TRIM(Num2LStr(p%FFYHWid))//']' - ErrStat = ErrID_Fatal ! we don't return anything + ErrMsg = ' Error: FF wind array was exhausted at '//TRIM( Num2LStr( REAL( TIME, ReKi ) ) )// & + ' seconds (trying to access data at '//TRIM( Num2LStr( REAL( TimeShifted, ReKi ) ) )//' seconds).' + ErrStat = ErrID_Fatal RETURN ENDIF ENDIF - - !------------------------------------------------------------------------------------------------- - ! Get normalization values for 3d-linear interpolation on the grid - !------------------------------------------------------------------------------------------------- - -!New Algorithm here + + ENDIF + END SUBROUTINE GetTBounds + + !------------------------------------------------------------------------------------------------- + !> Find the bounding rows for the Z position. [The lower-left corner is (1,1) when looking upwind.] + SUBROUTINE GetZBounds() + + ZGRID = ( Position(3) - p%GridBase )*p%InvFFZD + + IF (ZGRID > -1*TOL) THEN + OnGrid = .TRUE. + + ! Index for start and end slices + IZLO = INT( ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 + IZHI = IZLO + 1 + + ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. + ! Subtract 1_IntKi from Z since the indices are starting at 1, not 0 + Z = 2.0_ReKi * (ZGRID - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi + + IF ( IZLO < 1 ) THEN + IF ( IZLO == 0 .AND. Z >= 1.0-TOL ) THEN + Z = -1.0_ReKi + IZLO = 1 + ELSE + ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& + TRIM(Num2LStr(Position(3)))//' m is below the grid).' + ErrStat = ErrID_Fatal + RETURN + ENDIF + ELSEIF ( IZLO >= p%NZGrids ) THEN + IF ( IZLO == p%NZGrids .AND. Z <= TOL ) THEN + Z = -1.0_ReKi + IZHI = IZLO ! We're right on the last point, which is still okay + ELSE + ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& + TRIM(Num2LStr(Position(3)))//' m is above the grid).' + ErrStat = ErrID_Fatal + RETURN + ENDIF + ENDIF + + ELSE + + OnGrid = .FALSE. ! this is on the tower + + IF (p%InterpTower) then + ! get Z between ground and bottom of grid + ZGRID = Position(3)/p%GridBase + Z = 2.0_ReKi * ZGRID - 1.0_ReKi + IZHI = 1 + IZLO = 0 + + IF ( ZGRID < 0.0_ReKi ) THEN + ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & + '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the ground).' + ErrStat = ErrID_Fatal + RETURN + ENDIF + ELSE + IF ( p%NTGrids < 1) THEN + ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & + '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' + ErrStat = ErrID_Fatal + RETURN + ENDIF + + IZLO = INT( -1.0*ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 + + IF ( IZLO >= p%NTGrids ) THEN !our dz is the difference between the bottom tower point and the ground + IZLO = p%NTGrids + ! Check that this isn't zero. Value between -1 and 1 corresponding to the relative position. + Z = 1.0_ReKi - 2.0_ReKi * (Position(3) / (p%GridBase - REAL(IZLO - 1_IntKi, ReKi)/p%InvFFZD)) + ELSE + ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. Used in the interpolation. + Z = 2.0_ReKi * (ABS(ZGRID) - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi + ENDIF + IZHI = IZLO + 1 + ENDIF + END IF + END SUBROUTINE GetZBounds + + !------------------------------------------------------------------------------------------------- + !> Find the bounding columns for the Y position. [The lower-left corner is (1,1) when looking upwind.] + SUBROUTINE GetYBounds() + + YGRID = ( Position(2) + p%FFYHWid )*p%InvFFYD ! really, it's (Position(2) - -1.0*p%FFYHWid) + IYLO = INT( YGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 + IYHI = IYLO + 1 + + ! Set Y as a value between -1 and 1 for the relative location between IYLO and IYHI. Used in the interpolation. + ! Subtract 1_IntKi from IYLO since grids start at index 1, not 0 + Y = 2.0_ReKi * (YGRID - REAL(IYLO - 1_IntKi, ReKi)) - 1.0_ReKi + + IF ( IYLO >= p%NYGrids .OR. IYLO < 1 ) THEN + IF ( IYLO == 0 .AND. Y >= 1.0-TOL ) THEN + Y = -1.0_ReKi + IYLO = 1 + ELSE IF ( IYLO == p%NYGrids .AND. Y <= TOL ) THEN + Y = -1.0_ReKi + IYHI = IYLO ! We're right on the last point, which is still okay + ELSE + ErrMsg = ' FF wind array boundaries violated: Grid too small in Y direction. Y='// & + TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*p%FFYHWid))// & + ', '//TRIM(Num2LStr(p%FFYHWid))//']' + ErrStat = ErrID_Fatal ! we don't return anything + RETURN + ENDIF + ENDIF + END SUBROUTINE GetYBounds + + !------------------------------------------------------------------------------------------------- + !> Get normalization values for 3d-linear interpolation on the grid + SUBROUTINE GetInterpWeights3D() N(1) = ( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) N(2) = ( 1.0_ReKi + Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) N(3) = ( 1.0_ReKi - Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) @@ -493,9 +460,19 @@ SUBROUTINE GetInterpValues() N(7) = ( 1.0_ReKi - Z )*( 1.0_ReKi + Y )*( 1.0_ReKi + T ) N(8) = ( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) N = N / REAL( SIZE(N), ReKi ) ! normalize - - END SUBROUTINE GetInterpValues + END SUBROUTINE GetInterpWeights3D + + !------------------------------------------------------------------------------------------------- + !> Get normalization values for 3d-linear interpolation on the grid + SUBROUTINE GetInterpWeightsPlane() + M(1) = ( 1.0_ReKi + Z )*( 1.0_ReKi - T ) + M(2) = ( 1.0_ReKi + Z )*( 1.0_ReKi + T ) + M(3) = ( 1.0_ReKi - Z )*( 1.0_ReKi - T ) + M(4) = ( 1.0_ReKi - Z )*( 1.0_ReKi + T ) + M = M / REAL( SIZE(M), ReKi ) ! normalize + END SUBROUTINE GetInterpWeightsPlane END FUNCTION FFWind_Interp + !==================================================================================================== !> This routine is used read scale the full-field turbulence data stored in HAWC format. SUBROUTINE ScaleTurbulence(InitInp, FFData, ScaleFactors, ErrStat, ErrMsg) From d4de507033dc9b1a88230746349e3f2d5ccea7d9 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 29 Sep 2021 09:47:09 -0600 Subject: [PATCH 17/51] IfW: logic for extrapolation of points outside grid Only applies to OLAF free wake points. --- modules/aerodyn/src/AeroDyn.f90 | 17 + modules/inflowwind/src/IfW_FFWind_Base.f90 | 348 +++++++++++++++--- modules/inflowwind/src/InflowWind_Driver.f90 | 3 + .../inflowwind/src/InflowWind_Driver_Subs.f90 | 44 ++- .../src/InflowWind_Driver_Types.f90 | 1 + modules/openfast-library/src/FAST_Subs.f90 | 5 + 6 files changed, 345 insertions(+), 73 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index 332ec044b7..3122984819 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -62,6 +62,7 @@ module AeroDyn PUBLIC :: AD_GetOP !< Routine to pack the operating point values (for linearization) into arrays PUBLIC :: AD_NumWindPoints !< Routine to return then number of windpoints required by AeroDyn + PUBLIC :: AD_BoxExceedPointsIdx !< Routine to set the start of the OLAF wind points PUBLIC :: AD_GetExternalWind !< Set the external wind into AeroDyn inputs PUBLIC :: AD_SetExternalWindPositions !< Set the external wind points needed by AeroDyn inputs @@ -7003,6 +7004,22 @@ integer(IntKi) function AD_NumWindPoints(u_AD, o_AD) result(n) end if end function AD_NumWindPoints !---------------------------------------------------------------------------------------------------------------------------------- +!> Start index of the OLAF wind points for this turbine +!! Should respect the order of AD_GetExternalWind and AD_SetExternalWindPositions +integer(IntKi) function AD_BoxExceedPointsIdx(u_AD, o_AD) result(n) + type(AD_InputType), intent(in ) :: u_AD ! AeroDyn data + type(AD_OtherStateType), intent(in ) :: o_AD ! AeroDyn data + ! locals + integer(IntKi) :: k + integer(IntKi) :: TotPts ! call AD_NumWindPts, then subtract + TotPts = AD_NumWindPoints(u_AD, o_AD) + if (allocated(o_AD%WakeLocationPoints)) then + n = TotPts - size(o_AD%WakeLocationPoints, dim=2) + 1 ! start index of the olaf points + else ! No OLAF, so return -1 to indicate not used + n = -1 + endif +end function AD_BoxExceedPointsIdx +!---------------------------------------------------------------------------------------------------------------------------------- !> Sets the wind calculated by InflowWind into the AeroDyn arrays ("InputSolve_IfW") !! Should respect the order of AD_NumWindPoints and AD_SetExternalWindPositions subroutine AD_GetExternalWind(u_AD, VelUVW, node, errStat, errMsg) diff --git a/modules/inflowwind/src/IfW_FFWind_Base.f90 b/modules/inflowwind/src/IfW_FFWind_Base.f90 index 959003f421..16a08c7fa3 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base.f90 +++ b/modules/inflowwind/src/IfW_FFWind_Base.f90 @@ -73,6 +73,7 @@ SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, Velocity, ErrStat, ErrMsg ! local variables INTEGER(IntKi) :: NumPoints ! Number of points specified by the PositionXYZ array + LOGICAL :: GridExceedAllow ! is this point allowed to exceed bounds of wind grid ! local counters INTEGER(IntKi) :: PointNum ! a loop counter for the current point @@ -105,8 +106,23 @@ SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, Velocity, ErrStat, ErrMsg !OMP do private(PointNum, TmpErrStat, TmpErrMsg ) schedule(runtime) DO PointNum = 1, NumPoints + ! is this point allowed beyond the bounds of the wind box? + GridExceedAllow = p%BoxExceedAllowF .and. ( PointNum >= p%BoxExceedAllowIdx ) + +if (isnan(PositionXYZ(1,PointNum)) .or. isnan(PositionXYZ(2,PointNum)) .or. isnan(PositionXYZ(3,PointNum))) then +ErrStat=ErrID_Fatal +if(GridExceedAllow) then +ErrMsg="NaN passed into IfW at "//trim(num2lstr(TIME))//" for PointNum "//trim(num2lstr(PointNum))//" of "//trim(num2lstr(NumPoints))//" with GridExceedAllow = true" +else +ErrMsg="NaN passed into IfW at "//trim(num2lstr(TIME))//" for PointNum "//trim(num2lstr(PointNum))//" of "//trim(num2lstr(NumPoints))//" with GridExceedAllow = fals" +endif +return +endif ! Calculate the velocity for the position - Velocity(:,PointNum) = FFWind_Interp(Time,PositionXYZ(:,PointNum),p,TmpErrStat,TmpErrMsg) + Velocity(:,PointNum) = FFWind_Interp(Time,PositionXYZ(:,PointNum),p,GridExceedAllow,TmpErrStat,TmpErrMsg) +if (TIME > 12.4_DbKi) then +write(23,*) TIME,PointNum,PositionXYZ(:,PointNum),Velocity(:,PointNum) +endif ! Error handling IF (TmpErrStat /= ErrID_None) THEN ! adding this so we don't have to convert numbers to strings every time @@ -153,7 +169,7 @@ END SUBROUTINE IfW_FFWind_CalcOutput !! 09/23/2009 - Modified by B. Jonkman to use arguments instead of modules to determine time and position. !! Height is now relative to the ground !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) +FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, ErrStat, ErrMsg) IMPLICIT NONE @@ -162,6 +178,7 @@ FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) REAL(DbKi), INTENT(IN ) :: Time !< time (s) REAL(ReKi), INTENT(IN ) :: Position(3) !< takes the place of XGrnd, YGrnd, ZGrnd TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters + LOGICAL, INTENT(IN ) :: GridExceedAllow ! is this point allowed to exceed bounds of wind grid REAL(ReKi) :: FFWind_Interp(3) !< The U, V, W velocities INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status @@ -181,6 +198,9 @@ FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) REAL(ReKi) :: u(8) ! array for holding the corner values for the interpolation algorithm across a cubic volume REAL(ReKi) :: M(4) ! array for holding scaling factors for the interpolation algorithm -- 4 point method for tower interp REAL(ReKi) :: v(4) ! array for holding the corner values for the interpolation algorithm across an area -- 4 point method for tower interp + ! Arrays for scaling and corner factors for interpolation in grid exceed case between tower to ground to grid-bottom + REAL(ReKi) :: NGe(10) ! scaling factors + REAL(ReKi) :: uGe(10) ! the corner values INTEGER(IntKi) :: IDIM INTEGER(IntKi) :: ITHI @@ -190,7 +210,28 @@ FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) INTEGER(IntKi) :: IZHI INTEGER(IntKi) :: IZLO - LOGICAL :: OnGrid + LOGICAL :: AboveGridBottom + + !> If GridExceedAllow is true, values for this point will be interpolated between the value at the edge of the grid + !! and the average value over Y for that (X,Z,T) location. This method is not ideal but should yield relatively + !! reasonable results for wake convection (OLAF points) and Lidar measurements far off the grid. A better method of + !! interpolation above the grid using the wind profile would likely be better, but the resulting impact on the + !! physics of the turbine is expected to be limited. + !! + !! For points above the top of the grid, the value is interpolated between the average value for the top of the grid + !! and the closest (X,Y,Z,T) point (interpolated over half grid height span, then held constant over remainder of Z). + !! + !! For points below the top of the grid, the value is interpolated between the Y averaged value for that (X,Z,T) + !! location and the closest (X,Y,Z,T) point (interpolated over half grid width span, then held constant over all + !! points further out in Y. + INTEGER(IntKi) :: IY2 + REAL(ReKi) :: Y2 ! for points away from tower below grid + REAL(ReKi) :: Z2 ! for points away from tower below grid + REAL(ReKi) :: YgZt ! for points away from tower below grid + LOGICAL :: GridExceedY ! point is beyond bounds of grid in Y. Interpolate to average Z level over one grid width if GridExceedAllow + LOGICAL :: GridExceedZmax ! point is beyond upper bounds of grid in Z. Interpolate to average Z value at top of box over one half grid height if GridExceedAllow + LOGICAL :: GridExceedZmin ! point is below lower bounds of grid in Z. Interpolate to average Z value at top of box over one half grid height if GridExceedAllow + LOGICAL :: GridExtrap ! Extrapolation outside grid is allowed and point lies outside grid above z_min !------------------------------------------------------------------------------------------------- ! Initialize variables @@ -200,50 +241,203 @@ FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" - + GridExceedY = .false. + GridExceedZmax = .false. + GridExceedZmin = .false. + GridExtrap = .false. !------------------------------------------------------------------------------------------------- ! By definition, wind below the ground is always zero (no turbulence, either). !------------------------------------------------------------------------------------------------- IF ( Position(3) <= 0.0_ReKi ) RETURN - !------------------------------------------------------------------------------------------------- - ! get the bounding limits for T and Z + ! get the bounding limits for T, Z, and Y !------------------------------------------------------------------------------------------------- call GetTBounds(); if (ErrStat >= AbortErrLev) return call GetZBounds(); if (ErrStat >= AbortErrLev) return + if (GridExceedAllow) then + call GetYBoundsGridExceed(); + else + call GetYBounds(); if (ErrStat >= AbortErrLev) return + endif !------------------------------------------------------------------------------------------------- ! Calculate the value !------------------------------------------------------------------------------------------------- - IF ( OnGrid ) THEN ! The tower points don't use this - - call GetYBounds(); if (ErrStat >= AbortErrLev) return + IF ( AboveGridBottom ) THEN ! The tower points don't use this + ! get the Y indices amd get interpolation values call GetInterpWeights3D(); - !-------------------------------------------------------- - ! Interpolate on the grid - DO IDIM=1,p%NFFComp ! all the components - u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) - u(2) = p%FFData( IZHI, IYHI, IDIM, ITLO ) - u(3) = p%FFData( IZLO, IYHI, IDIM, ITLO ) - u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) - u(5) = p%FFData( IZHI, IYLO, IDIM, ITHI ) - u(6) = p%FFData( IZHI, IYHI, IDIM, ITHI ) - u(7) = p%FFData( IZLO, IYHI, IDIM, ITHI ) - u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) - FFWind_Interp(IDIM) = SUM ( N * u ) - END DO !IDIM + if ( GridExtrap ) then ! only true if allowed and beyond grid + + !-------------------------------------------------------- + ! Interpolate from grid edge averaged values at (Z,T) at + ! boundary at half grid width beyond + ! + ! NOTE: above grid top, the interpolate to value of average + ! across top of grid (Y values) at +FFZHWid + if ( GridExceedY ) then + if ( GridExceedZmax ) then + ! Above the grid and beyond +/-Y + ! NOTE: IZLO==IZHI -- top of grid + ! IZHI -- top of grid+FFZHWid + ! IYLO==IYHI -- side of grid point is beyond + do IDIM=1,p%NFFComp ! all the components + u(1) = p%FFAvgData( IZHI, IDIM, ITLO ) + u(2) = p%FFAvgData( IZHI, IDIM, ITLO ) + u(3) = p%FFAvgData( IZLO, IDIM, ITLO ) + u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) + u(5) = p%FFAvgData( IZHI, IDIM, ITHI ) + u(6) = p%FFAvgData( IZHI, IDIM, ITHI ) + u(7) = p%FFAvgData( IZLO, IDIM, ITHI ) + u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) + FFWind_Interp(IDIM) = SUM ( N * u ) + end do !IDIM + else + ! Beyond +/-Y of grid, but within +/-Z + ! NOTE: IYLO==IYHI -- side of grid point is beyond + do IDIM=1,p%NFFComp ! all the components + u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) + u(2) = p%FFAvgData( IZHI, IDIM, ITLO ) + u(3) = p%FFAvgData( IZLO, IDIM, ITLO ) + u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) + u(5) = p%FFData( IZHI, IYLO, IDIM, ITHI ) + u(6) = p%FFAvgData( IZHI, IDIM, ITHI ) + u(7) = p%FFAvgData( IZLO, IDIM, ITHI ) + u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) + FFWind_Interp(IDIM) = SUM ( N * u ) + end do !IDIM + endif + else + ! Above the grid, but within +/-Y + ! NOTE: IZLO -- top of grid + ! IZHI -- top of grid+FFZHWid + do IDIM=1,p%NFFComp ! all the components + u(1) = p%FFAvgData( IZHI, IDIM, ITLO ) + u(2) = p%FFAvgData( IZHI, IDIM, ITLO ) + u(3) = p%FFData( IZLO, IYHI, IDIM, ITLO ) + u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) + u(5) = p%FFAvgData( IZHI, IDIM, ITHI ) + u(6) = p%FFAvgData( IZHI, IDIM, ITHI ) + u(7) = p%FFData( IZLO, IYHI, IDIM, ITHI ) + u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) + FFWind_Interp(IDIM) = SUM ( N * u ) + end do !IDIM + endif + else + !-------------------------------------------------------- + ! Interpolate on the grid itself + DO IDIM=1,p%NFFComp ! all the components + u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) + u(2) = p%FFData( IZHI, IYHI, IDIM, ITLO ) + u(3) = p%FFData( IZLO, IYHI, IDIM, ITLO ) + u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) + u(5) = p%FFData( IZHI, IYLO, IDIM, ITHI ) + u(6) = p%FFData( IZHI, IYHI, IDIM, ITHI ) + u(7) = p%FFData( IZLO, IYHI, IDIM, ITHI ) + u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) + FFWind_Interp(IDIM) = SUM ( N * u ) + END DO !IDIM + endif ELSE - IF (p%InterpTower) THEN + IF ( GridExtrap .and. GridExceedZmin ) THEN + ! Below bottom of grid requires some special logic depending if tower + ! data exists, and if outside the Y bounds of the grid. + if ( GridExceedY ) then + ! interp between bottom of grid and ground when outside Y bounds of grid + ZGRID = Position(3)/p%GridBase + Z = 2.0_ReKi * ZGRID - 1.0_ReKi + IZHI = 1 + IZHI = 0 + + ! Get standard interpolation weightings + call GetInterpWeights3D(); + + ! Beyond the left and right bounds of grid. Linear interpolate + ! between: + ! bottom of Yavg bottom corner of grid + ! ground ground + do IDIM=1,p%NFFComp ! all the components + u(1) = p%FFData( 1, IYLO, IDIM, ITLO ) + u(2) = p%FFAvgData( 1, IDIM, ITLO ) + u(3) = 0.0_ReKi ! ground + u(4) = 0.0_ReKi ! ground + u(5) = p%FFData( 1, IYLO, IDIM, ITHI ) + u(6) = p%FFAvgData( 1, IDIM, ITHI ) + u(7) = 0.0_ReKi ! ground + u(8) = 0.0_ReKi ! ground + FFWind_Interp(IDIM) = SUM ( N * u ) + enddo + else + if (p%NTGrids < 1) then + ! Get standard interpolation weightings + call GetInterpWeights3D(); + + ! Below grid with no tower points defined + do IDIM=1,p%NFFComp ! all the components + u(1) = p%FFData( 1, IYLO, IDIM, ITLO ) + u(2) = p%FFData( 1, IYHI, IDIM, ITLO ) + u(3) = 0.0_ReKi ! ground + u(4) = 0.0_ReKi ! ground + u(5) = p%FFData( 1, IYLO, IDIM, ITHI ) + u(6) = p%FFData( 1, IYHI, IDIM, ITHI ) + u(7) = 0.0_ReKi ! ground + u(8) = 0.0_ReKi ! ground + FFWind_Interp(IDIM) = SUM ( N * u ) + enddo + else ! Tower grid + ! Special weightings required: + ! Tower has some number of points, but anywhere either + ! side of the tower only has the closest point at the + ! bottom of the grid. So we need to weight across the + ! the span differently + ! Y2 - scaled distance between side edge of grid and tower (in y) + ! Z2 - scaled distance between bottom edge of grid and ground (in z) + ! Y - scaled distance between IYLO-IYHI along bottom of grid + ! Z - scaled distance between IZLO-IZHI olong tower line + ! IYHI - grid high y point index + ! IYLO - grid low y point index + ! IZHI - tower upper point index + ! IZLO - tower lower point index + Y2 = -2.0_ReKi * abs(Position(2))/p%FFYHWid + 1.0_ReKi ! From side of grid to tower (tower at +1) + Z2 = 2.0_ReKi * Position(3)/p%GridBase - 1.0_ReKi + YgZt = 2.0_ReKi * (abs(Position(2))/(abs(Position(2)) + (p%GridBase-Position(3)))) - 1.0_ReKi ! on Tower ==-1, on grid bottom == 1 + NGe=0.0_ReKi + NGe(1) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YgZt)* ( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! grid bottom low (top right point, lo half) + NGe(2) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YgZt)* ( 1.0_ReKi + Y )*( 1.0_ReKi - T ) ! grid bottom hi (top right point, hi half) + NGE(3) = ( 1.0_ReKi-YgZt)*( 1.0_ReKi + Z )* ( 1.0_ReKi - T )*2.0_ReKi ! tower line high (bottom right point, hi half) + NGE(4) = ( 1.0_ReKi-YgZt)*( 1.0_ReKi - Z )* ( 1.0_ReKi - T )*2.0_ReKi ! Tower line lo (bottom right point, lo half) + NGe(5) = ( 1.0_ReKi - Z2)* ( 1.0_ReKi - T )*6.0_ReKi ! ground (bottom left point) + NGe(6) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YgZt)* ( 1.0_ReKi - Y )*( 1.0_ReKi + T ) + NGe(7) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YgZt)* ( 1.0_ReKi + Y )*( 1.0_ReKi + T ) + NGE(8) = ( 1.0_ReKi-YgZt)*( 1.0_ReKi + Z )* ( 1.0_ReKi + T )*2.0_ReKi + NGE(9) = ( 1.0_ReKi-YgZt)*( 1.0_ReKi - Z )* ( 1.0_ReKi + T )*2.0_ReKi + NGe(10) = ( 1.0_ReKi - Z2)* ( 1.0_ReKi + T )*6.0_ReKi + NGe = NGe / 16.0_ReKi ! normalize + do IDIM=1,p%NFFComp + uGe(1) = p%FFData( 1, IYLO, IDIM, ITLO ) ! grid bottom low (top point, lo half) + uGe(2) = p%FFData( 1, IYHI, IDIM, ITLO ) ! grid bottom hi (top point, hi half) + uGe(3) = p%FFTower( IDIM, IZHI, ITLO ) ! tower line high (bottom point, hi half) + uGe(4) = p%FFTower( IDIM, IZLO, ITLO ) ! Tower line lo (bottom point, lo half) + uGe(5) = 0.0_ReKi ! ground (bottom left point) + uGe(6) = p%FFData( 1, IYLO, IDIM, ITHI ) + uGe(7) = p%FFData( 1, IYHI, IDIM, ITHI ) + uGe(8) = p%FFTower( IDIM, IZHI, ITHI ) + uGe(9) = p%FFTower( IDIM, IZLO, ITHI ) + uGe(10) = 0.0_ReKi + FFWind_Interp(IDIM) = SUM ( NGe * uGe ) + enddo + endif + endif + ELSEIF (p%InterpTower) THEN + !----------------------------------------------------- ! Interpolate on the bottom of the grid to the ground ! ground points set to zero - call GetYBounds(); if (ErrStat >= AbortErrLev) return call GetInterpWeights3D(); DO IDIM=1,p%NFFComp ! all the components @@ -279,7 +473,7 @@ FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) FFWind_Interp(IDIM) = SUM ( M * v ) END DO !IDIM END IF ! Interpolate below the grid - ENDIF ! OnGrid + ENDIF ! AboveGridBottom RETURN @@ -347,10 +541,10 @@ SUBROUTINE GetZBounds() ZGRID = ( Position(3) - p%GridBase )*p%InvFFZD IF (ZGRID > -1*TOL) THEN - OnGrid = .TRUE. + AboveGridBottom = .TRUE. ! Index for start and end slices - IZLO = INT( ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 + IZLO = FLOOR( ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 IZHI = IZLO + 1 ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. @@ -362,6 +556,7 @@ SUBROUTINE GetZBounds() Z = -1.0_ReKi IZLO = 1 ELSE + ! Given the first if statement, is it ever possible to end up here??? ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& TRIM(Num2LStr(Position(3)))//' m is below the grid).' ErrStat = ErrID_Fatal @@ -371,6 +566,14 @@ SUBROUTINE GetZBounds() IF ( IZLO == p%NZGrids .AND. Z <= TOL ) THEN Z = -1.0_ReKi IZHI = IZLO ! We're right on the last point, which is still okay + ELSEIF ( GridExceedAllow ) THEN + ! calculate new Z between top of grid and half zgrid height above top of grid (range of -1 to 1) + Z = 2.0_ReKi * ( Position(3) - (p%GridBase + 2*p%FFZHWid) ) / p%FFZHWid - 1.0_ReKi + Z = min(Z,1.0_ReKi) ! plateau value at grid width above top of grid + IZLO = p%NZGrids ! Top of grid + IZHI = p%NZGrids ! Top of grid + GridExceedZmax = .true. + GridExtrap = .true. ELSE ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& TRIM(Num2LStr(Position(3)))//' m is above the grid).' @@ -380,9 +583,11 @@ SUBROUTINE GetZBounds() ENDIF ELSE - - OnGrid = .FALSE. ! this is on the tower - + AboveGridBottom = .FALSE. ! this is below the grid bottom + if ( GridExceedAllow ) then + GridExceedZmin = .true. + GridExtrap = .true. + endif IF (p%InterpTower) then ! get Z between ground and bottom of grid ZGRID = Position(3)/p%GridBase @@ -391,6 +596,7 @@ SUBROUTINE GetZBounds() IZLO = 0 IF ( ZGRID < 0.0_ReKi ) THEN + ! note: this is already considered at the start of the routine ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the ground).' ErrStat = ErrID_Fatal @@ -398,25 +604,27 @@ SUBROUTINE GetZBounds() ENDIF ELSE IF ( p%NTGrids < 1) THEN - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & - '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - - IZLO = INT( -1.0*ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - - IF ( IZLO >= p%NTGrids ) THEN !our dz is the difference between the bottom tower point and the ground - IZLO = p%NTGrids - ! Check that this isn't zero. Value between -1 and 1 corresponding to the relative position. - Z = 1.0_ReKi - 2.0_ReKi * (Position(3) / (p%GridBase - REAL(IZLO - 1_IntKi, ReKi)/p%InvFFZD)) + IF ( .not. GridExceedAllow ) THEN + ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & + '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' + ErrStat = ErrID_Fatal + RETURN + ENDIF ELSE - ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. Used in the interpolation. - Z = 2.0_ReKi * (ABS(ZGRID) - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi - ENDIF - IZHI = IZLO + 1 - ENDIF - END IF + IZLO = INT( -1.0*ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 + + IF ( IZLO >= p%NTGrids ) THEN !our dz is the difference between the bottom tower point and the ground + IZLO = p%NTGrids + ! Check that this isn't zero. Value between -1 and 1 corresponding to the relative position. + Z = 1.0_ReKi - 2.0_ReKi * (Position(3) / (p%GridBase - REAL(IZLO - 1_IntKi, ReKi)/p%InvFFZD)) + ELSE + ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. Used in the interpolation. + Z = 2.0_ReKi * (ABS(ZGRID) - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi + ENDIF + IZHI = IZLO + 1 + ENDIF ! Tower grid + ENDIF ! Interp tower + END IF ! AboveGridBottom END SUBROUTINE GetZBounds !------------------------------------------------------------------------------------------------- @@ -424,7 +632,8 @@ END SUBROUTINE GetZBounds SUBROUTINE GetYBounds() YGRID = ( Position(2) + p%FFYHWid )*p%InvFFYD ! really, it's (Position(2) - -1.0*p%FFYHWid) - IYLO = INT( YGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 + + IYLO = FLOOR( YGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 IYHI = IYLO + 1 ! Set Y as a value between -1 and 1 for the relative location between IYLO and IYHI. Used in the interpolation. @@ -448,13 +657,46 @@ SUBROUTINE GetYBounds() ENDIF END SUBROUTINE GetYBounds + !------------------------------------------------------------------------------------------------- + !> Find the bounding columns for the Y position. [The lower-left corner is (1,1) when looking upwind.] + !! The logic is slightly different when grid exceedence is allowed. + SUBROUTINE GetYBoundsGridExceed() + YGRID = ( Position(2) + p%FFYHWid )*p%InvFFYD ! really, it's (Position(2) - -1.0*p%FFYHWid) + IYLO = FLOOR( YGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 + IYHI = IYLO + 1 + + ! Set Y as a value between -1 and 1 for the relative location between IYLO and IYHI. Used in the interpolation. + ! Subtract 1_IntKi from IYLO since grids start at index 1, not 0 + Y = 2.0_ReKi * (YGRID - REAL(IYLO - 1_IntKi, ReKi)) - 1.0_ReKi + + ! Using the average across Y as the boundary beyond the grid at +/-2*YHWid + IF ( IYLO <= 0 ) THEN ! Beyond lo side + ! calculate new Y between half ygrid width beyond edge (2*FFYHWid) and the + ! low side of the grid, then scale to -1 to 1 + Y = 2.0_ReKi * ( Position(2) + 2*p%FFYHWid ) / p%FFYHWid - 1.0_ReKi + Y = max(y,-1.0_ReKi) ! plateau value at grid width lo side of grid + IYLO = 1 ! Lo side of grid + IYHI = 1 ! Lo side of grid + Y = -Y ! Flip sign so -1 will be grid edge at all times + GridExceedY = .true. + GridExtrap = .true. + ELSEIF ( IYHI > p%NYGrids ) THEN ! Beyond hi side + Y = 2.0_ReKi * ( Position(2) - p%FFYHWid) / p%FFYHWid - 1.0_ReKi + IYLO = p%NYGrids ! Hi side of grid + IYHI = p%NYGrids ! Hi side of grid + Y = min(Y,1.0_ReKi) ! plateau value at grid width beyond edge + GridExceedY = .true. + GridExtrap = .true. + ENDIF + END SUBROUTINE GetYBoundsGridExceed + !------------------------------------------------------------------------------------------------- !> Get normalization values for 3d-linear interpolation on the grid SUBROUTINE GetInterpWeights3D() - N(1) = ( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) - N(2) = ( 1.0_ReKi + Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) - N(3) = ( 1.0_ReKi - Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) - N(4) = ( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) + N(1) = ( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! top left + N(2) = ( 1.0_ReKi + Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) ! top right + N(3) = ( 1.0_ReKi - Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) ! bottom right + N(4) = ( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! bottom left N(5) = ( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) N(6) = ( 1.0_ReKi + Z )*( 1.0_ReKi + Y )*( 1.0_ReKi + T ) N(7) = ( 1.0_ReKi - Z )*( 1.0_ReKi + Y )*( 1.0_ReKi + T ) diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index c2d4b104da..1d26960bb9 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -171,6 +171,7 @@ PROGRAM InflowWind_Driver CLSettingsFlags%WrBladed = .FALSE. ! don't convert to Bladed format CLSettingsFlags%WrVTK = .FALSE. ! don't convert to VTK format CLSettingsFlags%WrUniform = .FALSE. ! don't convert to UniformWind format + CLSettingsFlags%BoxExceedAllowF = .FALSE. ! don't set flag to allow points outside FF box ! Initialize the driver settings to their default values (same as the CL -- command line -- values) Settings = CLSettings @@ -461,6 +462,8 @@ PROGRAM InflowWind_Driver END IF InflowWind_InitInp%RootName = trim(InflowWind_InitInp%RootName)//'.IfW' InflowWind_InitInp%RadAvg = -1.0_ReKi ! let the IfW code guess what to use + InflowWind_InitInp%BoxExceedAllowF = SettingsFlags%BoxExceedAllowF ! Set flag for allowing points outside the wind box (alternate interpolation method for FF) + if (InflowWind_InitInp%BoxExceedAllowF) InflowWind_InitInp%BoxExceedAllowIdx = 1_IntKi IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr('Calling InflowWind_Init...') diff --git a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 index ed7801e79f..4fa263221c 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 @@ -59,25 +59,26 @@ SUBROUTINE DispHelpText( ErrStat, ErrMsg ) CALL WrScr(" (no driver input file)") CALL WrScr("") CALL WrScr(" The following options will overwrite values in the driver input file:") - CALL WrScr(" "//SwChar//"DT[#] -- timestep ") - CALL WrScr(" "//SwChar//"TStart[#] -- start time ") - CALL WrScr(" "//SwChar//"TSteps[#] -- number of timesteps ") - CALL WrScr(" "//SwChar//"xrange[#:#] -- range of x (#'s are reals) ") - CALL WrScr(" "//SwChar//"yrange[#:#] -- range of y ") - CALL WrScr(" "//SwChar//"zrange[#:#] -- range in z (ground = 0.0) ") - CALL WrScr(" "//SwChar//"Dx[#] -- spacing in x ") - CALL WrScr(" "//SwChar//"Dy[#] -- spacing in y ") - CALL WrScr(" "//SwChar//"Dz[#] -- spacing in z ") -! CALL WrScr(" "//SwChar//"sum -- summarize wind file info [N/A]") -! CALL WrScr(" "//SwChar//"FFT[X,Y,Z] -- an fft over all t using specified DT at X,Y,Z [N/A]") - CALL WrScr(" "//SwChar//"points[FILE] -- calculates at x,y,z coordinates specified in a ") + CALL WrScr(" "//SwChar//"DT[#] -- timestep ") + CALL WrScr(" "//SwChar//"TStart[#] -- start time ") + CALL WrScr(" "//SwChar//"TSteps[#] -- number of timesteps ") + CALL WrScr(" "//SwChar//"xrange[#:#] -- range of x (#'s are reals) ") + CALL WrScr(" "//SwChar//"yrange[#:#] -- range of y ") + CALL WrScr(" "//SwChar//"zrange[#:#] -- range in z (ground = 0.0) ") + CALL WrScr(" "//SwChar//"Dx[#] -- spacing in x ") + CALL WrScr(" "//SwChar//"Dy[#] -- spacing in y ") + CALL WrScr(" "//SwChar//"Dz[#] -- spacing in z ") +! CALL WrScr(" "//SwChar//"sum -- summarize wind file info [N/A]") +! CALL WrScr(" "//SwChar//"FFT[X,Y,Z] -- an fft over all t using specified DT at X,Y,Z [N/A]") + CALL WrScr(" "//SwChar//"points[FILE] -- calculates at x,y,z coordinates specified in a ") CALL WrScr(" white space delimited FILE") - CALL WrScr(" "//SwChar//"v -- verbose output ") - CALL WrScr(" "//SwChar//"vv -- very verbose output ") - CALL WrScr(" "//SwChar//"HAWC -- convert contents of to HAWC format ") - CALL WrScr(" "//SwChar//"Bladed -- convert contents of to Bladed format ") - CALL WrScr(" "//SwChar//"vtk -- convert contents of to vtk format ") - CALL WrScr(" "//SwChar//"help -- print this help menu and exit") + CALL WrScr(" "//SwChar//"v -- verbose output ") + CALL WrScr(" "//SwChar//"vv -- very verbose output ") + CALL WrScr(" "//SwChar//"HAWC -- convert contents of to HAWC format ") + CALL WrScr(" "//SwChar//"Bladed -- convert contents of to Bladed format ") + CALL WrScr(" "//SwChar//"vtk -- convert contents of to vtk format ") + CALL WrScr(" "//SwChar//"BoxExceedAllow -- set flag to allow FF points outside wind box") + CALL WrScr(" "//SwChar//"help -- print this help menu and exit") CALL WrScr("") CALL WrScr(" Notes:") CALL WrScr(" -- Unspecified ranges and resolutions default to what is in the file.") @@ -326,6 +327,8 @@ SUBROUTINE ParseArg( CLSettings, CLFlags, ThisArgUC, ThisArg, ifwFlagSet, ErrSta RETURN ELSEIF ( TRIM(ThisArgUC) == "UNIFORM" ) THEN CLFlags%WrUniform = .TRUE. + ELSEIF ( TRIM(ThisArgUC) == "BOXEXCEEDALLOW" ) THEN + CLFlags%BoxExceedAllowF = .TRUE. RETURN ELSE CALL SetErrStat( ErrID_Warn," Unrecognized option '"//SwChar//TRIM(ThisArg)//"'. Ignoring. Use option "//SwChar//"help for list of options.", & @@ -1340,6 +1343,7 @@ SUBROUTINE UpdateSettingsWithCL( DvrFlags, DvrSettings, CLFlags, CLSettings, DVR DvrFlags%WrBladed = DvrFlags%WrBladed .or. CLFlags%WrBladed ! create file if specified in either place DvrFlags%WrVTK = DvrFlags%WrVTK .or. CLFlags%WrVTK ! create file if specified in either place DvrFlags%WrUniform = DvrFlags%WrUniform .or. CLFlags%WrUniform ! create file if specified in either place + DvrFlags%BoxExceedAllowF = DvrFlags%BoxExceedAllowF .or. CLFlags%BoxExceedAllowF ! flag to allow points beyond box for FF ! ! Due to the complexity, we are handling overwriting driver input file settings with ! ! command line settings and the instance where no driver input file is read separately. @@ -1389,6 +1393,7 @@ SUBROUTINE UpdateSettingsWithCL( DvrFlags, DvrSettings, CLFlags, CLSettings, DVR DvrSettings%NumTimeSteps = MAX(DvrSettings%NumTimeSteps,1_IntKi) + !-------------------------------------------- ! Did we change the ranges for the WindGrid? !-------------------------------------------- @@ -1765,7 +1770,6 @@ SUBROUTINE UpdateSettingsWithCL( DvrFlags, DvrSettings, CLFlags, CLSettings, DVR ENDIF - END SUBROUTINE UpdateSettingsWithCL @@ -2283,7 +2287,7 @@ SUBROUTINE WindGridVel_OutputWrite (FileUnit, FileName, Initialized, Settings, G INTEGER(IntKi) :: I !< generic counter - WindVelFmt = "(3(F14.7,3x),3(F10.3,3x))" + WindVelFmt = "(3(F14.7,3x),3(F14.7,3x))" ErrMsg = '' ErrStat = ErrID_None diff --git a/modules/inflowwind/src/InflowWind_Driver_Types.f90 b/modules/inflowwind/src/InflowWind_Driver_Types.f90 index 49fa3446d5..aa1e50a398 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Types.f90 @@ -66,6 +66,7 @@ MODULE InflowWind_Driver_Types LOGICAL :: FFTOutputInit = .FALSE. !< Is the FFT output file initialized LOGICAL :: Verbose = .FALSE. !< Verbose error reporting LOGICAL :: VVerbose = .FALSE. !< Very Verbose error reporting + LOGICAL :: BoxExceedAllowF = .FALSE. !< set flag to allow exceeding wind box boundaries for FF files (for diagnostic purposes) LOGICAL :: WrHAWC = .FALSE. !< Requested file conversion to HAWC2 format? LOGICAL :: WrBladed = .FALSE. !< Requested file conversion to Bladed format? diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 61a47d579b..d53d31b58f 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -568,6 +568,11 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, ELSEIF ( p_FAST%CompAero == Module_AD ) THEN ! Number of Wind points from AeroDyn, see AeroDyn.f90 Init%InData_IfW%NumWindPoints = Init%InData_IfW%NumWindPoints + AD_NumWindPoints(AD%Input(1), AD%OtherSt(STATE_CURR)) + ! 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))) + endif END IF ! lidar From 3a63e7c3c8fa83bfa0726808ffbcb2c79e7570d7 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Fri, 1 Oct 2021 10:50:05 -0600 Subject: [PATCH 18/51] IfW grid exceed: algorithm for extrapolating from tower below grid This gives a reasonably continuous function (not smooth) from the tower out beyond the +/-Y edge of the grid. There is some physics that we can't account for simply because the information doesn't exist, but this should at least allow wake evolution. If weirdness occurs, extend grid to ground. One missing piece at the moment is the summation of NGe should be ==1 for the region between 2*FFYHWid < abs(y) < FFYHWid, but it is not. Since the plots show continuity in value (not in derivatives), it is assumed there is some book-keeping incorrect with the NGe(5) and NGe(10) terms which get multiplied by zero. So something isn't exactly right in the derivation, but the result is still reasonable (though potentially incorrect). --- modules/inflowwind/src/IfW_FFWind_Base.f90 | 201 +++++++++++++++------ 1 file changed, 144 insertions(+), 57 deletions(-) diff --git a/modules/inflowwind/src/IfW_FFWind_Base.f90 b/modules/inflowwind/src/IfW_FFWind_Base.f90 index 16a08c7fa3..ed9edab0b8 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base.f90 +++ b/modules/inflowwind/src/IfW_FFWind_Base.f90 @@ -109,20 +109,8 @@ SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, Velocity, ErrStat, ErrMsg ! is this point allowed beyond the bounds of the wind box? GridExceedAllow = p%BoxExceedAllowF .and. ( PointNum >= p%BoxExceedAllowIdx ) -if (isnan(PositionXYZ(1,PointNum)) .or. isnan(PositionXYZ(2,PointNum)) .or. isnan(PositionXYZ(3,PointNum))) then -ErrStat=ErrID_Fatal -if(GridExceedAllow) then -ErrMsg="NaN passed into IfW at "//trim(num2lstr(TIME))//" for PointNum "//trim(num2lstr(PointNum))//" of "//trim(num2lstr(NumPoints))//" with GridExceedAllow = true" -else -ErrMsg="NaN passed into IfW at "//trim(num2lstr(TIME))//" for PointNum "//trim(num2lstr(PointNum))//" of "//trim(num2lstr(NumPoints))//" with GridExceedAllow = fals" -endif -return -endif ! Calculate the velocity for the position Velocity(:,PointNum) = FFWind_Interp(Time,PositionXYZ(:,PointNum),p,GridExceedAllow,TmpErrStat,TmpErrMsg) -if (TIME > 12.4_DbKi) then -write(23,*) TIME,PointNum,PositionXYZ(:,PointNum),Velocity(:,PointNum) -endif ! Error handling IF (TmpErrStat /= ErrID_None) THEN ! adding this so we don't have to convert numbers to strings every time @@ -224,10 +212,18 @@ FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, ErrStat, ErrMsg) !! For points below the top of the grid, the value is interpolated between the Y averaged value for that (X,Z,T) !! location and the closest (X,Y,Z,T) point (interpolated over half grid width span, then held constant over all !! points further out in Y. + !! + !! NOTE: to test the effects of grid exceeded points, run the driver with a grid output larger than the wind grid + !! for a single timestep (set in driver input file IfW_driver.inp) using the command: + !! + !! inflowwind_driver -BoxExceedAllow IfW_driver.inp + !! + !! and plot the resulting surfaces representing the U,V,W at a given YZ plane at time T (results given in + !! output file IfW_driver.WindGrid.out). INTEGER(IntKi) :: IY2 - REAL(ReKi) :: Y2 ! for points away from tower below grid - REAL(ReKi) :: Z2 ! for points away from tower below grid - REAL(ReKi) :: YgZt ! for points away from tower below grid + REAL(ReKi) :: Z2 ! for points away from tower below grid -- distance from ground to grid bottom (-1 to 1 range) + REAL(ReKi) :: YtZg ! distance from grid to tower along a right angled corner line from grid bottom through point to tower + REAL(ReKi) :: YtZgG ! distance from grid to tower along a right angled corner line from grid bottom through point to tower LOGICAL :: GridExceedY ! point is beyond bounds of grid in Y. Interpolate to average Z level over one grid width if GridExceedAllow LOGICAL :: GridExceedZmax ! point is beyond upper bounds of grid in Z. Interpolate to average Z value at top of box over one half grid height if GridExceedAllow LOGICAL :: GridExceedZmin ! point is below lower bounds of grid in Z. Interpolate to average Z value at top of box over one half grid height if GridExceedAllow @@ -347,31 +343,124 @@ FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, ErrStat, ErrMsg) IF ( GridExtrap .and. GridExceedZmin ) THEN ! Below bottom of grid requires some special logic depending if tower ! data exists, and if outside the Y bounds of the grid. + ! + ! Tower influence: + ! Extrapolating between the bottom of the grid, the ground, and the + ! tower is a bit of an exercise in data fabrication. The tower typically + ! is an expoential decline from the bottom of the grid, but may not go + ! to zero at the ground. Beyond the tower, there is no information from + ! the wind file regarding interpolation between the grid and ground, so + ! 1) a linear interpolation is sometimes used when no tower points + ! exist, or + ! 2) the tower values are simply assumed across this region. + ! The problem with 2) is it is not necessarily continuous at the bottom + ! of the grid. This is not historically an issue since the tower is + ! usually the only thing that shows up in that region (blades are still + ! moving within the grid), but may occasionally appear when the tower + ! moves in a floating offshore system. + ! + ! For lidar or free wake propogation, a continuous function is necessary + ! to prevent jittery measurements or tearing of the wake vortices due + ! to dramatic shear. To address this, the tower influence is calculated + ! as across the region as follows: + ! 1) weighting of tower vs. bottom of grid influence based on how + ! close the point is to these two lines. + ! 2) tower influence may exist at grid edge between grid corner and + ! ground, so influence of tower at this imaginary line is used to + ! extrapolate beyond the grid edge in the +/-Y directions. Linear + ! 3) the average value across Y at the bottom of the grid at time T + ! used as a constant value at Z of bottom of grid and linearly + ! interpolated to the ground for abs(y)>2*FFYHWid. + ! 4) linear interpolation is used between 2*FFHWid > abs(y) > 2*FFHWid + ! The above assumptions give continuous wind functions, though not smooth. + ! It is far from ideal, but at least should allow the simulation to run + ! without undue influence of discontinueties in the wind velocities. If + ! this extrapolation is not sufficient, then simply make the grid extend + ! all the way to the ground. if ( GridExceedY ) then - ! interp between bottom of grid and ground when outside Y bounds of grid - ZGRID = Position(3)/p%GridBase - Z = 2.0_ReKi * ZGRID - 1.0_ReKi - IZHI = 1 - IZHI = 0 - - ! Get standard interpolation weightings - call GetInterpWeights3D(); - - ! Beyond the left and right bounds of grid. Linear interpolate - ! between: - ! bottom of Yavg bottom corner of grid - ! ground ground - do IDIM=1,p%NFFComp ! all the components - u(1) = p%FFData( 1, IYLO, IDIM, ITLO ) - u(2) = p%FFAvgData( 1, IDIM, ITLO ) - u(3) = 0.0_ReKi ! ground - u(4) = 0.0_ReKi ! ground - u(5) = p%FFData( 1, IYLO, IDIM, ITHI ) - u(6) = p%FFAvgData( 1, IDIM, ITHI ) - u(7) = 0.0_ReKi ! ground - u(8) = 0.0_ReKi ! ground - FFWind_Interp(IDIM) = SUM ( N * u ) - enddo + if (p%NTGrids < 1) then + ! interp between bottom of grid and ground when outside Y bounds of grid and no tower + ZGRID = Position(3)/p%GridBase + Z = 2.0_ReKi * ZGRID - 1.0_ReKi + IZHI = 1 + IZHI = 0 + + ! Get standard interpolation weightings + call GetInterpWeights3D(); + + ! Beyond the left and right bounds of grid. Linear interpolate + ! between: + ! bottom of Yavg bottom corner of grid + ! ground ground + do IDIM=1,p%NFFComp ! all the components + u(1) = p%FFData( 1, IYLO, IDIM, ITLO ) + u(2) = p%FFAvgData( 1, IDIM, ITLO ) + u(3) = 0.0_ReKi ! ground + u(4) = 0.0_ReKi ! ground + u(5) = p%FFData( 1, IYLO, IDIM, ITHI ) + u(6) = p%FFAvgData( 1, IDIM, ITHI ) + u(7) = 0.0_ReKi ! ground + u(8) = 0.0_ReKi ! ground + FFWind_Interp(IDIM) = SUM ( N * u ) + enddo + else ! Tower grid + ! YtZg - distance from grid bottom to tower along a right angled corner + ! line from grid bottom through point to tower. Used to change + ! weighting between grid and tower influece (kind of approximates + ! a spherical weighting, but without considering more points along + ! grid bottom or tower). + ! YtZgG- distance from ground bottom to point along a right angled corner + ! line from ground through point to tower. Used to change + ! weighting between grid and tower influece at +/-p%FFYHWid + ! (similar to YtZg). + ! Z2 - scaled distance between bottom edge of grid and ground (in z) + ! Y - scaled distance between IYLO-IYHI between grid edge and +/-2*p%FFYHWid + ! Z - scaled distance between IZLO-IZHI olong tower line + ! IYLO - grid corner point index + ! IZHI - tower upper point index + ! IZLO - tower lower point index + ! + ! NOTE: there is a slight bug with this formulation. The sum(NGe) should be + ! exactly 1.0, but it is not. The boundaries match the expected values + ! well and give continuous transitions to the other regions, so it is + ! suspected that the ground point coefficient is incorrect. Since the + ! ground point coefficient is multiplied by zero, it doesn't affect + ! the results so I won't spend more time trying to figure it out (ADP). + Z2 = 2.0_ReKi * Position(3)/p%GridBase - 1.0_ReKi + YtZg = 2.0_ReKi * (p%FFYHWid/(p%FFYHWid + (p%GridBase-Position(3)))) - 1.0_ReKi + YtZgG= 2.0_ReKi * (Position(3))/(p%FFYHWid+Position(2)+Position(3)) - 1.0_ReKi + NGe=0.0_ReKi + NGe(1) = ( 1.0_ReKi + Z2)* ( 1.0_ReKi + Y )*( 1.0_ReKi - T )*2.0_ReKi ! bottom of grid average (top right point, hi half) + NGe(2) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! corner of grid (top right point, lo half) + NGe(3) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! Below grid edge with tower effect (bottom right point, hi half) + NGe(4) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! Below grid edge with tower effect (bottom right point, lo half) + NGe(6) = ( 1.0_ReKi + Z2)* ( 1.0_ReKi + Y )*( 1.0_ReKi + T )*2.0_ReKi + NGe(7) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - Y )*( 1.0_ReKi + T ) + NGe(8) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) + NGe(9) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) + if (abs(Position(2)) > 2*p%FFYHWid) then + NGe(5) = ( 1.0_ReKi - Z2)* ( 1.0_ReKi - T )*4.0_ReKi ! ground (bottom left point) + NGe(10) = ( 1.0_ReKi - Z2)* ( 1.0_ReKi + T )*4.0_ReKi + else + ! NOTE: This coefficient is probably incorrect, but gets multiplied by zero so I'm not fixing it. + NGe(5) = ( 1.0_ReKi - Z2)*( 1.0_ReKi-YtZgG)*( 1.0_ReKi + Y )* ( 1.0_ReKi - T ) ! ground (bottom left point) + NGe(10) = ( 1.0_ReKi - Z2)*( 1.0_ReKi-YtZgG)*( 1.0_ReKi + Y )* ( 1.0_ReKi + T ) + endif + NGe = NGe /16.0_ReKi ! normalize + do IDIM=1,p%NFFComp + uGe(1) = p%FFAvgData( 1, IDIM, ITLO ) ! bottom of grid average + uGe(2) = p%FFData( 1, IYLO, IDIM, ITLO ) ! Corner of grid + uGe(3) = p%FFTower( IDIM, IZHI, ITLO ) ! tower line high (bottom point, hi half) + uGe(4) = p%FFTower( IDIM, IZLO, ITLO ) ! Tower line lo (bottom point, lo half) + uGe(5) = 0.0_ReKi ! ground (bottom left point) + uGe(6) = p%FFAvgData( 1, IDIM, ITHI ) + uGe(7) = p%FFData( 1, IYLO, IDIM, ITHI ) + uGe(8) = p%FFTower( IDIM, IZHI, ITHI ) + uGe(9) = p%FFTower( IDIM, IZLO, ITHI ) + uGe(10) = 0.0_ReKi + FFWind_Interp(IDIM) = SUM ( NGe * uGe ) + enddo + endif else if (p%NTGrids < 1) then ! Get standard interpolation weightings @@ -390,12 +479,11 @@ FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, ErrStat, ErrMsg) FFWind_Interp(IDIM) = SUM ( N * u ) enddo else ! Tower grid - ! Special weightings required: - ! Tower has some number of points, but anywhere either - ! side of the tower only has the closest point at the - ! bottom of the grid. So we need to weight across the - ! the span differently - ! Y2 - scaled distance between side edge of grid and tower (in y) + ! YtZg - distance from grid bottom to tower along a right angled corner + ! line from grid bottom through point to tower. Used to change + ! weighting between grid and tower influece (kind of approximates + ! a spherical weighting, but without considering more points along + ! grid bottom or tower). ! Z2 - scaled distance between bottom edge of grid and ground (in z) ! Y - scaled distance between IYLO-IYHI along bottom of grid ! Z - scaled distance between IZLO-IZHI olong tower line @@ -403,20 +491,19 @@ FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, ErrStat, ErrMsg) ! IYLO - grid low y point index ! IZHI - tower upper point index ! IZLO - tower lower point index - Y2 = -2.0_ReKi * abs(Position(2))/p%FFYHWid + 1.0_ReKi ! From side of grid to tower (tower at +1) Z2 = 2.0_ReKi * Position(3)/p%GridBase - 1.0_ReKi - YgZt = 2.0_ReKi * (abs(Position(2))/(abs(Position(2)) + (p%GridBase-Position(3)))) - 1.0_ReKi ! on Tower ==-1, on grid bottom == 1 + YtZg = 2.0_ReKi * (abs(Position(2))/(abs(Position(2)) + (p%GridBase-Position(3)))) - 1.0_ReKi ! on Tower ==-1, on grid bottom == 1 NGe=0.0_ReKi - NGe(1) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YgZt)* ( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! grid bottom low (top right point, lo half) - NGe(2) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YgZt)* ( 1.0_ReKi + Y )*( 1.0_ReKi - T ) ! grid bottom hi (top right point, hi half) - NGE(3) = ( 1.0_ReKi-YgZt)*( 1.0_ReKi + Z )* ( 1.0_ReKi - T )*2.0_ReKi ! tower line high (bottom right point, hi half) - NGE(4) = ( 1.0_ReKi-YgZt)*( 1.0_ReKi - Z )* ( 1.0_ReKi - T )*2.0_ReKi ! Tower line lo (bottom right point, lo half) - NGe(5) = ( 1.0_ReKi - Z2)* ( 1.0_ReKi - T )*6.0_ReKi ! ground (bottom left point) - NGe(6) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YgZt)* ( 1.0_ReKi - Y )*( 1.0_ReKi + T ) - NGe(7) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YgZt)* ( 1.0_ReKi + Y )*( 1.0_ReKi + T ) - NGE(8) = ( 1.0_ReKi-YgZt)*( 1.0_ReKi + Z )* ( 1.0_ReKi + T )*2.0_ReKi - NGE(9) = ( 1.0_ReKi-YgZt)*( 1.0_ReKi - Z )* ( 1.0_ReKi + T )*2.0_ReKi - NGe(10) = ( 1.0_ReKi - Z2)* ( 1.0_ReKi + T )*6.0_ReKi + NGe(1) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! grid bottom low (top right point, lo half) + NGe(2) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi + Y )*( 1.0_ReKi - T ) ! grid bottom hi (top right point, hi half) + NGe(3) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi + Z )* ( 1.0_ReKi - T )*2.0_ReKi ! tower line high (bottom right point, hi half) + NGe(4) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi - Z )* ( 1.0_ReKi - T )*2.0_ReKi ! Tower line lo (bottom right point, lo half) + NGe(5) = ( 1.0_ReKi - Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - T )*2.0_ReKi ! ground (bottom left point) + NGe(6) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - Y )*( 1.0_ReKi + T ) + NGe(7) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi + Y )*( 1.0_ReKi + T ) + NGe(8) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi + Z )* ( 1.0_ReKi + T )*2.0_ReKi + NGe(9) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi - Z )* ( 1.0_ReKi + T )*2.0_ReKi + NGe(10) = ( 1.0_ReKi - Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi + T )*2.0_ReKi NGe = NGe / 16.0_ReKi ! normalize do IDIM=1,p%NFFComp uGe(1) = p%FFData( 1, IYLO, IDIM, ITLO ) ! grid bottom low (top point, lo half) From 1698843bbb260ab6dabfd62874a861293a748210 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 4 Oct 2021 16:29:09 -0600 Subject: [PATCH 19/51] IfW grid exceed: add some rudimentary documentation --- docs/source/user/inflowwind/driver.rst | 120 +++++++++++++++--- .../inflowwind/figs/FFWindExtrap--NoTower.png | Bin 0 -> 136589 bytes .../inflowwind/figs/FFWindExtrap--Tower.png | Bin 0 -> 135967 bytes 3 files changed, 102 insertions(+), 18 deletions(-) create mode 100644 docs/source/user/inflowwind/figs/FFWindExtrap--NoTower.png create mode 100644 docs/source/user/inflowwind/figs/FFWindExtrap--Tower.png diff --git a/docs/source/user/inflowwind/driver.rst b/docs/source/user/inflowwind/driver.rst index fd322a5b1f..937760baf9 100644 --- a/docs/source/user/inflowwind/driver.rst +++ b/docs/source/user/inflowwind/driver.rst @@ -13,23 +13,23 @@ Command-line syntax for InflowWind driver: options: /ifw -- treat as name of InflowWind input file (no driver input file) The following options will override values in the driver input file: - /DT[#] -- timestep - /TStart[#] -- start time - /TSteps[#] -- number of timesteps - /xrange[#:#] -- range of x (#'s are reals) - /yrange[#:#] -- range of y - /zrange[#:#] -- range in z (ground = 0.0) - /Dx[#] -- spacing in x - /Dy[#] -- spacing in y - /Dz[#] -- spacing in z - /points[FILE] -- calculates at x,y,z coordinates specified in a white space delimited FILE - /v -- verbose output - /vv -- very verbose output - /hawc -- convert wind file specified in InflowWind to HAWC format - /bladed -- convert wind file specified in InflowWind to Bladed format - /uniform -- convert wind file specified in InflowWind to Uniform-wind format - /vtk -- convert wind file specified in InflowWind to VTK format - /help -- print this help menu and exit + /DT[#] -- timestep + /TStart[#] -- start time + /TSteps[#] -- number of timesteps + /xrange[#:#] -- range of x (#'s are reals) + /yrange[#:#] -- range of y + /zrange[#:#] -- range in z (ground = 0.0) + /Dx[#] -- spacing in x + /Dy[#] -- spacing in y + /Dz[#] -- spacing in z + /points[FILE] -- calculates at x,y,z coordinates specified in a white space delimited FILE + /v -- verbose output + /vv -- very verbose output + /hawc -- convert wind file specified in InflowWind to HAWC format + /bladed -- convert wind file specified in InflowWind to Bladed format + /vtk -- convert wind file specified in InflowWind to VTK format + /BoxExceedAllow -- set flag to extrapolate values of points outside FF wind box + /help -- print this help menu and exit :: @@ -137,4 +137,88 @@ When converting from a full-field wind format to a uniform wind file, the follow - The power law exponent is either 1. The power-law exponent specified in InflowWind (if a power law wind profile is used to add to the turbulence with native-Bladed or HAWC2 files), or - 2. Calculated by using the mean wind speeds at two points: the reference (hub) height and the uppermost height on the grid. \ No newline at end of file + 2. Calculated by using the mean wind speeds at two points: the reference (hub) height and the uppermost height on the grid. + +BoxExceedAllow flag +------------------- + +A feature was added to InflowWind to all for some requested points to lie +outside the full field wind grid. This allows for a continuous exptrapolation of +values beyond the grid that approaches an average level. + +Purpose +~~~~~~~ + +When InflowWind is coupled to OpenFAST, wind points corresponding to the free +vortex wake module (OLAF) in AeroDyn 15 and LidarSim module may be outside the +full-field wind data. No other wind data points may be outside the grid +(AeroDyn15 blades must be within the wind box). The wake from OLAF may over +time stray outside the full-field wind box, in which case it should be +sufficiently far from the turbine that any inacuracies in the reported wind +value should have little to no effect on the turbine. The method employed here +should allow the wake to continue evolving without flow reversals or other +oddities due to a discontinuity at the wind grid boundary. However, to limit +the impact of the approximation used, the wake should not be allowed to exit the +box until far from the turbine. + +The other use case is when the LidarSim requests data far from the turbine that +may lie outside the wind box, such as a yawed, or floating turbine where the +sensing beam periodically exits the wind box. + +Method +~~~~~~ + +During initialization, a flag and corresponding index are passed to tell IfW to +allow points in the requested position array to lie outside the full-field wind +and tower grids starting at this index. The values for these points are then +extrapolated using the data from the full-field wind as follows: + + 1. The average wind value at each Z height at each timestep is calculated and + stored during initialization (averaged across the Y dimension). + 2. Wind above the full field wind grid is linearly interpolated between the + value at the top of the grid the average of the top of the grid. This + linear interpolation zone extends from the top of grid to the top of the + grid + one half grid height (``FFZHWid``). Values beyond that are held + constant. + 3. Values beyond the +/-Y grid edges are linearly interpolated between the + value at the edge of the grid and the average for that Z elevation in the + grid. The interpolation zone is between the edge of the grid and one half + grid width further along Y at ``+/-2*FFYHWid``. + 4. When no tower data is present, the values below the grid are linearly + interpolated between the bottom of the grid and 0 at the ground. + 5. When tower data is present, points below the grid are interpolated between + the tower and grid and the ground (0 value at ``+/-2*FFYHWid``). Linear + interpolation is then used beyond the edge of the grid. + + +Testing with driver +~~~~~~~~~~~~~~~~~~~ + +To test this feature, the driver accepts the flag ``BoxExceedAllow`` and will +signal to InflowWind that all windgrid points may be beyond the edge of the +grid. To use this, setup a driver input file with an output wind grid that is +larger than the full-field grid from the wind file referenced in the +corresponding InflowWind input file. Then the following command can be used +(Linux syntax, Windows is slightly different): + +.. code-block:: bash + + > inflowwind_driver -BoxExceedAllow MyDriverFile.inp + +For a single YZ plane from the resulting wind grid output file at time T, the +results for extrapolated data points can be plotted and should show +characteristics similar to the following plots. + + +.. figure:: figs/FFWindExtrap--NoTower.png + :width: 90% + + Extrapolation of wind values beyond the full field wind grid when no tower data is present. The semi-transparent red planes indicate the edges of the full-field wind grid, and the red points are the locations of wind grid data in this example case. All other points shown on the surface are interpolated/extrapolated. + + +.. figure:: figs/FFWindExtrap--Tower.png + :widt: 90% + + Extrapolation of wind values beyond the full field wind grid when tower data is present. The semi-transparent red planes indicate the edges of th e full-field wind grid, blue semi-transparent plane indicates the tower grid, and the red points indcate the data points from the wind grid and tower. All other points shown on the surface are interpolated/extrapolated. + + diff --git a/docs/source/user/inflowwind/figs/FFWindExtrap--NoTower.png b/docs/source/user/inflowwind/figs/FFWindExtrap--NoTower.png new file mode 100644 index 0000000000000000000000000000000000000000..8d1746de8eb7a30d4940e49cf283ebaee55c934c GIT binary patch literal 136589 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 literal 0 HcmV?d00001 diff --git a/docs/source/user/inflowwind/figs/FFWindExtrap--Tower.png b/docs/source/user/inflowwind/figs/FFWindExtrap--Tower.png new file mode 100644 index 0000000000000000000000000000000000000000..1e871c3d1f468c9f550c016cf72af39938bf2d95 GIT binary patch literal 135967 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⪼fy_FB{IQ2H5lFVVAm6sZu%795+8doF$GXhY?^ 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 literal 0 HcmV?d00001 From 7f7596d73f685722d0747f1e9be5737178524dff Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 5 Oct 2021 09:38:06 -0600 Subject: [PATCH 20/51] IfW grid exceed: fix logic error for points outside box Missed a corner case --- modules/inflowwind/src/IfW_FFWind_Base.f90 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/inflowwind/src/IfW_FFWind_Base.f90 b/modules/inflowwind/src/IfW_FFWind_Base.f90 index ed9edab0b8..8ab37f2528 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base.f90 +++ b/modules/inflowwind/src/IfW_FFWind_Base.f90 @@ -642,8 +642,15 @@ SUBROUTINE GetZBounds() IF ( IZLO == 0 .AND. Z >= 1.0-TOL ) THEN Z = -1.0_ReKi IZLO = 1 + ELSEIF ( GridExceedAllow ) THEN + ! calculate new Z between top of grid and half zgrid height above top of grid (range of -1 to 1) + Z = 2.0_ReKi * ( Position(3)/p%GridBase ) - 1.0_ReKi + Z = max(Z,-1.0_ReKi) ! enforce ground boundary + IZLO = 0 ! ground + IZHI = 1 ! Bottom of grid + AboveGridBottom = .FALSE. ! this is below the grid bottom + GridExtrap = .true. ELSE - ! Given the first if statement, is it ever possible to end up here??? ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& TRIM(Num2LStr(Position(3)))//' m is below the grid).' ErrStat = ErrID_Fatal From 37cef069ea9f3f6076f90d51de1bbc1f29c94916 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 5 Oct 2021 12:13:48 -0600 Subject: [PATCH 21/51] IfW grid exceed: add rough test case placeholder --- 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 f19127ebd2..47d17b0896 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit f19127ebd2f82cc4f2c08ce40553d58d20050822 +Subproject commit 47d17b0896e9034176e1b919b2e5efde6b9724a2 From 6966ab97c48bb25cfd72c71cc0ff6595329707c4 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Tue, 5 Oct 2021 16:39:00 -0600 Subject: [PATCH 22/51] IfW grid exceed: add warning on first occurance --- modules/inflowwind/src/IfW_BladedFFWind.f90 | 2 +- modules/inflowwind/src/IfW_BladedFFWind.txt | 2 +- .../inflowwind/src/IfW_BladedFFWind_Types.f90 | 99 +++++++++++- modules/inflowwind/src/IfW_FFWind_Base.f90 | 24 ++- modules/inflowwind/src/IfW_FFWind_Base.txt | 2 + .../inflowwind/src/IfW_FFWind_Base_Types.f90 | 142 ++++++++++++++++++ modules/inflowwind/src/IfW_HAWCWind.f90 | 4 +- modules/inflowwind/src/IfW_HAWCWind.txt | 2 +- modules/inflowwind/src/IfW_HAWCWind_Types.f90 | 99 +++++++++++- modules/inflowwind/src/IfW_TSFFWind.f90 | 2 +- modules/inflowwind/src/IfW_TSFFWind.txt | 2 +- modules/inflowwind/src/IfW_TSFFWind_Types.f90 | 99 +++++++++++- 12 files changed, 446 insertions(+), 33 deletions(-) diff --git a/modules/inflowwind/src/IfW_BladedFFWind.f90 b/modules/inflowwind/src/IfW_BladedFFWind.f90 index fc655af876..698705c7bc 100644 --- a/modules/inflowwind/src/IfW_BladedFFWind.f90 +++ b/modules/inflowwind/src/IfW_BladedFFWind.f90 @@ -1896,7 +1896,7 @@ SUBROUTINE IfW_BladedFFWind_CalcOutput(Time, PositionXYZ, ParamData, Velocity, M - CALL IfW_FFWind_CalcOutput(Time, PositionXYZ, ParamData%FF, Velocity, ErrStat, ErrMsg) + CALL IfW_FFWind_CalcOutput(Time, PositionXYZ, ParamData%FF, MiscVars%FF, Velocity, ErrStat, ErrMsg) RETURN diff --git a/modules/inflowwind/src/IfW_BladedFFWind.txt b/modules/inflowwind/src/IfW_BladedFFWind.txt index 7e622e6630..80a9494be2 100644 --- a/modules/inflowwind/src/IfW_BladedFFWind.txt +++ b/modules/inflowwind/src/IfW_BladedFFWind.txt @@ -32,7 +32,7 @@ typedef ^ InitOutputType ReKi VFlowAngle # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType IntKi dummy - 0 - "An Index into the TData array" - +typedef ^ MiscVarType IfW_FFWind_MiscVarType FF - - - "Miscvar used in all full-field " - # ..... Parameters ................................................................................................................ # Define parameters here: diff --git a/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 b/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 index b540ee2f78..d399dd138e 100644 --- a/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 +++ b/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 @@ -55,7 +55,7 @@ MODULE IfW_BladedFFWind_Types ! ======================= ! ========= IfW_BladedFFWind_MiscVarType ======= TYPE, PUBLIC :: IfW_BladedFFWind_MiscVarType - INTEGER(IntKi) :: dummy = 0 !< An Index into the TData array [-] + TYPE(IfW_FFWind_MiscVarType) :: FF !< Miscvar used in all full-field [-] END TYPE IfW_BladedFFWind_MiscVarType ! ======================= ! ========= IfW_BladedFFWind_ParameterType ======= @@ -590,7 +590,9 @@ SUBROUTINE IfW_BladedFFWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrSta ! ErrStat = ErrID_None ErrMsg = "" - DstMiscData%dummy = SrcMiscData%dummy + CALL IfW_FFWind_CopyMisc( SrcMiscData%FF, DstMiscData%FF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE IfW_BladedFFWind_CopyMisc SUBROUTINE IfW_BladedFFWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -614,6 +616,8 @@ SUBROUTINE IfW_BladedFFWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpo DEALLOCATEpointers_local = .true. END IF + CALL IfW_FFWind_DestroyMisc( MiscData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE IfW_BladedFFWind_DestroyMisc SUBROUTINE IfW_BladedFFWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -651,7 +655,24 @@ SUBROUTINE IfW_BladedFFWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSta Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! dummy + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype + CALL IfW_FFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -679,8 +700,34 @@ SUBROUTINE IfW_BladedFFWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSta Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf(Int_Xferred) = InData%dummy - Int_Xferred = Int_Xferred + 1 + CALL IfW_FFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF END SUBROUTINE IfW_BladedFFWind_PackMisc SUBROUTINE IfW_BladedFFWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -709,8 +756,46 @@ SUBROUTINE IfW_BladedFFWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Err Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%dummy = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FFWind_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE IfW_BladedFFWind_UnPackMisc SUBROUTINE IfW_BladedFFWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/inflowwind/src/IfW_FFWind_Base.f90 b/modules/inflowwind/src/IfW_FFWind_Base.f90 index 8ab37f2528..8de07ba010 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base.f90 +++ b/modules/inflowwind/src/IfW_FFWind_Base.f90 @@ -56,7 +56,7 @@ MODULE IfW_FFWind_Base !==================================================================================================== !> This routine acts as a wrapper for the GetWindSpeed routine. It steps through the array of input !! positions and calls the GetWindSpeed routine to calculate the velocities at each point. -SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, Velocity, ErrStat, ErrMsg) +SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, m, Velocity, ErrStat, ErrMsg) IMPLICIT NONE @@ -65,6 +65,7 @@ SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, Velocity, ErrStat, ErrMsg REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation REAL(ReKi), INTENT(IN ) :: PositionXYZ(:,:) !< Array of XYZ coordinates, 3xN TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(IfW_FFWind_MiscVarType), INTENT(INOUT) :: m !< MiscVar REAL(ReKi), INTENT(INOUT) :: Velocity(:,:) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) ! Error handling @@ -74,6 +75,7 @@ SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, Velocity, ErrStat, ErrMsg ! local variables INTEGER(IntKi) :: NumPoints ! Number of points specified by the PositionXYZ array LOGICAL :: GridExceedAllow ! is this point allowed to exceed bounds of wind grid + LOGICAL :: GridExtrap ! did this point fall outside the wind box and get extrapolated? ! local counters INTEGER(IntKi) :: PointNum ! a loop counter for the current point @@ -110,7 +112,7 @@ SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, Velocity, ErrStat, ErrMsg GridExceedAllow = p%BoxExceedAllowF .and. ( PointNum >= p%BoxExceedAllowIdx ) ! Calculate the velocity for the position - Velocity(:,PointNum) = FFWind_Interp(Time,PositionXYZ(:,PointNum),p,GridExceedAllow,TmpErrStat,TmpErrMsg) + Velocity(:,PointNum) = FFWind_Interp(Time,PositionXYZ(:,PointNum),p,GridExceedAllow,GridExtrap,TmpErrStat,TmpErrMsg) ! Error handling IF (TmpErrStat /= ErrID_None) THEN ! adding this so we don't have to convert numbers to strings every time @@ -124,6 +126,20 @@ SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, Velocity, ErrStat, ErrMsg !OMP END CRITICAL END IF + if (GridExceedAllow .and. GridExtrap .and. (.not. m%BoxExceedWarned)) then + !$OMP CRITICAL ! Needed to avoid data race on issuing warning + call WrScr( "WARNING from InflowWind:") + call WrScr( "------------------------") + call WrScr( " Grid point extrapolated beyond bounds of full-field wind grid [position=(" // & + TRIM(Num2LStr(PositionXYZ(1,PointNum)))//", "//TRIM(Num2LStr(PositionXYZ(2,PointNum)))//", " // & + TRIM(Num2LStr(PositionXYZ(3,PointNum)))//") in wind-file coordinates, T="//trim(Num2LStr(Time))//"]."//NewLine// & + "This only occurs for free vortex wake points or LidarSim measurement locations. " // & + "Use a larger full-field wind grid if the simulation yields undesirable results. Further warnings are suppressed.") + call WrScr( "------------------------") + m%BoxExceedWarned = .TRUE. + !$OMP END CRITICAL + endif + ENDDO !OMP END DO !OMP END PARALLEL @@ -157,7 +173,7 @@ END SUBROUTINE IfW_FFWind_CalcOutput !! 09/23/2009 - Modified by B. Jonkman to use arguments instead of modules to determine time and position. !! Height is now relative to the ground !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, ErrStat, ErrMsg) +FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, GridExtrap, ErrStat, ErrMsg) IMPLICIT NONE @@ -167,6 +183,7 @@ FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, ErrStat, ErrMsg) REAL(ReKi), INTENT(IN ) :: Position(3) !< takes the place of XGrnd, YGrnd, ZGrnd TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters LOGICAL, INTENT(IN ) :: GridExceedAllow ! is this point allowed to exceed bounds of wind grid + LOGICAL, INTENT(INOUT) :: GridExtrap ! Extrapolation outside grid is allowed and point lies outside grid REAL(ReKi) :: FFWind_Interp(3) !< The U, V, W velocities INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status @@ -227,7 +244,6 @@ FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, ErrStat, ErrMsg) LOGICAL :: GridExceedY ! point is beyond bounds of grid in Y. Interpolate to average Z level over one grid width if GridExceedAllow LOGICAL :: GridExceedZmax ! point is beyond upper bounds of grid in Z. Interpolate to average Z value at top of box over one half grid height if GridExceedAllow LOGICAL :: GridExceedZmin ! point is below lower bounds of grid in Z. Interpolate to average Z value at top of box over one half grid height if GridExceedAllow - LOGICAL :: GridExtrap ! Extrapolation outside grid is allowed and point lies outside grid above z_min !------------------------------------------------------------------------------------------------- ! Initialize variables diff --git a/modules/inflowwind/src/IfW_FFWind_Base.txt b/modules/inflowwind/src/IfW_FFWind_Base.txt index 622c057307..aade2e109a 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base.txt +++ b/modules/inflowwind/src/IfW_FFWind_Base.txt @@ -62,3 +62,5 @@ typedef ^ ^ ReKi RefLen typedef ^ ^ LOGICAL BoxExceedAllowF - .FALSE. - "Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim)" - typedef ^ ^ IntKi BoxExceedAllowIdx - -1 - "Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim)" - +# ..... MiscVar ................................................................................................................... +typedef ^ MiscVarType LOGICAL BoxExceedWarned - .FALSE. - "Has a warning been issued for points extrapolated beyond FFWind grid" - diff --git a/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 b/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 index 7a05fdc08c..f3c4e57a7c 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 +++ b/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 @@ -87,6 +87,11 @@ MODULE IfW_FFWind_Base_Types INTEGER(IntKi) :: BoxExceedAllowIdx = -1 !< Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim) [-] END TYPE IfW_FFWind_ParameterType ! ======================= +! ========= IfW_FFWind_MiscVarType ======= + TYPE, PUBLIC :: IfW_FFWind_MiscVarType + LOGICAL :: BoxExceedWarned = .FALSE. !< Has a warning been issued for points extrapolated beyond FFWind grid [-] + END TYPE IfW_FFWind_MiscVarType +! ======================= CONTAINS SUBROUTINE IfW_FFWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) TYPE(IfW_FFWind_InitInputType), INTENT(IN) :: SrcInitInputData @@ -879,5 +884,142 @@ SUBROUTINE IfW_FFWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Xferred = Int_Xferred + 1 END SUBROUTINE IfW_FFWind_UnPackParam + SUBROUTINE IfW_FFWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) + TYPE(IfW_FFWind_MiscVarType), INTENT(IN) :: SrcMiscData + TYPE(IfW_FFWind_MiscVarType), INTENT(INOUT) :: DstMiscData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_CopyMisc' +! + ErrStat = ErrID_None + ErrMsg = "" + DstMiscData%BoxExceedWarned = SrcMiscData%BoxExceedWarned + END SUBROUTINE IfW_FFWind_CopyMisc + + SUBROUTINE IfW_FFWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(IfW_FFWind_MiscVarType), INTENT(INOUT) :: MiscData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_DestroyMisc' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FFWind_DestroyMisc + + SUBROUTINE IfW_FFWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(IfW_FFWind_MiscVarType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_PackMisc' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! BoxExceedWarned + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedWarned, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IfW_FFWind_PackMisc + + SUBROUTINE IfW_FFWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(IfW_FFWind_MiscVarType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_UnPackMisc' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%BoxExceedWarned = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedWarned) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE IfW_FFWind_UnPackMisc + END MODULE IfW_FFWind_Base_Types !ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/IfW_HAWCWind.f90 b/modules/inflowwind/src/IfW_HAWCWind.f90 index a8f6b3aa82..3b544ff2d5 100644 --- a/modules/inflowwind/src/IfW_HAWCWind.f90 +++ b/modules/inflowwind/src/IfW_HAWCWind.f90 @@ -201,8 +201,6 @@ SUBROUTINE IfW_HAWCWind_Init(InitInp, p, MiscVars, Interval, InitOut, ErrStat, E WRITE(InitInp%SumFileUnit,'(F10.3,2x,F10.3,2x,F10.3)',IOSTAT=TmpErrStat) InitOut%sf ENDIF - MiscVars%DummyMiscVar = 0 - RETURN END SUBROUTINE IfW_HAWCWind_Init @@ -362,7 +360,7 @@ SUBROUTINE IfW_HAWCWind_CalcOutput(Time, PositionXYZ, p, Velocity, MiscVars, Err ! Initialize some things !------------------------------------------------------------------------------------------------- - CALL IfW_FFWind_CalcOutput(Time, PositionXYZ, p%FF, Velocity, ErrStat, ErrMsg) + CALL IfW_FFWind_CalcOutput(Time, PositionXYZ, p%FF, MiscVars%FF, Velocity, ErrStat, ErrMsg) RETURN END SUBROUTINE IfW_HAWCWind_CalcOutput diff --git a/modules/inflowwind/src/IfW_HAWCWind.txt b/modules/inflowwind/src/IfW_HAWCWind.txt index 41fa813893..56ad590bd9 100644 --- a/modules/inflowwind/src/IfW_HAWCWind.txt +++ b/modules/inflowwind/src/IfW_HAWCWind.txt @@ -39,7 +39,7 @@ typedef ^ OtherStateType ReKi DummyOtherStat # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi DummyMiscVar - - - "Remove this variable if you have misc variables" - +typedef ^ MiscVarType IfW_FFWind_MiscVarType FF - - - "Miscvar used in all full-field " - # ..... Parameters ................................................................................................................ # Define parameters here: diff --git a/modules/inflowwind/src/IfW_HAWCWind_Types.f90 b/modules/inflowwind/src/IfW_HAWCWind_Types.f90 index cbbadbd6d7..f091cbfead 100644 --- a/modules/inflowwind/src/IfW_HAWCWind_Types.f90 +++ b/modules/inflowwind/src/IfW_HAWCWind_Types.f90 @@ -75,7 +75,7 @@ MODULE IfW_HAWCWind_Types ! ======================= ! ========= IfW_HAWCWind_MiscVarType ======= TYPE, PUBLIC :: IfW_HAWCWind_MiscVarType - REAL(ReKi) :: DummyMiscVar !< Remove this variable if you have misc variables [-] + TYPE(IfW_FFWind_MiscVarType) :: FF !< Miscvar used in all full-field [-] END TYPE IfW_HAWCWind_MiscVarType ! ======================= ! ========= IfW_HAWCWind_ParameterType ======= @@ -1171,7 +1171,9 @@ SUBROUTINE IfW_HAWCWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, E ! ErrStat = ErrID_None ErrMsg = "" - DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar + CALL IfW_FFWind_CopyMisc( SrcMiscData%FF, DstMiscData%FF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE IfW_HAWCWind_CopyMisc SUBROUTINE IfW_HAWCWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -1195,6 +1197,8 @@ SUBROUTINE IfW_HAWCWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointe DEALLOCATEpointers_local = .true. END IF + CALL IfW_FFWind_DestroyMisc( MiscData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE IfW_HAWCWind_DestroyMisc SUBROUTINE IfW_HAWCWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -1232,7 +1236,24 @@ SUBROUTINE IfW_HAWCWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyMiscVar + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype + CALL IfW_FFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1260,8 +1281,34 @@ SUBROUTINE IfW_HAWCWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Db_Xferred = 1 Int_Xferred = 1 - ReKiBuf(Re_Xferred) = InData%DummyMiscVar - Re_Xferred = Re_Xferred + 1 + CALL IfW_FFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF END SUBROUTINE IfW_HAWCWind_PackMisc SUBROUTINE IfW_HAWCWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -1290,8 +1337,46 @@ SUBROUTINE IfW_HAWCWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%DummyMiscVar = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FFWind_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE IfW_HAWCWind_UnPackMisc SUBROUTINE IfW_HAWCWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/inflowwind/src/IfW_TSFFWind.f90 b/modules/inflowwind/src/IfW_TSFFWind.f90 index 9be1015599..4547282c05 100644 --- a/modules/inflowwind/src/IfW_TSFFWind.f90 +++ b/modules/inflowwind/src/IfW_TSFFWind.f90 @@ -629,7 +629,7 @@ SUBROUTINE IfW_TSFFWind_CalcOutput(Time, PositionXYZ, p, Velocity, MiscVars, Er - CALL IfW_FFWind_CalcOutput(Time, PositionXYZ, p%FF, Velocity, ErrStat, ErrMsg) + CALL IfW_FFWind_CalcOutput(Time, PositionXYZ, p%FF, MiscVars%FF, Velocity, ErrStat, ErrMsg) RETURN diff --git a/modules/inflowwind/src/IfW_TSFFWind.txt b/modules/inflowwind/src/IfW_TSFFWind.txt index 2d5e88d81a..b0859a3d62 100644 --- a/modules/inflowwind/src/IfW_TSFFWind.txt +++ b/modules/inflowwind/src/IfW_TSFFWind.txt @@ -25,7 +25,7 @@ typedef ^ InitOutputType ProgDesc Ver # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType IntKi dummy - 0 - "An Index into the TData array" - +typedef ^ MiscVarType IfW_FFWind_MiscVarType FF - - - "Miscvar used in all full-field " - # ..... Parameters ................................................................................................................ # Define parameters here: diff --git a/modules/inflowwind/src/IfW_TSFFWind_Types.f90 b/modules/inflowwind/src/IfW_TSFFWind_Types.f90 index b142f61a67..0142c4da0f 100644 --- a/modules/inflowwind/src/IfW_TSFFWind_Types.f90 +++ b/modules/inflowwind/src/IfW_TSFFWind_Types.f90 @@ -48,7 +48,7 @@ MODULE IfW_TSFFWind_Types ! ======================= ! ========= IfW_TSFFWind_MiscVarType ======= TYPE, PUBLIC :: IfW_TSFFWind_MiscVarType - INTEGER(IntKi) :: dummy = 0 !< An Index into the TData array [-] + TYPE(IfW_FFWind_MiscVarType) :: FF !< Miscvar used in all full-field [-] END TYPE IfW_TSFFWind_MiscVarType ! ======================= ! ========= IfW_TSFFWind_ParameterType ======= @@ -531,7 +531,9 @@ SUBROUTINE IfW_TSFFWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, E ! ErrStat = ErrID_None ErrMsg = "" - DstMiscData%dummy = SrcMiscData%dummy + CALL IfW_FFWind_CopyMisc( SrcMiscData%FF, DstMiscData%FF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE IfW_TSFFWind_CopyMisc SUBROUTINE IfW_TSFFWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -555,6 +557,8 @@ SUBROUTINE IfW_TSFFWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointe DEALLOCATEpointers_local = .true. END IF + CALL IfW_FFWind_DestroyMisc( MiscData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE IfW_TSFFWind_DestroyMisc SUBROUTINE IfW_TSFFWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -592,7 +596,24 @@ SUBROUTINE IfW_TSFFWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! dummy + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype + CALL IfW_FFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FF + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FF + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FF + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -620,8 +641,34 @@ SUBROUTINE IfW_TSFFWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf(Int_Xferred) = InData%dummy - Int_Xferred = Int_Xferred + 1 + CALL IfW_FFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF END SUBROUTINE IfW_TSFFWind_PackMisc SUBROUTINE IfW_TSFFWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -650,8 +697,46 @@ SUBROUTINE IfW_TSFFWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%dummy = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FFWind_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE IfW_TSFFWind_UnPackMisc SUBROUTINE IfW_TSFFWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) From 17530fd9ef60c651897e45d866684afe628ab4c5 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 11 Oct 2021 15:20:53 -0600 Subject: [PATCH 23/51] Ifw grid exceed: fix logic error at grid boundary The tolerance check for the bottom edge of the grid should be scaled to match the other tolerance specs --- modules/inflowwind/src/IfW_FFWind_Base.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/inflowwind/src/IfW_FFWind_Base.f90 b/modules/inflowwind/src/IfW_FFWind_Base.f90 index 8de07ba010..4c8c384140 100644 --- a/modules/inflowwind/src/IfW_FFWind_Base.f90 +++ b/modules/inflowwind/src/IfW_FFWind_Base.f90 @@ -655,7 +655,7 @@ SUBROUTINE GetZBounds() Z = 2.0_ReKi * (ZGRID - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi IF ( IZLO < 1 ) THEN - IF ( IZLO == 0 .AND. Z >= 1.0-TOL ) THEN + IF ( IZLO == 0 .AND. Z >= 1.0-TOL/p%InvFFZD ) THEN ! Just below bottom edge, but within tolerance Z = -1.0_ReKi IZLO = 1 ELSEIF ( GridExceedAllow ) THEN From 5f7e540cfa68cd5351c0c012352782c0ea8601af Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Mon, 20 Mar 2023 14:35:22 -0600 Subject: [PATCH 24/51] docs: mispell on figure option `width` --- docs/source/user/inflowwind/driver.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/user/inflowwind/driver.rst b/docs/source/user/inflowwind/driver.rst index 937760baf9..0712f8a8dc 100644 --- a/docs/source/user/inflowwind/driver.rst +++ b/docs/source/user/inflowwind/driver.rst @@ -217,7 +217,7 @@ characteristics similar to the following plots. .. figure:: figs/FFWindExtrap--Tower.png - :widt: 90% + :width: 90% Extrapolation of wind values beyond the full field wind grid when tower data is present. The semi-transparent red planes indicate the edges of th e full-field wind grid, blue semi-transparent plane indicates the tower grid, and the red points indcate the data points from the wind grid and tower. All other points shown on the surface are interpolated/extrapolated. From e3df8c03b1cabd2c9584739508547051459d3e27 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Mon, 27 Mar 2023 21:10:26 +0000 Subject: [PATCH 25/51] Changed InflowWind to use new FlowField type Also removed all redundant modules. --- modules/inflowwind/CMakeLists.txt | 43 +- modules/inflowwind/src/CTWind.f90 | 1345 ------- modules/inflowwind/src/FDWind.f90 | 1300 ------ modules/inflowwind/src/FlowField_IO_Types.f90 | 3534 ----------------- modules/inflowwind/src/IfW_4Dext.f90 | 369 -- modules/inflowwind/src/IfW_4Dext.txt | 39 - modules/inflowwind/src/IfW_4Dext_Types.f90 | 879 ---- modules/inflowwind/src/IfW_BladedFFWind.f90 | 1925 --------- modules/inflowwind/src/IfW_BladedFFWind.txt | 41 - .../inflowwind/src/IfW_BladedFFWind_Types.f90 | 847 ---- modules/inflowwind/src/IfW_FFWind_Base.f90 | 1205 ------ modules/inflowwind/src/IfW_FFWind_Base.txt | 59 - .../inflowwind/src/IfW_FFWind_Base_Types.f90 | 777 ---- modules/inflowwind/src/IfW_FlowField.f90 | 381 +- modules/inflowwind/src/IfW_FlowField.txt | 16 +- .../inflowwind/src/IfW_FlowField_Types.f90 | 357 +- modules/inflowwind/src/IfW_HAWCWind.f90 | 390 -- modules/inflowwind/src/IfW_HAWCWind.txt | 52 - modules/inflowwind/src/IfW_HAWCWind_Types.f90 | 1720 -------- modules/inflowwind/src/IfW_TSFFWind.f90 | 661 --- modules/inflowwind/src/IfW_TSFFWind.txt | 33 - modules/inflowwind/src/IfW_TSFFWind_Types.f90 | 788 ---- modules/inflowwind/src/IfW_UniformWind.f90 | 1333 ------- modules/inflowwind/src/IfW_UniformWind.txt | 67 - .../inflowwind/src/IfW_UniformWind_Types.f90 | 1546 ------- modules/inflowwind/src/IfW_UserWind.f90 | 282 -- modules/inflowwind/src/IfW_UserWind.txt | 36 - modules/inflowwind/src/IfW_UserWind_Types.f90 | 695 ---- modules/inflowwind/src/InflowWind.f90 | 1626 +++----- modules/inflowwind/src/InflowWind.txt | 79 +- modules/inflowwind/src/InflowWind_Driver.f90 | 72 +- .../inflowwind/src/InflowWind_Driver_Subs.f90 | 187 + .../src/InflowWind_Driver_Types.f90 | 1 - .../{FlowField_IO.f90 => InflowWind_IO.f90} | 763 ++-- .../{FlowField_IO.txt => InflowWind_IO.txt} | 94 +- .../inflowwind/src/InflowWind_IO_Types.f90 | 2209 +++++++++++ modules/inflowwind/src/InflowWind_Subs.f90 | 368 +- modules/inflowwind/src/InflowWind_Types.f90 | 2163 ++-------- modules/inflowwind/tests/ifw_test_tools.F90 | 6 +- modules/inflowwind/tests/test_outputs.F90 | 2 +- modules/inflowwind/tests/test_steady_wind.F90 | 2 +- .../inflowwind/tests/test_uniform_wind.F90 | 12 +- reg_tests/r-test | 2 +- 43 files changed, 4509 insertions(+), 23797 deletions(-) delete mode 100644 modules/inflowwind/src/CTWind.f90 delete mode 100644 modules/inflowwind/src/FDWind.f90 delete mode 100644 modules/inflowwind/src/FlowField_IO_Types.f90 delete mode 100644 modules/inflowwind/src/IfW_4Dext.f90 delete mode 100644 modules/inflowwind/src/IfW_4Dext.txt delete mode 100644 modules/inflowwind/src/IfW_4Dext_Types.f90 delete mode 100644 modules/inflowwind/src/IfW_BladedFFWind.f90 delete mode 100644 modules/inflowwind/src/IfW_BladedFFWind.txt delete mode 100644 modules/inflowwind/src/IfW_BladedFFWind_Types.f90 delete mode 100644 modules/inflowwind/src/IfW_FFWind_Base.f90 delete mode 100644 modules/inflowwind/src/IfW_FFWind_Base.txt delete mode 100644 modules/inflowwind/src/IfW_FFWind_Base_Types.f90 delete mode 100644 modules/inflowwind/src/IfW_HAWCWind.f90 delete mode 100644 modules/inflowwind/src/IfW_HAWCWind.txt delete mode 100644 modules/inflowwind/src/IfW_HAWCWind_Types.f90 delete mode 100644 modules/inflowwind/src/IfW_TSFFWind.f90 delete mode 100644 modules/inflowwind/src/IfW_TSFFWind.txt delete mode 100644 modules/inflowwind/src/IfW_TSFFWind_Types.f90 delete mode 100644 modules/inflowwind/src/IfW_UniformWind.f90 delete mode 100644 modules/inflowwind/src/IfW_UniformWind.txt delete mode 100644 modules/inflowwind/src/IfW_UniformWind_Types.f90 delete mode 100644 modules/inflowwind/src/IfW_UserWind.f90 delete mode 100644 modules/inflowwind/src/IfW_UserWind.txt delete mode 100644 modules/inflowwind/src/IfW_UserWind_Types.f90 rename modules/inflowwind/src/{FlowField_IO.f90 => InflowWind_IO.f90} (81%) rename modules/inflowwind/src/{FlowField_IO.txt => InflowWind_IO.txt} (76%) create mode 100644 modules/inflowwind/src/InflowWind_IO_Types.f90 diff --git a/modules/inflowwind/CMakeLists.txt b/modules/inflowwind/CMakeLists.txt index 2c2f537ec3..bbedac86a2 100644 --- a/modules/inflowwind/CMakeLists.txt +++ b/modules/inflowwind/CMakeLists.txt @@ -15,51 +15,28 @@ # if (GENERATE_TYPES) - generate_f90_types(src/InflowWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/InflowWind_Types.f90) - generate_f90_types(src/Lidar.txt ${CMAKE_CURRENT_LIST_DIR}/src/Lidar_Types.f90) - generate_f90_types(src/IfW_BladedFFWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_BladedFFWind_Types.f90 -noextrap) - generate_f90_types(src/IfW_4Dext.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_4Dext_Types.f90 -noextrap) - generate_f90_types(src/IfW_HAWCWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_HAWCWind_Types.f90 -noextrap) - generate_f90_types(src/IfW_TSFFWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_TSFFWind_Types.f90 -noextrap) - generate_f90_types(src/IfW_UniformWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_UniformWind_Types.f90 -noextrap) - generate_f90_types(src/IfW_UserWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_UserWind_Types.f90 -noextrap) - generate_f90_types(src/IfW_FFWind_Base.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_FFWind_Base_Types.f90 -noextrap) generate_f90_types(src/IfW_FlowField.txt ${CMAKE_CURRENT_LIST_DIR}/src/IfW_FlowField_Types.f90 -noextrap) - generate_f90_types(src/FlowField_IO.txt ${CMAKE_CURRENT_LIST_DIR}/src/FlowField_IO_Types.f90 -noextrap) + generate_f90_types(src/InflowWind_IO.txt ${CMAKE_CURRENT_LIST_DIR}/src/InflowWind_IO_Types.f90 -noextrap) + generate_f90_types(src/Lidar.txt ${CMAKE_CURRENT_LIST_DIR}/src/Lidar_Types.f90) + generate_f90_types(src/InflowWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/InflowWind_Types.f90) endif() -set(IFW_SOURCES +add_library(ifwlib src/IfW_FlowField_Types.f90 src/IfW_FlowField.f90 - src/FlowField_IO_Types.f90 - src/FlowField_IO.f90 - src/IfW_BladedFFWind.f90 - src/IfW_4Dext.f90 - src/IfW_HAWCWind.f90 - src/IfW_TSFFWind.f90 - src/IfW_UserWind.f90 - src/IfW_UniformWind.f90 + src/InflowWind_IO_Types.f90 + src/InflowWind_IO.f90 src/InflowWind_Subs.f90 - src/InflowWind.f90 - src/Lidar.f90 - src/IfW_FFWind_Base.f90 - src/IfW_FFWind_Base_Types.f90 - src/IfW_BladedFFWind_Types.f90 - src/IfW_4Dext_Types.f90 - src/IfW_HAWCWind_Types.f90 - src/IfW_TSFFWind_Types.f90 - src/IfW_UserWind_Types.f90 - src/IfW_UniformWind_Types.f90 src/InflowWind_Types.f90 + src/InflowWind.f90 src/Lidar_Types.f90 + src/Lidar.f90 ) - -add_library(ifwlib ${IFW_SOURCES}) target_link_libraries(ifwlib nwtclibs) # C-bound interface library add_library(ifw_c_binding SHARED src/IfW_C_Binding.f90) -target_link_libraries(ifw_c_binding ifwlib versioninfolib ${CMAKE_DL_LIBS}) +target_link_libraries(ifw_c_binding ifwlib versioninfolib) if(APPLE OR UNIX) target_compile_definitions(ifw_c_binding PUBLIC -DIMPLICIT_DLLEXPORT) endif() @@ -71,7 +48,7 @@ set(IFW_DRIVER_SOURCES ) add_executable(inflowwind_driver ${IFW_DRIVER_SOURCES}) -target_link_libraries(inflowwind_driver ifwlib versioninfolib ${CMAKE_DL_LIBS}) +target_link_libraries(inflowwind_driver ifwlib versioninfolib) install(TARGETS inflowwind_driver ifwlib ifw_c_binding EXPORT "${CMAKE_PROJECT_NAME}Libraries" diff --git a/modules/inflowwind/src/CTWind.f90 b/modules/inflowwind/src/CTWind.f90 deleted file mode 100644 index b0adc411c7..0000000000 --- a/modules/inflowwind/src/CTWind.f90 +++ /dev/null @@ -1,1345 +0,0 @@ -MODULE CTWind -! This module uses reads coherent turbulence parameter (CTP) files and processes the data in them -! to get coherent turbulence which is later superimposed on a background wind field (the super- -! positioning occurs elsewhere). The turbulence in this module is part of the KH billow, which -! can be read using FDWind. As a result, the scaling here should be similiar to FDWind. -! -! This module assumes that the origin, (0,0,0), is located at the tower centerline at ground level, -! and that all units are specified in the metric system (using meters and seconds). -! Data is shifted by half the grid width when used with FFWind. -! -! Created 25-Sept-2009 by B. Jonkman, National Renewable Energy Laboratory -! using subroutines and modules from AeroDyn v12.58 -! -! Modified Jan-2013 by A. Platt, National Renewable Energy Laboratory -! to fit the modularization framework used by FAST -! -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2013 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** -! File last committed: $Date: 2014-07-29 13:30:04 -0600 (Tue, 29 Jul 2014) $ -! (File) Revision #: $Rev: 125 $ -! URL: $HeadURL$ -!********************************************************************************************************************************** - - USE NWTC_Library - USE SharedInflowDefs - USE InflowWind_Module_Types - - IMPLICIT NONE - PRIVATE - - -!fixme: this invokes SAVE - INTEGER, PARAMETER :: NumComps = 3 ! number of components - - ! CT_Wind - REAL(ReKi) :: DelYCTgrid ! The nondimensional distance between grid points in the y direction. - REAL(ReKi) :: DelZCTgrid ! The nondimensional distance between grid points in the z direction. - REAL(ReKi) :: CTDistSc ! Disturbance scale (ratio of wave height to rotor diameter). - REAL(ReKi) :: CTOffset (NumComps) ! Offsets to convert integer data to actual wind speeds. - REAL(ReKi) :: CTScale (NumComps) ! Scaling factors to convert integer data to actual wind speeds. - - - REAL(ReKi), ALLOCATABLE :: CTvelU (:,:,:) ! The y-z grid velocity data (U components) for the lower- and upper-bound time slices - REAL(ReKi), ALLOCATABLE :: CTvelV (:,:,:) ! The y-z grid velocity data (V components) for the lower- and upper-bound time slices - REAL(ReKi), ALLOCATABLE :: CTvelW (:,:,:) ! The y-z grid velocity data (W components) for the lower- and upper-bound time slices - REAL(ReKi) :: CTLy ! Fractional location of tower centerline from right (looking downwind) to left side of the dataset. - REAL(ReKi) :: CTLz ! Fractional location of hub height from bottom to top of dataset. - REAL(ReKi) :: CTScaleVel ! Scaling velocity, U0. 2*U0 is the difference in wind speed between the top and bottom of the wave. - REAL(ReKi), ALLOCATABLE :: Tdata (:) ! The list of times for the CT-wind input files. - - REAL(ReKi) :: CT_Zref ! The reference height for the CT file (the bottom of the billow) - REAL(ReKi) :: CTYHWid ! The half the width of the background dataset, used to compute the CTwind time offset - REAL(ReKi) :: CTYmax ! The dimensional lateral width of the dataset. - REAL(ReKi) :: CTYt ! Distance of the tower from the right side of the dataset (looking downwind). - REAL(ReKi) :: CTZmax ! The dimensional vertical height of the dataset. - REAL(ReKi) :: InvMCTWS ! The multiplicative inverse of the mean hub height wind speed for the CT wind data - - INTEGER :: CT_DF_Y ! The decimation factor for the CT wind data in the y direction. - INTEGER :: CT_DF_Z ! The decimation factor for the CT wind data in the z direction. - INTEGER :: CTvel_files(2) ! Times for the CT wind files stored in CTvel arrays. - - INTEGER :: IndCT_hi ! An index into the 3rd dimension of the CTvel arrays, indicating the upper time slice (allows us to avoid copying array) - INTEGER :: IndCT_lo ! An index into the 3rd dimension of the CTvel arrays, indicating the lower time slice (allows us to avoid copying array) - - INTEGER :: NumCTt ! The number of CT wind grids, no more than one grid per time step. - INTEGER :: NumCTy ! The number of CT wind grid points in the y direction. - INTEGER :: NumCTyD ! The decimated number of CT wind grid points in the y direction. - INTEGER :: NumCTyD1 ! The decimated number of CT wind grid points in the y direction minus 1. - INTEGER :: NumCTz ! The number of CT wind grid points in the z direction. - INTEGER :: NumCTzD ! The decimated number of CT wind grid points in the z direction. - INTEGER :: NumCTzD1 ! The decimated number of CT wind grid points in the z direction minus 1. -!FIXME: move to otherstate - INTEGER, SAVE :: TimeIndx = 0 ! Index into the time array - INTEGER, ALLOCATABLE :: TimeStpCT (:) ! The list of time steps from the original LE simulation, associated with the CT-wind times. - - INTEGER :: CTWindUnit ! unit number used to read the wind files at each call to CT_GetWindSpeed() - - LOGICAL :: CTVertShft ! Flag to indicate whether or not to shift the z values for the w component. - - CHARACTER(3) :: CText ! The extension used for coherent turbulence data files. (usually "les" or "dns") - CHARACTER(1024) :: CTSpath ! The path to the CT wind files. - -!FIXME: move this to types -- parameters! - TYPE :: CTWindFiles - CHARACTER(1024) :: CTfile ! The name of the file containing the time-step history of the wind files. - CHARACTER(1024) :: CTbackgr ! The name of the background wind data - END TYPE CTWindFiles - -!FIXME: this should be moved to parameters. - TYPE, PUBLIC :: CT_Backgr -! TYPE :: CT_Backgr - CHARACTER(1024) :: WindFile ! The name of the background wind file - INTEGER :: WindFileType ! The type of background wind file (currently only FF) - LOGICAL :: CoherentStr ! If the coherent time step file is blank or doesn't exist, this is FALSE (use the background only) - END TYPE CT_Backgr - - - PUBLIC :: CT_Init - PUBLIC :: CT_GetWindSpeed - PUBLIC :: CT_SetRefVal - PUBLIC :: CT_Terminate - -CONTAINS -!==================================================================================================== -SUBROUTINE CT_Init(UnWind, WindFile, BackGrndValues, ErrStat, ErrMsg) -! This subroutine is called at the beginning of a simulation. It reads the CTP file to obtain -! the name of the CTS file, the path locating the binary KH files, and decimation factors. -! It returns the background wind file and type; it also returns a flag that determines if CT wind -! files are ACTUALLY to be used (e.g., if the CTS file is blank or there is one line of zero in the -! CTS time array). -!---------------------------------------------------------------------------------------------------- - - ! Passed Variables: - - INTEGER, INTENT(IN) :: UnWind ! unit number for reading wind files - CHARACTER(*), INTENT(IN) :: WindFile ! Name of the CTP (.ctp) wind file - TYPE(CT_Backgr), INTENT(OUT) :: BackGrndValues ! output background values - INTEGER, INTENT(OUT) :: ErrStat ! return ErrID_None if no errors - CHARACTER(*), INTENT(OUT) :: ErrMsg ! message if there was an error - - ! Local Variables: - - TYPE(CTWindFiles) :: CTP_files - CHARACTER(3) :: CT_SC_ext ! extension of the scaling file - LOGICAL :: EmptyFileStat ! temporary variable indicating the CT file was empty / non-existent - - ! Temporary error handling Variables - - INTEGER :: TmpErrStat ! Temporary Error Status - CHARACTER(LEN(ErrMsg)) :: TmpErrMsg ! Temporary error message returned - - - - !------------------------------------------------------------------------------------------------- - ! Initialize temporary variables - !------------------------------------------------------------------------------------------------- - - TmpErrStat = ErrID_None - TmpErrMsg = '' - - !------------------------------------------------------------------------------------------------- - ! Check that the module hasn't already been initialized. - !------------------------------------------------------------------------------------------------- - - IF ( TimeIndx /= 0 ) THEN - ErrMsg = ' CTWind has already been initialized.' - ErrStat = ErrID_Fatal - RETURN - ELSE - ErrMsg = '' - ErrStat = ErrID_None - END IF - - - !------------------------------------------------------------------------------------------------- - ! Read the CTP file and set the background data info to be returned later - !------------------------------------------------------------------------------------------------- - - CALL ReadCTP( UnWind, WindFile, CTP_files, TmpErrStat, TmpErrMsg ) - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - BackGrndValues%WindFile = CTP_files%CTbackgr - BackGrndValues%WindFileType = FF_Wind !bjj: perhaps we should check the wind type here - - - !------------------------------------------------------------------------------------------------- - ! Read the CT file to get the time step and file number arrays - !------------------------------------------------------------------------------------------------- - - CALL ReadCT( UnWind, CTP_files%CTfile, CT_SC_ext, EmptyFileStat, TmpErrStat, TmpErrMsg ) - - ! Errors check - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! If the CTP_files%CTfile was empty or non-existent, we continue on without it. - - IF ( EmptyFileStat ) THEN - - ! The file is missing, blank (or possibly incomplete), or has only 1 time step line (which - ! is zero); Go on without the CT file, using just the background - - ErrMsg = TRIM(ErrMsg)//' '//'Coherent turbulence wind file will be turned off.' - - BackGrndValues%CoherentStr = .FALSE. - CALL CT_Terminate( TmpErrStat, TmpErrMsg ) - - ! Error check - ErrStat = MAX( ErrStat, TmpErrStat ) - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - IF ( ErrStat >= AbortErrLev ) RETURN - - - RETURN - - ELSEIF ( (ErrStat < AbortErrLev) .AND. NumCTt > 1) THEN - BackGrndValues%CoherentStr = .TRUE. - - !------------------------------------------------------------------------------------------------- - ! Read file containing scaling for the binary large-eddy files - !------------------------------------------------------------------------------------------------- - CALL ReadCTScales( UnWind, TRIM( CTSpath )//'\Scales.'//TRIM( CT_SC_ext ), TmpErrStat, TmpErrMsg ) - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CTScale(:) = CTScaleVel*CTScale(:) - CTOffset(:) = CTScaleVel*CTOffset(:) - - END IF - - - !------------------------------------------------------------------------------------------------- - ! Set some values that don't change during the run - !------------------------------------------------------------------------------------------------- - - CTYHWid = 0.0 ! This value is used to perform a time shift (the equivalent distance of FFYHWid [approx. rotor radius]) - CT_Zref = -1.0 ! This value needs to be set after the corresponding background turbulence has been read (or the CTS file should be changed) - - NumCTyD = ( NumCTy + CT_DF_Y - 1 )/CT_DF_Y ! The decimated number of CT wind grid points in the y direction. - NumCTzD = ( NumCTz + CT_DF_Z - 1 )/CT_DF_Z ! The decimated number of CT wind grid points in the z direction. - NumCTyD1 = NumCTyD - 1 ! The decimated number of CT wind grid points in the y direction minus 1. - NumCTzD1 = NumCTzD - 1 ! The decimated number of CT wind grid points in the z direction minus 1. - - CTYt = CTYmax*CTLy ! Distance of the tower from the right side of the dataset (looking downwind). -! CTZt = CTZmax*CTLz ! Distance of the hub from the bottom of the dataset. - DelYCTgrid = 1.0/NumCTyD1 ! The nondimensional distance between grid points in the y direction. - DelZCTgrid = 1.0/NumCTzD1 ! The nondimensional distance between grid points in the z direction. - - - - !------------------------------------------------------------------------------------------------- - ! Allocate the wind array and initialize it - !------------------------------------------------------------------------------------------------- - - IF (.NOT. ALLOCATED(CTvelU) ) THEN - ALLOCATE ( CTvelU(NumCTyD,NumCTzD,2), STAT=TmpErrStat ) - - IF ( TmpErrStat /= 0 ) THEN - ErrMsg = TRIM(ErrMsg)//' Error allocating memory for the CTvelU array.' - ErrStat = ErrID_Fatal - RETURN - END IF - END IF - - IF (.NOT. ALLOCATED(CTvelV) ) THEN -! CALL AllocAry( CTvelV, NumCTyD, NumCTzD, 2, 'CTvelV', ErrStat ) !AllRAry3 AllocAry - ALLOCATE ( CTvelV(NumCTyD,NumCTzD,2), STAT=TmpErrStat ) - - IF ( TmpErrStat /= 0 ) THEN - ErrMsg = TRIM(ErrMsg)//' Error allocating memory for the CTvelV array.' - ErrStat = ErrID_Fatal - RETURN - END IF - END IF - - IF (.NOT. ALLOCATED(CTvelW) ) THEN -! CALL AllocAry( CTvelW, NumCTyD, NumCTzD, 2, 'CTvelW', ErrStat ) !AllRAry3 AllocAry - ALLOCATE ( CTvelW(NumCTyD,NumCTzD,2), STAT=TmpErrStat ) - - IF ( TmpErrStat /= 0 ) THEN - ErrMsg = TRIM(ErrMsg)//' Error allocating memory for the CTvelW array.' - ErrStat = ErrID_Fatal - RETURN - END IF - END IF - - CTvelU(:,:,:) = 0.0 ! the original velocity data - CTvelV(:,:,:) = 0.0 ! the original velocity data - CTvelW(:,:,:) = 0.0 ! the original velocity data - - !------------------------------------------------------------------------------------------------- - ! Initialize the arrays and set the initialization flag - !------------------------------------------------------------------------------------------------- - CTvel_files(:) = 0 ! the name of the files currently in the CTvel array - CTWindUnit = UnWind ! This unit is needed to open the binary files at each step - TimeIndx = 1 - - RETURN - -END SUBROUTINE CT_Init -!==================================================================================================== -SUBROUTINE CT_SetRefVal(Height, HWidth, ErrStat, ErrMsg) - - REAL(ReKi), INTENT(IN) :: Height ! a reference height (should be hub height) - REAL(ReKi), INTENT(IN), OPTIONAL :: HWidth ! a reference offset (should be half grid width [~rotor radius]) - INTEGER, INTENT(OUT) :: ErrStat ! returns ErrID_None if no errors, nonzero otherwise - CHARACTER(*), INTENT(OUT) :: ErrMsg ! Message to return about the error - - - !------------------------------------------------------------------------------------------------- - ! Check that we've initialized everything first - !------------------------------------------------------------------------------------------------- - - IF ( TimeIndx == 0 ) THEN - ErrMsg = ' Initialialize the CTWind module before calling its subroutines.' - ErrStat = ErrID_Fatal - RETURN - ELSE IF ( CT_Zref >= 0 ) THEN - ErrMsg = ' Cannot reset the CTWind reference height in the middle of a simulation.' - ErrStat = ErrID_Fatal - RETURN - ELSE - ErrStat = ErrID_None - END IF - - - !------------------------------------------------------------------------------------------------- - ! Set the grid shift using the half-width - !------------------------------------------------------------------------------------------------- - IF ( PRESENT( HWidth ) ) THEN - CTYHWid = HWidth - - IF ( CTYHWid < 0 ) THEN - ErrMsg = TRIM(ErrMsg)//' Reference width in CTWind cannot be negative.' - CTYHWid = 0 - ErrStat = ErrID_Fatal - END IF - END IF - - - !------------------------------------------------------------------------------------------------- - ! Set the reference height (bottom of the KH billow) using the input hub-height - !------------------------------------------------------------------------------------------------- - ! CTZt = CTZmax*CTLz ! the distance between the hub and the bottom of the dataset - - CT_Zref = Height - CTZmax*CTLz ! the height of the bottom of the KH billow - - IF ( CT_Zref < 0 ) THEN - ErrMsg = TRIM(ErrMsg)//' Reference height in CTWind cannot be negative.' - CT_Zref = 0 - ErrStat = ErrID_Fatal - END IF - - -END SUBROUTINE CT_SetRefVal -!==================================================================================================== -FUNCTION CT_GetWindSpeed(Time, InputPosition, ErrStat, ErrMsg) -! This function receives time and position (in InputInfo) where (undisturbed) velocities are are -! requested. It returns the velocities at the specified time and space that are superimposed on -! a background wind flow. This function interpolates into the full-field CT wind arrays, performing -! a time shift based on the average windspeed. The modified time is used to decide which pair of time -! slices to interpolate within and between. After finding the two time slices, it decides which four -! grid points bound the (Y,Z) pair. It does a bilinear interpolation for (Y,Z) on each bounding time -! slice, then linearly interpolates between the 2 time slices. This routine assumes that X is downwind, -! Y is to the left when looking downwind and Z is up. In the time (X) and Z directions, steady winds -! are used when extrapolation is required. The dataset is assumed to be periodic in the Y direction. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables: - - REAL(DbKi), INTENT(IN) :: Time ! the time - REAL(ReKi), INTENT(IN) :: InputPosition(3) ! the position (X,Y,Z) - INTEGER, INTENT(OUT):: ErrStat ! returns ErrID_None if no error; non-zero otherwise - CHARACTER(*), INTENT(OUT) :: ErrMsg ! Message about the error - REAL(ReKi) :: CT_GetWindSpeed ! the resultant wind speed - - - ! Local Variables: - - REAL(ReKi) :: Iyz_th ! Temporary interpolated value. (time hi, all y, all z) - REAL(ReKi) :: Iyz_tl ! Temporary interpolated value. (time lo, all y, all z) - REAL(ReKi) :: Iyhz ! Temporary interpolated value. (y hi, all z) - REAL(ReKi) :: Iylz ! Temporary interpolated value. (y lo, all z) - REAL(ReKi) :: TimeShifted ! Shifted time (necessary because we're keeping x constant) - REAL(ReKi) :: Tgrid ! Fractional distance between time grids. - REAL(ReKi) :: Ygrid ! Fractional distance between grids in the y direction. - REAL(ReKi) :: Ynorm ! Nondimensional lateral distance of the analysis point from right side of dataset (looking downwind). - REAL(ReKi) :: Zgrid(3) ! Fractional distance between grids in the z direction. - REAL(ReKi) :: Znorm ! Nondimensional vertical distance of the analysis point from bottom of dataset. - - INTEGER :: I - INTEGER :: IYHi - INTEGER :: IYLo - INTEGER :: IZHi(3) - INTEGER :: IZLo(3) - - ! Temporary error handling - INTEGER :: TmpErrStat - CHARACTER(LEN(ErrMsg)) :: TmpErrMsg - - - !------------------------------------------------------------------------------------------------- - ! Check that we've initialized everything first - !------------------------------------------------------------------------------------------------- - - IF ( TimeIndx == 0 ) THEN - ErrMsg = ' Initialialize the CTWind module before calling its subroutines.' - ErrStat = ErrID_Fatal - RETURN - ELSE IF ( CT_Zref < 0 ) THEN - ErrMsg = ' Set the reference height in the CTWind module before calling CT_GetWindSpeed.' - ErrStat = ErrID_Fatal - RETURN - ELSE - ErrStat = ErrID_None - END IF - - - !------------------------------------------------------------------------------------------------- - ! Perform the time shift. At time=0, a point half the grid width downstream will index into the zero - ! time slice. CTYHWid is used to shift the CT wind the same as FF wind is shifted. - ! This assumes that the coherent turbulence events are moving at MCTWS - !------------------------------------------------------------------------------------------------- - - TimeShifted = TIME + ( CTYHWid - InputPosition(1) )*InvMCTWS - - - !------------------------------------------------------------------------------------------------- - ! Find the bounding time slices: - ! Linearly interpolate in time (or set to 0 before and/or after) - ! (compare with NWTC_Num.f90\InterpStpReal) - !------------------------------------------------------------------------------------------------- - - ! Let's check the limits first. - - IF ( TimeShifted <= Tdata(1) ) THEN - - TimeIndx = 1 - Tgrid = 0.0 - -! CT_GetWindSpeed%Velocity(:) = 0.0 -! RETURN - - ELSE IF ( TimeShifted >= Tdata(NumCTt) ) THEN - - TimeIndx = NumCTt - 1 - Tgrid = 1.0 - -! CT_GetWindSpeed%Velocity(:) = 0.0 -! RETURN - - ELSE - - ! Let's interpolate! - - TimeIndx = MAX( MIN( TimeIndx, NumCTt-1 ), 1 ) - - - DO - - IF ( TimeShifted < Tdata(TimeIndx) ) THEN - - TimeIndx = TimeIndx - 1 - - ELSE IF ( TimeShifted >= Tdata(TimeIndx+1) ) THEN - - TimeIndx = TimeIndx + 1 - - ELSE - - Tgrid = MIN( MAX( ( TimeShifted - Tdata(TimeIndx) )/( Tdata(TimeIndx+1) - Tdata(TimeIndx) ), 0.0 ), 1.0 ) - EXIT - - END IF - - END DO - - END IF - - - !------------------------------------------------------------------------------------------------- - ! Read the data at the two time steps, if necessary - !------------------------------------------------------------------------------------------------- - - IF ( TimeStpCT(TimeIndx) == CTvel_files(2) ) THEN - IndCT_lo = 2 - IndCT_hi = 1 - - ELSE - IndCT_lo = 1 - IndCT_hi = 2 - - IF ( TimeStpCT(TimeIndx) /= CTvel_files(IndCT_lo) ) THEN - CTvel_files(IndCT_lo) = TimeStpCT(TimeIndx) - CALL ReadCTData ( CTWindUnit, CTvel_files(IndCT_lo), IndCT_lo, TmpErrStat, TmpErrMsg ) - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - END IF - - - IF ( CTvel_files(IndCT_hi) /= TimeStpCT(TimeIndx+1) ) THEN - - CTvel_files(IndCT_hi) = TimeStpCT(TimeIndx+1) - CALL ReadCTData ( CTWindUnit, CTvel_files(IndCT_hi), IndCT_hi, TmpErrStat, TmpErrMsg ) - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - - !------------------------------------------------------------------------------------------------- - ! Calculate the y values; The lower-right corner is (1,1) when looking downwind. - ! note that the KH data is periodic in this direction - !------------------------------------------------------------------------------------------------- - - Ynorm = ( CTYt + InputPosition(2) )/CTYmax - - ! Ensure Ynorm is not negative. The wave is periodic in y. - - IF ( Ynorm < 0.0 ) THEN - Ynorm = 1.0 + MOD(Ynorm, 1.0) - ENDIF - - Ygrid = MIN( MAX( MOD( Ynorm, DelYCTgrid ), 0.0 ), 1.0 ) - IYLo = MAX( MOD( INT( Ynorm*NumCTyD1 ) + 1, NumCTyD1 ), 1 ) - IYHi = MOD( IYLo, NumCTyD ) + 1 - - - !------------------------------------------------------------------------------------------------- - ! Calculate the z values The lower-right corner is (1,1) when looking downwind. - ! Note: the equivalent Znorm for the w-component may be shifted vertically by half the original - ! grid spacing. (the K-H data staggers w differently than u & v). We store IZLo, IZHi, and - ! Zgrid in an array to account for this difference. - !------------------------------------------------------------------------------------------------- - - Znorm = MIN( MAX( ( InputPosition(3) - CT_Zref )/CTZmax, 0.0 ), 1.0 ) ! non-dimensional height (CT_Zref is the bottom of the billow) - - ! Find out fractionally how far we are between grids in time and between grid points in each direction. - ! Limit values to avoid extrapolation. We need this for interpolation later on. - - Zgrid(1:2) = MIN( MAX( MOD( Znorm, DelZCTgrid ), 0.0 ), 1.0 ) - IZLo(1:2) = MAX( INT( Znorm*NumCTzD1 ) + 1, 1 ) ! Make sure the lowest possible value is 1. - - ! If we are located at the upper end of the z dimension, decrement the index by one and set the grid coordinate to 1. - - IF ( IZLo(1) == NumCTzD ) THEN - IZLo(1:2) = NumCTzD1 - Zgrid(1:2) = 1.0 - ENDIF - - - !------------------------------------------------------------------------------------------------- - ! Find the equivalent Znorm for the w-component, which may be shifted vertically by half - ! the original grid spacing. (This is necessary due to the fact that the K-H data staggers w - ! differently than u & v). LES and DNS scale differently. - !------------------------------------------------------------------------------------------------- - - IF ( CTVertShft ) THEN - Znorm = MAX( Znorm - 0.5*DelZCTgrid/CT_DF_Z, 0.0 ) - - Zgrid(3) = MIN( MAX( MOD( Znorm, DelZCTgrid ), 0.0 ), 1.0 ) - IZLo(3) = MAX( INT( Znorm*NumCTzD1 ) + 1, 1 ) ! Make sure the lowest possible value is 1. - - - ! If we are located at the upper end of the z dimension, decrement the index by one and set the grid coordinate to 1. - - IF ( IZLo(3) == NumCTzD ) THEN - IZLo(3) = NumCTzD1 - Zgrid(3) = 1.0 - ENDIF - - ELSE - IZLo(3) = IZLo(1) - Zgrid(3)= Zgrid(1) - ENDIF - - IZHi(:) = IZLo(:) + 1 - -!bjj: old versions used Zgrid(3) = Zgrid(1) without regard to CTVertShft. It seemed wrong to me so I changed it. - - !------------------------------------------------------------------------------------------------- - ! Interpolate for U component of wind within the grid. - !------------------------------------------------------------------------------------------------- - - I = 1 - ! linearaly interpolate in the lower time slice - Iylz = ( CTvelU(IYLo,IZHi(I),IndCT_lo) - CTvelU(IYLo,IZLo(I),IndCT_lo) )*Zgrid(I) + CTvelU(IYLo,IZLo(I),IndCT_lo) - Iyhz = ( CTvelU(IYHi,IZHi(I),IndCT_lo) - CTvelU(IYHi,IZLo(I),IndCT_lo) )*Zgrid(I) + CTvelU(IYHi,IZLo(I),IndCT_lo) - Iyz_tl = ( Iyhz - Iylz )*Ygrid + Iylz - - ! linearaly interpolate in the upper time slice - Iylz = ( CTvelU(IYLo,IZHi(I),IndCT_hi) - CTvelU(IYLo,IZLo(I),IndCT_hi) )*Zgrid(I) + CTvelU(IYLo,IZLo(I),IndCT_hi) - Iyhz = ( CTvelU(IYHi,IZHi(I),IndCT_hi) - CTvelU(IYHi,IZLo(I),IndCT_hi) )*Zgrid(I) + CTvelU(IYHi,IZLo(I),IndCT_hi) - Iyz_th = ( Iyhz - Iylz )*Ygrid + Iylz - - CT_GetWindSpeed = ( Iyz_th - Iyz_tl )*Tgrid + Iyz_tl - - - !------------------------------------------------------------------------------------------------- - ! Interpolate for V component of wind within the grid. - !------------------------------------------------------------------------------------------------- - - I = 2 - - ! linearaly interpolate in the lower time slice - Iylz = ( CTvelV(IYLo,IZHi(I),IndCT_lo) - CTvelV(IYLo,IZLo(I),IndCT_lo) )*Zgrid(I) + CTvelV(IYLo,IZLo(I),IndCT_lo) - Iyhz = ( CTvelV(IYHi,IZHi(I),IndCT_lo) - CTvelV(IYHi,IZLo(I),IndCT_lo) )*Zgrid(I) + CTvelV(IYHi,IZLo(I),IndCT_lo) - Iyz_tl = ( Iyhz - Iylz )*Ygrid + Iylz - - ! linearaly interpolate in the upper time slice - Iylz = ( CTvelV(IYLo,IZHi(I),IndCT_hi) - CTvelV(IYLo,IZLo(I),IndCT_hi) )*Zgrid(I) + CTvelV(IYLo,IZLo(I),IndCT_hi) - Iyhz = ( CTvelV(IYHi,IZHi(I),IndCT_hi) - CTvelV(IYHi,IZLo(I),IndCT_hi) )*Zgrid(I) + CTvelV(IYHi,IZLo(I),IndCT_hi) - Iyz_th = ( Iyhz - Iylz )*Ygrid + Iylz - - CT_GetWindSpeed = ( Iyz_th - Iyz_tl )*Tgrid + Iyz_tl - - - !------------------------------------------------------------------------------------------------- - ! Interpolate for W component of wind within the grid. - !------------------------------------------------------------------------------------------------- - - I = 3 - - ! linearaly interpolate in the lower time slice - Iylz = ( CTvelW(IYLo,IZHi(I),IndCT_lo) - CTvelW(IYLo,IZLo(I),IndCT_lo) )*Zgrid(I) + CTvelW(IYLo,IZLo(I),IndCT_lo) - Iyhz = ( CTvelW(IYHi,IZHi(I),IndCT_lo) - CTvelW(IYHi,IZLo(I),IndCT_lo) )*Zgrid(I) + CTvelW(IYHi,IZLo(I),IndCT_lo) - Iyz_tl = ( Iyhz - Iylz )*Ygrid + Iylz - - ! linearaly interpolate in the upper time slice - Iylz = ( CTvelW(IYLo,IZHi(I),IndCT_hi) - CTvelW(IYLo,IZLo(I),IndCT_hi) )*Zgrid(I) + CTvelW(IYLo,IZLo(I),IndCT_hi) - Iyhz = ( CTvelW(IYHi,IZHi(I),IndCT_hi) - CTvelW(IYHi,IZLo(I),IndCT_hi) )*Zgrid(I) + CTvelW(IYHi,IZLo(I),IndCT_hi) - Iyz_th = ( Iyhz - Iylz )*Ygrid + Iylz - - CT_GetWindSpeed = ( Iyz_th - Iyz_tl )*Tgrid + Iyz_tl - - - RETURN - -END FUNCTION CT_GetWindSpeed -!==================================================================================================== -SUBROUTINE ReadCTData ( UnWind, CTFileNo, Itime, ErrStat, ErrMsg ) -! This subroutine is used to read one time-step's worth of large-eddy -! zero-mean wind data for each wind component from a file. -!---------------------------------------------------------------------------------------------------- - - - ! Passed variables. - - INTEGER, INTENT(IN) :: UnWind ! The I/O unit of the input file - INTEGER, INTENT(IN) :: CTFileNo ! The number of the file to read - INTEGER, INTENT(IN) :: Itime ! The index of the time slice - INTEGER, INTENT(OUT) :: ErrStat ! returns ErrID_None if no error; non-zero otherwise - CHARACTER(*), INTENT(OUT) :: ErrMsg ! Message to return about the error - - ! Local variables. - -! CHARACTER(1),PARAMETER :: Comp(NumComps) = (/'u', 'v', 'w' /) ! the wind components - CHARACTER(5) :: CTnum ! string equivalent of input variable CTFileNo - CHARACTER(1024) :: FileName ! The name of the input data file - - ! Temporary error handling Variables - - INTEGER :: TmpErrStat ! Temporary Error Status - CHARACTER(LEN(ErrMsg)) :: TmpErrMsg ! Temporary error message returned - - - !------------------------------------------------------------------------ - ! Initialize the error handling - !------------------------------------------------------------------------ - ErrStat = ErrID_None - ErrMsg = '' - - - IF ( CTFileNo == 0 ) THEN - - CTvelU(:,:,Itime) = 0.0 - CTvelV(:,:,Itime) = 0.0 - CTvelW(:,:,Itime) = 0.0 - - ELSE - ! Loop through the components - - WRITE( CTnum, '(I5.5)' ) CTFileNo - - - FileName = TRIM( CTSpath )//'\u\u_16i_'//CTnum//'.'//TRIM( CText ) - CALL LoadCTData( UnWind, TRIM(FileName), Itime, 1, CTvelU, TmpErrStat, TmpErrMsg ) - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - FileName = TRIM( CTSpath )//'\v\v_16i_'//CTnum//'.'//TRIM( CText ) - CALL LoadCTData( UnWind, TRIM(FileName), Itime, 2, CTvelV, TmpErrStat, TmpErrMsg ) - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - FileName = TRIM( CTSpath )//'\w\w_16i_'//CTnum//'.'//TRIM( CText ) - CALL LoadCTData( UnWind, TRIM(FileName), Itime, 3, CTvelW, TmpErrStat, TmpErrMsg ) - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - END IF - - RETURN - -END SUBROUTINE ReadCTData -!==================================================================================================== -SUBROUTINE LoadCTData( UnWind, FileName, ITime, IComp, Vel, ErrStat, ErrMsg ) -! This function is used to read the input parameters for the coherent turbulence events, -! based on the large-eddy simulation. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables. - - INTEGER, INTENT(IN) :: UnWind ! The I/O unit of the input file - CHARACTER(*), INTENT(IN) :: FileName ! The name of the file to open - INTEGER, INTENT(IN) :: Itime ! The index of the time slice - INTEGER, INTENT(IN) :: IComp ! The index of the component - REAL(ReKi), INTENT(INOUT) :: Vel (NumCTyD,NumCTzD,2) ! returns the velocity array (don't use INTENT OUT!) - INTEGER, INTENT(OUT) :: ErrStat ! returns ErrID_None if no error; non-zero otherwise - CHARACTER(*), INTENT(OUT) :: ErrMsg ! A message abouth the error - - - ! Local Variables - - INTEGER(B2Ki) :: Com (NumCTy) ! Temporary array to hold component's integer values for a given Z. - INTEGER :: IY ! A DO index for indexing the arrays in the y direction. - INTEGER :: IYK ! An index for the decimated arrays in the y direction. - INTEGER :: IZ ! A DO index for indexing the arrays in the z direction. - INTEGER :: IZK ! An index for the decimated arrays in the z direction. - - ! Temporary error handling - INTEGER :: TmpErrStat - CHARACTER(LEN(ErrMsg)) :: TmpErrMsg - - - !------------------------------------------------------------------------------------------------- - ! Set temporary Error info - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = '' -!FIXME: remove with add ErrMsg - TmpErrMsg = '' - - - !------------------------------------------------------------------------------------------------- - ! Open the input file - !------------------------------------------------------------------------------------------------- - - CALL OpenUInBEFile( UnWind, TRIM(FileName), 2*NumCTy, TmpErrStat ) ! add ErrMsg - IF ( ErrStat >= AbortErrLev ) THEN - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - RETURN - ELSE - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ENDIF - - - !------------------------------------------------------------------------------------------------- - ! Read the data and fill the arrays - !------------------------------------------------------------------------------------------------- - - IZK = 0 ! the Z index into the array (necessary b/c of decimation factor) - DO IZ=1,NumCTz,CT_DF_Z - - READ (UnWind,REC=IZ,IOSTAT=TmpErrStat) Com - - IF ( TmpErrStat /= 0 ) THEN - - ErrMsg = TRIM(ErrMsg)//' Error reading record '//TRIM( Num2LStr( IZ ) )//' of the binary CT wind file, "' & - //TRIM( FileName )//'."' - ErrStat=ErrID_Fatal - RETURN - - ENDIF - - IZK = IZK + 1 - IYK = 0 ! the Y index into the array (necessary b/c of decimation factor) - - DO IY=1,NumCTy,CT_DF_Y - IYK = IYK + 1 - Vel(IYK,IZK,ITime) = CTScale(IComp)*Com(IY) + CTOffset(IComp) - ENDDO ! IY - - ENDDO ! IZ - - - !------------------------------------------------------------------------------------------------- - ! Close the file - !------------------------------------------------------------------------------------------------- - CLOSE ( UnWind ) - - RETURN - - -END SUBROUTINE LoadCTData -!==================================================================================================== -SUBROUTINE ReadCTP( UnWind, FileName, CTPscaling, ErrStat, ErrMsg ) -! This function is used to read the input parameters for the coherent turbulence events, -! based on the large-eddy simulation. -!---------------------------------------------------------------------------------------------------- - - - ! Passed variables. - - INTEGER, INTENT(IN) :: UnWind ! The I/O unit of the input file - CHARACTER(*), INTENT(IN) :: FileName ! The name of the input data file - TYPE(CTWindFiles), INTENT(OUT) :: CTPscaling ! The file names contained in the CTP file - INTEGER, INTENT(OUT) :: ErrStat ! returns 0 if no error; non-zero otherwise' - CHARACTER(*), INTENT(OUT) :: ErrMsg ! Error message to return - - - ! Local variables. - - CHARACTER(1024) :: HeaderLine ! The header text in the file - CHARACTER(1024) :: TmpPath - - ! Temporary error handling Variables - - INTEGER :: TmpErrStat ! Temporary Error Status - CHARACTER(LEN(ErrMsg)) :: TmpErrMsg ! Temporary error message returned - - !------------------------------------------------------------------------------------------------- - ! Set temporary Error info - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = '' - - - !------------------------------------------------------------------------------------------------- - ! Open the CTP input file - !------------------------------------------------------------------------------------------------- - - CALL OpenFInpFile ( UnWind, TRIM( FileName ), TmpErrStat ) ! add ErrMsg - - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Read the CTP input file - !------------------------------------------------------------------------------------------------- - CALL ReadStr( UnWind, TRIM( FileName ), HeaderLine, 'Header line', 'The header line in the CTP file', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat > AbortErrLev ) THEN - ErrMsg = TRIM(ErrMsg)//' Error reading header line of '//TRIM(FileName)//'.' - RETURN - ENDIF - CALL WrScr ( ' Heading of the CT-wind-parameter file: "'//TRIM(HeaderLine)//'"' ) - - - CALL ReadCom( UnWind, TRIM( FileName ), 'parameter header line', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) THEN - ErrMsg = TRIM(ErrMsg)//' Error reading parameter header line of '//TRIM(FileName)//'.' - RETURN - ENDIF - - - CALL ReadVar( UnWind, TRIM( FileName ), CTSpath, 'CTSpath', & - 'Location (path) of the binary coherent turbulence dataset', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) THEN - ErrMsg = TRIM(ErrMsg)//' Error reading location (path) of the binary coherent turbulence dataset '//TRIM(FileName)//'.' - RETURN - ENDIF - - - CALL ReadVar( UnWind, TRIM( FileName ), CTPscaling%CTfile, 'CTfile', & - 'File containing the time steps for the coherent turbulence events (.cts)', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) THEN - ErrMsg = TRIM(ErrMsg)//' Error reading name of file containing time steps for the coherent turbulent events from ' & - //TRIM(FileName)//'.' - RETURN - ENDIF - - - IF ( PathIsRelative( CTPscaling%CTfile ) ) THEN - CALL GetPath( FileName, TmpPath ) - CTPscaling%CTfile = TRIM(TmpPath)//TRIM(CTPscaling%CTfile) - END IF - - - CALL ReadVar( UnWind, TRIM( FileName ), CTPscaling%CTbackgr, 'CTbackgr', 'File containing the background wind', TmpErrStat ) ! add ErrMsig - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) THEN - ErrMsg = TRIM(ErrMsg)//' Error reading name of file containing the background wind from '//TRIM(FileName)//'.' - RETURN - ENDIF - - IF ( PathIsRelative( CTPscaling%CTbackgr ) ) THEN - CALL GetPath( FileName, TmpPath ) - CTPscaling%CTbackgr = TRIM(TmpPath)//TRIM(CTPscaling%CTbackgr) - END IF - - - CALL ReadVar( UnWind, TRIM( FileName ), CT_DF_Y, 'CT_DF_Y', 'Decimation factor for wind data in the Y direction', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) THEN - ErrMsg = TRIM(ErrMsg)//' Error reading the decimation factor for wind data in the Y direction from ' & - //TRIM(FileName)//'.' - RETURN - ENDIF - - - CALL ReadVar( UnWind, TRIM( FileName ), CT_DF_Z, 'CT_DF_Z', 'Decimation factor for wind data in the Z direction', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) THEN - ErrMsg = TRIM(ErrMsg)//' Error reading the decimation factor for wind data in the Z direction from ' & - //TRIM(FileName)//'.' - RETURN - ENDIF - - - !------------------------------------------------------------------------------------------------- - ! Close the CTP input file - !------------------------------------------------------------------------------------------------- - - CLOSE( UnWind ) - - -END SUBROUTINE ReadCTP -!==================================================================================================== -SUBROUTINE ReadCT ( UnWind, FileName, CT_SC_ext, EmptyFileStat, ErrStat, ErrMsg ) -! This subroutine is used to read the input parameters calculated in TurbSim for the scaling of -! coherent turbulence events. It reads the .cts file and saves the time step and file number arrays. -!---------------------------------------------------------------------------------------------------- - -! EmptyFileStat: The CT file may not be exist or may be empty. TurbSim will do this in certain conditions. -! This is not a problem for program execution and used to be handled by Errstat<0. Set a -! warning in this case. - - - ! Passed variables. - - INTEGER, INTENT(IN) :: UnWind ! The I/O unit of the input file - CHARACTER(*), INTENT(IN) :: FileName ! The name of the input data file - CHARACTER(3), INTENT(OUT) :: CT_SC_ext ! The extension used for coherent turbulence scale files.(usually "les", "dns", or "dat") - LOGICAL, INTENT(OUT) :: EmptyFileStat ! Special case for this file type. see note above - INTEGER, INTENT(OUT) :: ErrStat ! returns ErrID_Warn if can't open the file - CHARACTER(*), INTENT(OUT) :: ErrMsg ! Message about what happened - - ! Local variables - - INTEGER :: IT ! Loop counter - - ! Temporary error handling variables - - INTEGER :: TmpErrStat ! temporary ErrStat - CHARACTER(LEN(ErrMsg)) :: TmpErrMsg ! temporary returned error message - - !------------------------------------------------------------------------------------------------- - ! Initialize variables - !------------------------------------------------------------------------------------------------- - - NumCTt = 0 - ErrMsg = '' - - !------------------------------------------------------------------------------------------------- - ! Open the CTS input file -- can proceed if we can't open this file. - !------------------------------------------------------------------------------------------------- - - CALL OpenFInpFile ( UnWind, TRIM( FileName ), TmpErrStat ) ! add ErrMsg when available - IF (TmpErrStat /= 0) THEN - EmptyFileStat = .TRUE. - ErrMsg = ' Error opening '//TRIM(FileName)//', ignoring it.' - ErrStat = ErrID_Warn - RETURN - ELSE - EmptyFileStat = .FALSE. - ENDIF - - !------------------------------------------------------------------------------------------------- - ! Read the header of the CTS input file - !------------------------------------------------------------------------------------------------- - - ! Check to see if the first value is numeric (old) or the file type (new) and start again - - READ ( UnWind, *, IOSTAT=TmpErrStat ) CTScaleVel - REWIND( UnWind ) - - IF ( TmpErrStat /= 0 ) THEN ! try again - - CALL ReadVar( UnWind, TRIM( FileName ), CText, 'CText', 'FileType ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? Can proceeed if the file is empty. - IF ( TmpErrStat < 0 ) THEN ! end of record / end of file condition - ErrMsg = TRIM(ErrMsg)//' File '//TRIM(FileName)//' is empty; ignoring it' - ErrStat = ErrID_Warn - EmptyFileStat = .TRUE. - RETURN - ELSE ! positive, so something bad happened. - ErrMsg = TRIM(ErrMsg)//' Error reading from file '//TRIM(TmpErrMsg) - ErrStat = ErrID_Fatal - ENDIF - IF ( ErrStat >= AbortErrLev ) RETURN - - CT_SC_ext = CText - - CALL ReadVar( UnWind, TRIM( FileName ), CTScaleVel, 'CTScaleVel', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - ELSE ! assume LES files - - CALL ReadVar( UnWind, TRIM( FileName ), CTScaleVel, 'CTScaleVel', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - CText = 'les' - CT_SC_ext = 'dat' - END IF - - CALL ReadVar( UnWind, TRIM( FileName ), InvMCTWS, 'MeanCTWS', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - InvMCTWS = 1.0 / InvMCTWS - - - CALL ReadVar( UnWind, TRIM( FileName ), CTYmax, 'CTYmax', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), CTZmax, 'CTZmax', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), CTDistSc, 'CTDistSc', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), CTLy, 'CTLy', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), CTLz, 'CTLz', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), NumCTt, 'NumCTt', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX( ErrStat, TmpErrStat ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Allocate space for the arrays - !------------------------------------------------------------------------------------------------- - - IF (.NOT. ALLOCATED(Tdata) ) THEN - ALLOCATE ( Tdata(NumCTt) , STAT=TmpErrStat ) - - ! Errors occured? - IF (TmpErrStat /= 0) THEN - ErrMsg = TRIM(ErrMsg)//' Error allocating memory for the Tdata array.' - ErrStat = ErrID_Fatal - RETURN - ENDIF - - END IF - - IF (.NOT. ALLOCATED(TimeStpCT) ) THEN - ALLOCATE ( TimeStpCT(NumCTt) , STAT=TmpErrStat ) - - ! Errors occured? - IF (TmpErrStat /= 0) THEN - ErrMsg = TRIM(ErrMsg)//' Error allocating memory for the TimeStpCT array.' - ErrStat = ErrID_Fatal - RETURN - ENDIF - - END IF - - - !------------------------------------------------------------------------------------------------- - ! Read the arrays from the CTS input file - !------------------------------------------------------------------------------------------------- - - DO IT=1,NumCTt - - READ (UnWind,*,IOSTAT=TmpErrStat) Tdata(IT), TimeStpCT(IT) - - ! Errors occured? - IF ( TmpErrStat /=0 ) THEN - ErrStat=ErrID_Fatal - ErrMsg = TRIM(ErrMsg)//' Error reading record '//TRIM( Num2LStr( IT ) )//' of the CT-wind time-steps file, "' & - //TRIM( FileName )//'."' - - NumCTt = IT - 1 - RETURN - ENDIF - - ENDDO ! IT - - - !------------------------------------------------------------------------------------------------- - ! Close the CTS input file - !------------------------------------------------------------------------------------------------- - CLOSE( UnWind ) - - - RETURN - -END SUBROUTINE ReadCT -!==================================================================================================== -SUBROUTINE ReadCTScales ( UnWind, FileName, ErrStat, ErrMsg ) -! This subroutine is used to read the input parameters for the coherent turbulence events, based -! on the large-eddy simulation. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - - INTEGER, INTENT(IN) :: UnWind ! The I/O unit of the input file - CHARACTER(*), INTENT(IN) :: FileName ! The name of the input data file - INTEGER, INTENT(OUT) :: ErrStat ! returns ErrID_None if no error; non-zero otherwise - CHARACTER(*), INTENT(OUT) :: ErrMsg ! Message about the error - - - ! Local variables - - INTEGER :: I ! Array counter - - - ! Temporary error handling Variables - - INTEGER :: TmpErrStat ! Temporary Error Status - CHARACTER(LEN(ErrMsg)) :: TmpErrMsg ! Temporary error message returned - - !------------------------------------------------------------------------------------------------- - ! Open the file with the scales (les or dns) - !------------------------------------------------------------------------------------------------- - - CALL OpenFInpFile ( UnWind, TRIM( FileName ), ErrStat) ! add ErrMsg - IF (ErrStat /= 0) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Read the file with the scales (les or dns) - !------------------------------------------------------------------------------------------------- - - CALL ReadCom( UnWind, TRIM( FileName ), 'First line', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), CTVertShft, 'CTVertShft', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - DO I = 1,3 - CALL ReadVar( UnWind, TRIM( FileName ), CTScale(I), 'CTScale('//TRIM(Num2LStr(I))//')', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), CTOffset(I), 'CTOffset('//TRIM(Num2LStr(I))//')', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - END DO !I - - - CALL ReadVar( UnWind, TRIM( FileName ), NumCTy, 'NumCTy', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), NumCTz, 'NumCTz', ' ', TmpErrStat ) ! add ErrMsg - - ! Errors occured? - ErrMsg = TRIM(ErrMsg)//' '//TRIM(TmpErrMsg) - ErrStat = MAX(ErrStat, TmpErrStat) - IF ( ErrStat >= AbortErrLev ) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Close the file with the scales (les or dns) - !------------------------------------------------------------------------------------------------- - - CLOSE( UnWind ) - - - RETURN - -END SUBROUTINE ReadCTScales -!==================================================================================================== -SUBROUTINE CT_Terminate( ErrStat, ErrMsg ) -! This subroutine closes files, deallocates memory, and un-sets the initialization flag -!---------------------------------------------------------------------------------------------------- - - INTEGER, INTENT(OUT) :: ErrStat ! return ErrID_None if no errors, ErrID level otherwise. - CHARACTER(*), INTENT(OUT) :: ErrMsg ! Message about the error that occurred. - - - ! Temporary error handling Variables - - INTEGER :: TmpErrStat ! Temporary Error Status - CHARACTER(LEN(ErrMsg)) :: TmpErrMsg ! Temporary Error Message - - - ! Initialize variables - ErrStat = ErrID_None - ErrMsg = '' - TmpErrMsg = '' - TmpErrStat = 0 - - - CLOSE( CTWindUnit ) - - IF ( ALLOCATED( CTvelU ) ) DEALLOCATE( CTvelU, STAT=TmpErrStat, ERRMSG=TmpErrMsg ) - IF (TmpErrStat /= 0) THEN - ErrMsg = TRIM(ErrMsg)//' InflowWind:CTWind: Error occured during de-allocation of CTvelU.'//TmpErrMsg - ErrStat = ErrID_Fatal - ENDIF - - IF ( ALLOCATED( CTvelV ) ) DEALLOCATE( CTvelV, STAT=TmpErrStat, ERRMSG=TmpErrMsg ) - IF (TmpErrStat /= 0) THEN - ErrMsg = TRIM(ErrMsg)//' InflowWind:CTWind: Error occured during de-allocation of CTvelV.'//TmpErrMsg - ErrStat = ErrID_Fatal - ENDIF - - IF ( ALLOCATED( CTvelW ) ) DEALLOCATE( CTvelW, STAT=TmpErrStat, ERRMSG=TmpErrMsg ) - IF (TmpErrStat /= 0) THEN - ErrMsg = TRIM(ErrMsg)//' InflowWind:CTWind: Error occured during de-allocation of CTvelW.'//TmpErrMsg - ErrStat = ErrID_Fatal - ENDIF - - IF ( ALLOCATED( Tdata ) ) DEALLOCATE( Tdata, STAT=TmpErrStat, ERRMSG=TmpErrMsg ) - IF (TmpErrStat /= 0) THEN - ErrMsg = TRIM(ErrMsg)//' InflowWind:CTWind: Error occured during de-allocation of Tdata.'//TmpErrMsg - ErrStat = ErrID_Fatal - ENDIF - - IF ( ALLOCATED( TimeStpCT ) ) DEALLOCATE( TimeStpCT, STAT=TmpErrStat, ERRMSG=TmpErrMsg ) - IF (TmpErrStat /= 0) THEN - ErrMsg = TRIM(ErrMsg)//' InflowWind:CTWind: Error occured during de-allocation of TimeStpCT.'//TmpErrMsg - ErrStat = ErrID_Fatal - ENDIF - - TimeIndx = 0 - -END SUBROUTINE CT_Terminate -!==================================================================================================== -END MODULE CTWind diff --git a/modules/inflowwind/src/FDWind.f90 b/modules/inflowwind/src/FDWind.f90 deleted file mode 100644 index c8accae528..0000000000 --- a/modules/inflowwind/src/FDWind.f90 +++ /dev/null @@ -1,1300 +0,0 @@ -MODULE FDWind -! This module reads and processes 4-dimensional wind fields. -! The subroutines were originally created by Marshall Buhl to read LES data provided by researchers -! at NCAR. It was later updated by Bonnie Jonkman to read DNS data provided by researchers at CoRA. -! -! Data are assumed to be in units of meters and seconds. -! -! 7 Oct 2009 B. Jonkman, NREL/NWTC using subroutines from AeroDyn 12.57 -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2013 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** -! File last committed: $Date: 2014-07-29 13:30:04 -0600 (Tue, 29 Jul 2014) $ -! (File) Revision #: $Rev: 125 $ -! URL: $HeadURL$ -!********************************************************************************************************************************** - - USE NWTC_Library - USE SharedInflowDefs - USE InflowWind_Module_Types - - IMPLICIT NONE - PRIVATE - - ! FD_Wind - - REAL(ReKi) :: DelXgrid ! The nondimensional distance between grid points in the x direction. - REAL(ReKi) :: DelYgrid ! The nondimensional distance between grid points in the y direction. - REAL(ReKi) :: DelZgrid ! The nondimensional distance between grid points in the z direction. - REAL(ReKi) :: FDper ! Total time in dataset. - REAL(ReKi) :: FDTime (2) ! Times for the 4D wind files. - REAL(ReKi), ALLOCATABLE :: FDu (:,:,:,:) ! The u-component array of 4D wind data. - REAL(ReKi), ALLOCATABLE :: FDv (:,:,:,:) ! The v-component array of 4D wind data. - REAL(ReKi), ALLOCATABLE :: FDw (:,:,:,:) ! The w-component array of 4D wind data. - REAL(ReKi), ALLOCATABLE :: FDuData (:,:,:,:) ! The u-component array of all 4D wind data when used with advection. - REAL(ReKi), ALLOCATABLE :: FDvData (:,:,:,:) ! The v-component array of all 4D wind data when used with advection. - REAL(ReKi), ALLOCATABLE :: FDwData (:,:,:,:) ! The w-component array of all 4D wind data when used with advection. - REAL(ReKi) :: Lx ! Fractional location of tower centerline from upwind end to downwind end of the dataset. - REAL(ReKi) :: Ly ! Fractional location of tower centerline from right (looking downwind) to left side of the dataset. - REAL(ReKi) :: Lz ! Fractional location of hub height from bottom to top of dataset. - REAL(ReKi) :: Offsets (3) ! Offsets to convert integer data to actual wind speeds. -!FIXME: move to otherstates - REAL(ReKi), SAVE :: PrevTime ! The previous time this was called -- so we can go back in time if necessary - REAL(ReKi) :: RotDiam ! Rotor diameter. - REAL(ReKi) :: ScalFact (3) ! Scaling factors to convert integer data to actual wind speeds. - REAL(ReKi) :: ScaleVel ! Scaling velocity, U0. 2*U0 is the difference in wind speed between the top and bottom of the wave. - REAL(ReKi), ALLOCATABLE :: Times4D (:) ! The list of times for the 4D-wind input files. - REAL(ReKi) :: Tm_max ! The total nondimensional time of the dataset. - REAL(ReKi) :: TSclFact ! Scale factor for time (h/U0). - REAL(ReKi) :: T_4D_En ! Time at which the wave event ends. - REAL(ReKi) :: T_4D_St ! Time at which the wave event starts. - REAL(ReKi) :: Xmax ! The dimensional downwind length of the dataset. - REAL(ReKi) :: Xt ! Distance of the tower from the upwind end of the dataset. - REAL(ReKi) :: Ymax ! The dimensional lateral width of the dataset. - REAL(ReKi) :: Yt ! Distance of the tower from the right side of the dataset (looking downwind). - REAL(ReKi) :: Zmax ! The dimensional vertical height of the dataset. - REAL(ReKi) :: Zt ! Distance of the hub from the bottom of the dataset. - REAL(ReKi) :: Zref ! The reference height (hub height) - - INTEGER :: FD_DF_X ! The decimation factor for the 4D wind data in the x direction. - INTEGER :: FD_DF_Y ! The decimation factor for the 4D wind data in the y direction. - INTEGER :: FD_DF_Z ! The decimation factor for the 4D wind data in the z direction. - INTEGER :: FDFileNo ! The 4D wind file number. - INTEGER :: FDRecL ! The length, in bytes, of the LE binary records. - INTEGER :: Ind4DAdv ! Index of the file to be used in advection - INTEGER :: Ind4Dnew ! Index of the newest 4D wind file. - INTEGER :: Ind4Dold ! Index of the older 4D wind file. - INTEGER :: Num4Dt ! The number of 4D wind grids, one grid per time step. - INTEGER, PARAMETER :: Num4DtD = 2 ! The number of 4D wind grids stored in memory, normally 2 - INTEGER :: Num4Dx ! The number of 4D wind grid points in the x direction. - INTEGER :: Num4DxD ! The decimated number of 4D wind grid points in the x direction. - INTEGER :: Num4DxD1 ! The decimated number of 4D wind grid points in the x direction minus 1. - INTEGER :: Num4Dy ! The number of 4D wind grid points in the y direction. - INTEGER :: Num4DyD ! The decimated number of 4D wind grid points in the y direction. - INTEGER :: Num4DyD1 ! The decimated number of 4D wind grid points in the y direction minus 1. - INTEGER :: Num4Dz ! The number of 4D wind grid points in the z direction. - INTEGER :: Num4DzD ! The decimated number of 4D wind grid points in the z direction. - INTEGER :: Num4DzD1 ! The decimated number of 4D wind grid points in the z direction minus 1. - INTEGER :: NumAdvect ! Number of frozen timesteps to advect past the turbine - INTEGER :: Shft4Dnew ! Number of times the x-data needs to be shifted for advection - INTEGER, ALLOCATABLE :: Times4DIx (:) ! Index number of the 4D time files (used for advection) - - INTEGER :: FDUnit ! Unit number for reading wind files - - LOGICAL :: Advect ! Flag to indicate whether or not to advect a given data set or to just use the time step files - LOGICAL :: VertShft ! Flag to indicate whether or not to shift the z values for the w component. - -!FIXME: move to parameters or otherstates - LOGICAL, SAVE :: Initialized = .FALSE. - - CHARACTER(5), ALLOCATABLE :: AdvFiles (:) - CHARACTER(1024) :: FDSpath ! The path to the 4D wind files. - - - PUBLIC :: FD_Init - PUBLIC :: FD_GetWindSpeed - PUBLIC :: FD_Terminate - PUBLIC :: FD_GetValue - - -CONTAINS -!==================================================================================================== -SUBROUTINE FD_Init(UnWind, WindFile, RefHt, ErrStat) -! This subroutine is called at the beginning of a simulation to initialize the module. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - - INTEGER, INTENT(IN) :: UnWind ! unit number for reading wind files - CHARACTER(*), INTENT(IN) :: WindFile ! Name of the 4D wind parameter file (.fdp) - REAL(ReKi), INTENT(IN) :: RefHt ! The reference height for the billow (should be hub height) - INTEGER, INTENT(OUT) :: ErrStat ! return 0 if no errors; non-zero otherwise - - ! Local variables - - CHARACTER(1024) :: FDTSfile ! name of the 4D time step file - REAL(ReKi) :: FDTimStp ! Average time step for 4D wind data. - INTEGER :: IT - - !------------------------------------------------------------------------------------------------- - ! Check that the module hasn't already been initialized. - !------------------------------------------------------------------------------------------------- - - IF ( Initialized ) THEN - CALL WrScr( ' FDWind has already been initialized.' ) - ErrStat = 1 - RETURN - ELSE - ErrStat = 0 -! CALL NWTC_Init() ! Initialized in IfW_Init - END IF - - - !------------------------------------------------------------------------------------------------- - ! Set the reference height for the wind file (this takes the place of HH that was used earlier) - !------------------------------------------------------------------------------------------------- - - ZRef = RefHt - - !------------------------------------------------------------------------------------------------- - ! Read the main 4D input file - !------------------------------------------------------------------------------------------------- - - CALL ReadFDP( UnWind, WindFile, FDTSfile, ErrStat ) - IF ( ErrStat /= 0 ) RETURN - - !------------------------------------------------------------------------------------------------- - ! Get the times array, which must be scaled and shifted later using TSclFact and T_4D_St - !------------------------------------------------------------------------------------------------- - - CALL Read4Dtimes ( UnWind, FDTSfile, ErrStat ) - IF ( ErrStat /= 0 ) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Calculate some values that don't change during the run. - !------------------------------------------------------------------------------------------------- - - FDRecL = 2*Num4Dx*Num4Dy ! The length, in bytes, of the 4D binary records. - Num4DxD = ( Num4Dx + FD_DF_X - 1 )/FD_DF_X ! The decimated number of 4D wind grid points in the x direction. - Num4DyD = ( Num4Dy + FD_DF_Y - 1 )/FD_DF_Y ! The decimated number of 4D wind grid points in the y direction. - Num4DzD = ( Num4Dz + FD_DF_Z - 1 )/FD_DF_Z ! The decimated number of 4D wind grid points in the z direction. - Num4DxD1 = Num4DxD - 1 ! The decimated number of 4D wind grid points in the x direction minus 1. - Num4DyD1 = Num4DyD - 1 ! The decimated number of 4D wind grid points in the y direction minus 1. - Num4DzD1 = Num4DzD - 1 ! The decimated number of 4D wind grid points in the z direction minus 1. - - Tm_max = Times4D(Num4Dt) ! Time of end of dataset. - IF ( ADVECT ) THEN - FDTimStp = Xmax / ( ( Num4Dx - 1 )*( ScaleVel )*Num4Dt ) ! The timestep is calculated by the approximation dx/dt ~= U0 (divide by num4dt to get delta for a full timestep). - FDper = FDTimStp * Num4Dt ! Total time in dataset. (We have periodic time, so multiply by number of time steps, without subtracting 1) - TSclFact = FDper / Tm_max ! Equivalent scale factor for time. - ELSE - FDper = TSclFact*Tm_max ! Total time in dataset. - FDTimStp = FDper/( Num4Dt - 1 ) ! Average time step. - ENDIF - - T_4D_En = T_4D_St + FDper ! Time for the end of the dataset. - Xt = Xmax*Lx ! Distance of the tower from the upwind end of the dataset. - Yt = Ymax*Ly ! Distance of the tower from the right side of the dataset (looking downwind). - Zt = Zmax*Lz ! Distance of the hub from the bottom of the dataset. - DelXgrid = 1.0/Num4DxD1 ! The nondimensional distance between grid points in the x direction. - DelYgrid = 1.0/Num4DyD1 ! The nondimensional distance between grid points in the y direction. - DelZgrid = 1.0/Num4DzD1 ! The nondimensional distance between grid points in the z direction. - - - !------------------------------------------------------------------------------------------------- - ! Scale and shift the times array using TSclFact and T_4D_St - !------------------------------------------------------------------------------------------------- - - DO IT=1,Num4Dt - - Times4D(IT) = TSclFact*Times4D(IT) + T_4D_St - - ENDDO ! IT - - - !------------------------------------------------------------------------------------------------- - ! Allocate velocity arrays and fill Data arrays for advection (DNS files) - !------------------------------------------------------------------------------------------------- - - IF (.NOT. ALLOCATED(FDu) ) THEN -! CALL AllocAry ( FDu, Num4DxD, Num4DyD, Num4DzD, 2, 'U-component velocity array (FDu)', ErrStat) - ALLOCATE ( FDu(Num4DxD,Num4DyD,Num4DzD,2), STAT=ErrStat ) - - IF ( ErrStat /= 0 ) THEN - CALL WrScr ( ' Error allocating memory for the U-component velocity array (FDu) array.' ) - RETURN - END IF - END IF - - IF (.NOT. ALLOCATED(FDv) ) THEN -! CALL AllocAry ( FDv, Num4DxD, Num4DyD, Num4DzD, 2, 'V-component velocity array (FDv)', ErrStat) - ALLOCATE ( FDv(Num4DxD,Num4DyD,Num4DzD,2), STAT=ErrStat ) - - IF ( ErrStat /= 0 ) THEN - CALL WrScr ( ' Error allocating memory for the V-component velocity array (FDv) array.' ) - RETURN - END IF - END IF - - IF (.NOT. ALLOCATED(FDw) ) THEN -! CALL AllocAry ( FDw, Num4DxD, Num4DyD, Num4DzD, 2, 'W-component velocity array (FDw)', ErrStat) - ALLOCATE ( FDw(Num4DxD,Num4DyD,Num4DzD,2), STAT=ErrStat ) - - IF ( ErrStat /= 0 ) THEN - CALL WrScr ( ' Error allocating memory for the W-component velocity array (FDw) array.' ) - RETURN - END IF - END IF - - IF ( ADVECT ) THEN - - IF (.NOT. ALLOCATED(FDuData) ) THEN -! CALL AllocAry ( FDuData, Num4DxD, Num4DyD, Num4DzD, Num4Dt, 'U-component velocity array (FDuData)', ErrStat) - ALLOCATE ( FDuData(Num4DxD,Num4DyD,Num4DzD,Num4Dt), STAT=ErrStat ) - - IF ( ErrStat /= 0 ) THEN - CALL WrScr ( ' Error allocating memory for the U-component velocity array (FDuData) array.' ) - RETURN - END IF - END IF - - IF (.NOT. ALLOCATED(FDvData) ) THEN -! CALL AllocAry ( FDvData, Num4DxD, Num4DyD, Num4DzD, Num4Dt, 'V-component velocity array (FDvData)', ErrStat) - ALLOCATE ( FDvData(Num4DxD,Num4DyD,Num4DzD,Num4Dt), STAT=ErrStat ) - - IF ( ErrStat /= 0 ) THEN - CALL WrScr ( ' Error allocating memory for the V-component velocity array (FDvData) array.' ) - RETURN - END IF - END IF - - IF (.NOT. ALLOCATED(FDwData) ) THEN -! CALL AllocAry ( FDwData, Num4DxD, Num4DyD, Num4DzD, Num4Dt, 'W-component velocity array (FDwData)', ErrStat) - ALLOCATE ( FDwData(Num4DxD,Num4DyD,Num4DzD,Num4Dt), STAT=ErrStat ) - - IF ( ErrStat /= 0 ) THEN - CALL WrScr ( ' Error allocating memory for the W-component velocity array (FDwData) array.' ) - RETURN - END IF - END IF - - CALL ReadAll4DData(UnWind, ErrStat) !This needs AdvFiles(:), which was is read in ReadFDP() - IF ( ErrStat /= 0 ) RETURN - - ENDIF - - - !------------------------------------------------------------------------------------------------- - ! Determine the first file needed for this simulation. - !------------------------------------------------------------------------------------------------- - Ind4Dold = 1 ! Put the old stuff in the first part of the array. - Ind4Dnew = 2 ! Put the new stuff in the second part of the array. - - Shft4Dnew = 0 - - - IF ( T_4D_St >= 0.0 ) THEN - FDFileNo = 1 - ELSE - FDFileNo = Num4Dt - DO IT=1,Num4Dt - IF ( Times4D(IT) > 0.0 ) THEN - FDFileNo = IT - 1 - EXIT - END IF - END DO ! IT - END IF - - !------------------------------------------------------------------------------------------------- - ! Open, read, and close the first set of files. - !------------------------------------------------------------------------------------------------- - FDTime(Ind4Dold) = Times4D(FDFileNo) ! Set the time for this file. - - IF ( ADVECT ) THEN - CALL Load4DData(Ind4Dold) ! load data stored in FDuData, FDvData, and FDwData arrays - ELSE - CALL LoadLESData( UnWind, FDFileNo, Ind4Dold, ErrStat ) - END IF - - - !------------------------------------------------------------------------------------------------- - ! Open, read, and close the second set of files. - !------------------------------------------------------------------------------------------------- - FDFileNo = FDFileNo + 1 - - - IF ( ADVECT ) THEN - FDFileNo = MOD(FDFileNo-1,Num4Dt) + 1 - - IF (FDFileNo == 1) THEN - Shft4Dnew = Shft4Dnew + 1 - - IF (Ind4DAdv <= NumAdvect) THEN ! Ind4DAdv was set in ReadFDP - IF ( MOD( Shft4Dnew, Num4Dx ) == 0 ) THEN - CALL ReadAll4DData(UnWind, ErrStat) - IF ( ErrStat /= 0 ) RETURN - END IF - END IF - - ENDIF - - FDTime(Ind4Dnew) = Times4D(FDFileNo) + Shft4Dnew*FDPer ! Set the time for this file. - - CALL Load4DData( Ind4Dnew ) ! shift the data - - ELSE - FDTime(Ind4Dnew) = Times4D(FDFileNo) ! Set the time for this file. - - CALL LoadLESData( UnWind, FDFileNo, Ind4Dnew, ErrStat ) - ENDIF - - - !------------------------------------------------------------------------------------------------- - ! Set the initialization flag - !------------------------------------------------------------------------------------------------- - FDUnit = UnWind - PrevTime = 0.0 - - Initialized = .TRUE. - - RETURN - -END SUBROUTINE FD_Init -!==================================================================================================== -SUBROUTINE ReadFDP ( UnWind, FileName, FDTSfile, ErrStat ) -! This subroutine is used to read the input parameters for the large-eddy simulation. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - - INTEGER, INTENT(IN) :: UnWind ! unit number for reading wind files - CHARACTER(*), INTENT(IN) :: FileName ! Then name of the LE data file. - CHARACTER(*), INTENT(OUT) :: FDTSfile ! The name of the file containing the time-step history of the wind files. - INTEGER, INTENT(OUT) :: ErrStat ! return 0 if no errors encountered; non-zero otherwise - - - ! Local variables - - CHARACTER(1024) :: HeaderLine -!FIXME: this invokes SAVE - CHARACTER(1),PARAMETER :: Comp(3) = (/'U', 'V', 'W' /) ! the wind components - - REAL(ReKi) :: CoefTE ! Coefficient of thermal expansion. - REAL(ReKi) :: DistScal ! Disturbance scale (ratio of wave height to rotor diameter) from input file. - REAL(ReKi) :: Grav ! Gravitational acceleration. - REAL(ReKi) :: LenScale ! Length scale (h). - REAL(ReKi) :: Ri ! Richardson number. - REAL(ReKi) :: Ubot ! Steady u-component wind speed at the bottom of the wave. - REAL(ReKi) :: Zm_maxo ! The nondimensional vertical height of the untrimmed dataset. - - REAL(ReKi) :: Xm_max ! The nondimensional downwind length of the dataset. - REAL(ReKi) :: Ym_max ! The nondimensional lateral width of the dataset. - REAL(ReKi) :: Zm_max ! The nondimensional vertical height of the dataset. - - INTEGER :: I - - !------------------------------------------------------------------------------------------------- - ! Open the 4D parameter file for reading - !------------------------------------------------------------------------------------------------- - CALL OpenFInpFile ( UnWind, TRIM( FileName ), ErrStat) - IF (ErrStat /= 0) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Read the 4D parameter input file - !------------------------------------------------------------------------------------------------- - - !.............................................................................................. - ! Read the 4D wind parameters specific to this turbine simulation. - !.............................................................................................. - - CALL ReadStr( UnWind, TRIM( FileName ), HeaderLine, 'Header line', 'The header line in the FTP file', ErrStat ) - IF (ErrStat /= 0) RETURN - CALL WrScr ( ' Heading of the 4D-wind-parameter file: "'//TRIM(HeaderLine)//'"' ) - - - CALL ReadCom( UnWind, TRIM( FileName ), 'Header line', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), FDSpath, 'FDSpath', 'Location (path) of the binary dataset', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), FDTSfile, 'FDTSfile', & - 'Name of the file containing the time-step history of the wind files', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Ubot, 'Ubot', 'Steady u-component wind speed at the bottom of the wave', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), DistScal, 'DistScal', 'Disturbance scale', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Lx, 'Lx', & - 'Fractional location of tower centerline from upwind end to downwind end of the dataset', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Ly, 'Ly', & - 'Fractional location of tower centerline from right (looking downwind) to left side of the dataset', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Lz, 'Lz', & - 'Fractional location of hub height from bottom to top of dataset', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), T_4D_St, 'T_4D_St', 'Time at which the wave event starts', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), ScaleVel, 'ScaleVel', & - 'Scaling velocity, U0: half the difference in wind speed between the top and bottom of the billow.', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), RotDiam, 'RotDiam', 'Rotor diameter', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), FD_DF_X, 'FD_DF_X', 'Decimation factor in X direction', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), FD_DF_Y, 'FD_DF_Y', 'Decimation factor in Y direction', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), FD_DF_Z, 'FD_DF_Z', 'Decimation factor in Z direction', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadCom( UnWind, TRIM( FileName ), 'blank line', ErrStat ) - IF (ErrStat /= 0) RETURN - - !.............................................................................................. - ! Read the 4D wind parameters specific to the K-H billow simulation being used. - !.............................................................................................. - - CALL ReadCom( UnWind, TRIM( FileName ), 'LES parameters specific to the K-H billow simulation being used', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), VertShft, 'VertShft', & - 'Flag to indicate whether or not to shift the z values for the w component', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Xm_max, 'Xm_max', & - 'Maximum nondimensional downwind distance from center of dataset', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Ym_max, 'Ym_max', & - 'Maximum nondimensional lateral distance from center of dataset', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Zm_max, 'Zm_max', & - 'Maximum nondimensional vertical distance from center of dataset', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Zm_maxo, 'Zm_maxo', & - 'Maximum nondimensional vertical distance from center of untrimmed dataset', ErrStat ) - IF (ErrStat /= 0) RETURN - - - DO I = 1,3 - - CALL ReadVar( UnWind, TRIM( FileName ), ScalFact(I), Comp(I)//'Scl', & - Comp(I)//'-component scale factor for converting from integers to reals', ErrStat ) - IF (ErrStat /= 0) RETURN - ScalFact(I) = ScalFact(I) * ScaleVel - - - CALL ReadVar( UnWind, TRIM( FileName ), Offsets(I), Comp(I)//'Off', & - Comp(I)//'-component offset for converting from integers to reals', ErrStat ) - IF (ErrStat /= 0) RETURN - Offsets(I) = Offsets(I) * ScaleVel - - END DO - Offsets (1) = Offsets (1) + ScaleVel + Ubot ! u-component offset to convert integer data to actual wind speeds. - - - CALL ReadVar( UnWind, TRIM( FileName ), Num4Dt, 'Num4Dt', 'The number of LE grids, one grid per time step', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Num4Dx, 'Num4Dx', 'The number of LE grid points in the x direction', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Num4Dy, 'Num4Dy', 'The number of LE grid points in the y direction', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Num4Dz, 'Num4Dz', 'The number of LE grid points in the z direction', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Ri, 'Ri', 'Richardson number', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), CoefTE, 'CoefTE', 'Coefficient of thermal expansion', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Grav, 'Grav', 'Gravitational acceleration', ErrStat ) - IF (ErrStat /= 0) RETURN - - - CALL ReadVar( UnWind, TRIM( FileName ), Advect, 'Advect', 'Advection flag', ErrStat ) - - IF (ErrStat /= 0) THEN - - Advect = .FALSE. - Ind4DAdv = 0 - ErrStat = 0 - CALL WrScr( ' Advection will not be used.') - - ELSE - - IF (Advect) THEN - IF ( FD_DF_X /= 1 ) THEN - CALL WrScr( ' FD_DF_X must be 1 when using advection. ' ) - FD_DF_X = 1 - ENDIF - - CALL ReadVar( UnWind, TRIM( FileName ), NumAdvect, 'NumAdvect', 'Number of 4D files for advection', ErrStat ) - IF (ErrStat /= 0) RETURN - - - IF ( NumAdvect < 1 ) THEN - CALL WrScr( ' NumAdvect in 4D-wind-parameter file, "'//TRIM( FileName )//'," must be at least 1.' ) - ErrStat = 1 - RETURN - ENDIF - - IF ( .NOT. ALLOCATED( AdvFiles ) ) THEN -! CALL AllocAry( AdvFiles, NumAdvect, 'AdvFiles array', ErrStat ) - ALLOCATE ( AdvFiles(NumAdvect), STAT=ErrStat ) - - IF ( ErrStat /= 0 ) THEN - CALL WrScr ( ' Error allocating memory for the AdvFiles array.' ) - RETURN - END IF - ENDIF - - CALL ReadAryLines( UnWind, TRIM( FileName ), AdvFiles, NumAdvect, 'AdvFiles', 'Advection file names', ErrStat ) - IF (ErrStat /= 0) RETURN - Ind4DAdv = 1 - - ELSE - Ind4DAdv = 0 - ENDIF !Advect == .TRUE. - - END IF - - !------------------------------------------------------------------------------------------------- - ! Close the 4D parameter input file - !------------------------------------------------------------------------------------------------- - CLOSE ( UnWind ) - - !------------------------------------------------------------------------------------------------- - ! Close the 4D parameter input file - !------------------------------------------------------------------------------------------------- - - LenScale = RotDiam*DistScal/Zm_max ! Length scale (h). - Xmax = Xm_max*LenScale ! The dimensional length of the dataset. - Ymax = Ym_max*LenScale ! The dimensional width of the dataset - Zmax = Zm_max*LenScale ! The dimensional vertical height of the dataset. - TSclFact = LenScale/ScaleVel ! Scale factor for time (h/U0). - - - - RETURN - -END SUBROUTINE ReadFDP -!==================================================================================================== -SUBROUTINE Read4Dtimes ( UnWind, FileName, ErrStat ) -! This subroutine is used to read the time array for the 4D data. The times in the file are -! non-dimensional and non-uniformly spaced. They are scaled using TSclFact to obtain units of seconds -! and T_4D_St is added to allow the billow to start at non-zero time. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - - INTEGER, INTENT(IN) :: UnWind ! unit number for reading wind files - CHARACTER(*), INTENT(IN) :: FileName ! Then name of the LE data file. - INTEGER, INTENT(OUT) :: ErrStat ! return 0 if no errors encountered; non-zero otherwise - - - ! Local variables - - INTEGER :: I ! Loop counter - - !------------------------------------------------------------------------------------------------- - ! Allocate arrays to store the data in - !------------------------------------------------------------------------------------------------- - - IF (.NOT. ALLOCATED( Times4D) ) THEN -! CALL AllocAry( Times4D, Num4Dt, '4D time array', ErrStat) - ALLOCATE ( Times4D(Num4Dt), STAT=ErrStat ) - - IF ( ErrStat /= 0 ) THEN - CALL WrScr ( ' Error allocating memory for the Times4D array.' ) - RETURN - END IF - END IF - - IF (.NOT. ALLOCATED( Times4DIx) ) THEN -! CALL AllocAry( Times4DIx, Num4Dt, '4D time array', ErrStat) - ALLOCATE ( Times4DIx(Num4Dt), STAT=ErrStat ) - - IF ( ErrStat /= 0 ) THEN - CALL WrScr ( ' Error allocating memory for the Times4DIx array.' ) - RETURN - END IF - END IF - - - !------------------------------------------------------------------------------------------------- - ! Open the 4D times file - !------------------------------------------------------------------------------------------------- - CALL OpenFInpFile ( UnWind, TRIM( FileName ), ErrStat) - IF ( ErrStat /= 0 ) RETURN - - !------------------------------------------------------------------------------------------------- - ! Read the 4D times file - !------------------------------------------------------------------------------------------------- - CALL ReadCom( UnWind, TRIM( FileName ), 'first line', ErrStat) - IF ( ErrStat /= 0 ) RETURN - - DO I=1,Num4Dt - - READ (UnWind,*,IOSTAT=ErrStat) Times4DIx(I), Times4D(I) - - IF ( ErrStat /= 0 ) THEN - - CALL WrScr( ' Error reading line '//TRIM( Num2LStr( I+1 ) )// & - ' of the 4D-wind time-steps file, "'//TRIM( FileName )//'."') - RETURN - - ENDIF - - ENDDO ! I - - - !------------------------------------------------------------------------------------------------- - ! Close the 4D times file - !------------------------------------------------------------------------------------------------- - - CLOSE ( UnWind ) - - RETURN - -END SUBROUTINE Read4Dtimes -!==================================================================================================== -SUBROUTINE ReadAll4DData(UnWind, ErrStat) -! This subroutine reads the data into one array to be accessed later when ADVECT=.TRUE. Since there -! are just a few time steps, we'll load them into memory to (hopefully) save I/O time. -!---------------------------------------------------------------------------------------------------- - - INTEGER, INTENT(IN) :: UnWind - INTEGER, INTENT(OUT) :: ErrStat ! - INTEGER :: IT - - CHARACTER(1) :: FDNum - CHARACTER(20) :: DNSFileName ! String containing part of the current file name. - - - DO IT = 1,Num4Dt - - WRITE(FDNum,'(I1.1)') Times4DIx(IT) - DNSFileName = TRIM(AdvFiles(Ind4DAdv))//'_'//TRIM(FDNum)//'.dns' - - CALL Read4DData ( UnWind, TRIM( FDSpath )//'\u\u_16i_'//TRIM(DNSFileName), FDuData, IT, ScalFact(1), Offsets(1), ErrStat ) - IF ( ErrStat /= 0 ) RETURN - - CALL Read4DData ( UnWind, TRIM( FDSpath )//'\v\v_16i_'//TRIM(DNSFileName), FDvData, IT, ScalFact(2), Offsets(2), ErrStat ) - IF ( ErrStat /= 0 ) RETURN - - CALL Read4DData ( UnWind, TRIM( FDSpath )//'\w\w_16i_'//TRIM(DNSFileName), FDwData, IT, ScalFact(3), Offsets(3), ErrStat ) - IF ( ErrStat /= 0 ) RETURN - - ENDDO ! IT - - Ind4DAdv = Ind4DAdv + 1 - - RETURN - -END SUBROUTINE ReadAll4DData -!==================================================================================================== -SUBROUTINE LoadLESData( UnWind, FileNo, Indx, ErrStat ) -! This subroutine reads binary data from the U, V, and W files and stores them in the arrays FDu, -! FDv, and FDw (by calling Read4DData). -!---------------------------------------------------------------------------------------------------- - ! Passed variables - - INTEGER, INTENT(IN) :: UnWind ! unit number for reading wind files - INTEGER, INTENT(IN) :: FileNo ! current file number to read - INTEGER, INTENT(IN) :: Indx ! index into the data arrays - INTEGER, INTENT(OUT) :: ErrStat ! return 0 if no errors encountered; non-zero otherwise - - ! local variables - CHARACTER(5) :: FDNum - CHARACTER(20) :: LESFileName ! String containing part of the current file name. - - - ! get the file name for the file number - - WRITE(FDNum,'(I5.5)', IOStat=ErrStat) FileNo - IF ( ErrStat /= 0 ) RETURN - - LESFileName = TRIM(FDNum)//'.les' - - - ! set the paths and read the data for each component - - CALL Read4DData ( UnWind, TRIM( FDSpath )//'\u\u_16i_'//TRIM(LESFileName), FDu, Indx, ScalFact(1), Offsets(1), ErrStat ) - IF ( ErrStat /= 0 ) RETURN - - CALL Read4DData ( UnWind, TRIM( FDSpath )//'\v\v_16i_'//TRIM(LESFileName), FDv, Indx, ScalFact(2), Offsets(2), ErrStat ) - IF ( ErrStat /= 0 ) RETURN - - CALL Read4DData ( UnWind, TRIM( FDSpath )//'\w\w_16i_'//TRIM(LESFileName), FDw, Indx, ScalFact(3), Offsets(3), ErrStat ) - - -END SUBROUTINE LoadLESData -!==================================================================================================== -SUBROUTINE Read4DData ( UnWind, FileName, Comp, Indx4, Scale, Offset, ErrStat) -! This subroutine is used to read one time-step's worth of large-eddy wind data for one component -! from a file. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables - - INTEGER, INTENT(IN) :: UnWind ! The I/O unit of the LE file. - CHARACTER(*),INTENT(IN) :: FileName ! Then name of the LE data file. - - REAL(ReKi), INTENT(INOUT) :: Comp (:,:,:,:) ! The velocity array [do NOT make this INTENT(OUT): other parts of the array may become undefined] - INTEGER, INTENT(IN) :: Indx4 ! The index of the 4th dimension of Comp, which is to be read. - REAL(ReKi), INTENT(IN) :: Scale ! The scale factor for converting from intergers to non-normalized reals. - REAL(ReKi), INTENT(IN) :: Offset ! The offset for converting from intergers to non-normalized reals. - - INTEGER, INTENT(OUT) :: ErrStat ! The returned status of a READ. - - ! Local variables - - INTEGER :: IX ! A DO index for indexing the arrays in the x direction. - INTEGER :: IXK ! An index for the decimated arrays in the x direction. - INTEGER :: IY ! A DO index for indexing the arrays in the y direction. - INTEGER :: IYK ! An index for the decimated arrays in the y direction. - INTEGER :: IZ ! A DO index for indexing the arrays in the z direction. - INTEGER :: IZK ! An index for the decimated arrays in the z direction. - - INTEGER(B2Ki) :: Com (Num4Dx,Num4Dy) ! Temporary array to hold component's integer values for a given Z. - - - !------------------------------------------------------------------------------------------------- - ! Open the binary input file - !------------------------------------------------------------------------------------------------- - CALL OpenUInBEFile( UnWind, TRIM( FileName ), FDRecL, ErrStat ) - IF ( ErrStat /= 0 ) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Read the input file - !------------------------------------------------------------------------------------------------- - - IZK = 0 - DO IZ=1,Num4Dz,FD_DF_Z - - READ (UnWind,REC=IZ,IOSTAT=ErrStat) Com - - IF ( ErrStat /= 0 ) THEN - - CALL WrScr( ' Error reading record '//TRIM( Num2LStr( IZ ) )// & - ' of the binary 4D wind file, "'//TRIM( FileName )//'".') - RETURN - - ENDIF - - IZK = IZK + 1 ! IZK = ( IZ - 1 + FD_DF_Z )/FD_DF_Z - IYK = 0 - - DO IY=1,Num4Dy,FD_DF_Y - - IYK = IYK + 1 ! IYK = ( IY - 1 + FD_DF_Y )/FD_DF_Y - - DO IX=1,Num4Dx,FD_DF_X - - ! shift the x-index, if necessary, to perform Advection - - !IXK = ( IX + FD_DF_X - 1 )/FD_DF_X - IXK = ( MOD(IX+Shft4Dnew-1,Num4Dx) + FD_DF_X )/FD_DF_X - - Comp(IXK,IYK,IZK,Indx4) = Scale*Com(IX,IY) + Offset - - ENDDO ! IX - - ENDDO ! IY - - ENDDO ! IZ - - - !------------------------------------------------------------------------------------------------- - ! Close the file - !------------------------------------------------------------------------------------------------- - CLOSE ( UnWind ) - - RETURN - -END SUBROUTINE Read4DData -!==================================================================================================== -SUBROUTINE Load4DData( InpIndx ) -! This subroutine takes the data from the storage array (used when ADVECT=.TRUE., shifts it if necessary, -! and loads it into the array for the time slice indexed by InpIndx. -!---------------------------------------------------------------------------------------------------- - - INTEGER, INTENT(IN) :: InpIndx - - INTEGER :: IX - INTEGER :: IXK - - - DO IX=1,Num4Dx,FD_DF_X - - ! shift the x-index, if necessary, to perform Advection - IXK = ( MOD(IX+Shft4Dnew-1,Num4Dx) + FD_DF_X )/FD_DF_X - - FDu(IXK,:,:,InpIndx) = FDuData(IX,:,:,FDFileNo) - FDv(IXK,:,:,InpIndx) = FDvData(IX,:,:,FDFileNo) - FDw(IXK,:,:,InpIndx) = FDwData(IX,:,:,FDFileNo) - - ENDDO ! IX - - - RETURN - -END SUBROUTINE Load4DData -!==================================================================================================== -FUNCTION FD_GetValue(RVarName, ErrStat) -! This function returns a real scalar value whose name is listed in the RVarName input argument. -! If the name is not recognized, an error is returned in ErrStat. -!---------------------------------------------------------------------------------------------------- - - CHARACTER(*), INTENT(IN) :: RVarName - INTEGER, INTENT(OUT) :: ErrStat - REAL(ReKi) :: FD_GetValue - - - CHARACTER(20) :: VarNameUC - - - !------------------------------------------------------------------------------------------------- - ! Check that the module has been initialized. - !------------------------------------------------------------------------------------------------- - - IF ( .NOT. Initialized ) THEN - CALL WrScr( ' Initialialize the FDWind module before calling its subroutines.' ) - ErrStat = 1 - RETURN - ELSE - ErrStat = 0 - END IF - - - !------------------------------------------------------------------------------------------------- - ! Return the requested values. - !------------------------------------------------------------------------------------------------- - - VarNameUC = RVarName - CALL Conv2UC( VarNameUC ) - - SELECT CASE ( TRIM(VarNameUC) ) - - CASE ('ROTDIAM' ) - FD_GetValue = RotDiam - - CASE DEFAULT - CALL WrScr( ' Invalid variable name in FD_GetRValue().' ) - ErrStat = 1 - - END SELECT - -END FUNCTION FD_GetValue -!==================================================================================================== -FUNCTION FD_GetWindSpeed(Time, InputPosition, ErrStat) -! This function is used to interpolate into the 4D wind arrays. It receives X, Y, Z and TIME from the -! calling routine. The time since the start of the 4D data is used to decide which pair of time slices -! to interpolate within and between. After finding the two time slices, it decides which eight grid -! points bound the (X,Y,Z) pair. It does a trilinear interpolation for each time slice. Linear -! interpolation is then used to interpolate between time slices. This routine assumes that X is -! downwind, Y is to the left when looking downwind and Z is up. It also assumes that no -! extrapolation will be needed except in time and the Z direction. In those cases, the appropriate -! steady winds are used. -!---------------------------------------------------------------------------------------------------- - - ! Passed variables: - - REAL(DbKi), INTENT(IN) :: Time ! the time - REAL(ReKi), INTENT(IN) :: InputPosition(3) ! structure that contains the position - INTEGER, INTENT(OUT):: ErrStat ! returns 0 if no error; non-zero otherwise -!FIXME:delete -! TYPE(InflIntrpOut) :: FD_GetWindSpeed ! the resultant wind speed - REAL(ReKi) :: FD_GetWindSpeed(3) ! the resultant wind speed - - - ! Local Variables: - - REAL(ReKi) :: Ixhyz ! Temporary interpolated value. - REAL(ReKi) :: Ixlyz ! Temporary interpolated value. - REAL(ReKi) :: Ixyzo ! Temporary interpolated value. - REAL(ReKi) :: Iyhz ! Temporary interpolated value. - REAL(ReKi) :: Iylz ! Temporary interpolated value. - REAL(ReKi) :: Ixyzn ! Temporary interpolated value. - REAL(ReKi) :: Tgrid ! Fractional distance between time grids. - REAL(ReKi) :: Xgrid ! Fractional distance between grids in the x direction. - REAL(ReKi) :: Xnorm ! Nondimensional downwind distance of the analysis point from upwind end of dataset. - REAL(ReKi) :: Ygrid ! Fractional distance between grids in the y direction. - REAL(ReKi) :: Ynorm ! Nondimensional lateral distance of the analysis point from right side of dataset (looking downwind). - REAL(ReKi) :: Zgrid ! Fractional distance between grids in the z direction. - REAL(ReKi) :: Zgrid_w ! Fractional distance between grids in the z direction for the w component. - REAL(ReKi) :: Znorm ! Nondimensional vertical distance of the analysis point from bottom of dataset. - REAL(ReKi) :: Znorm_w ! Nondimensional vertical distance of the analysis point from bottom of dataset for the w component. - - INTEGER :: IT ! Index for do loop - INTEGER :: IXHI ! Index for the more-positive x value. - INTEGER :: IXLO ! Index for the more-negative x value. - INTEGER :: IYHI ! Index for the more-positive y value. - INTEGER :: IYLO ! Index for the more-negative y value. - INTEGER :: IZHI ! Index for the more-positive z value. - INTEGER :: IZHI_w ! Index for the more-positive z value for the w component. - INTEGER :: IZLO ! Index for the more-negative z value. - INTEGER :: IZLO_w ! Index for the more-negative z value for the w component. - - REAL(ReKi) :: TempWindSpeed(3) ! Temporary variable to hold the windspeed before returning - - !------------------------------------------------------------------------------------------------- - ! Check that we've initialized everything first - !------------------------------------------------------------------------------------------------- - - IF ( .NOT. Initialized ) THEN - CALL WrScr( ' Initialialize the FDWind module before calling its subroutines.' ) - ErrStat = 1 - RETURN - ELSE - ErrStat = 0 - END IF - - !------------------------------------------------------------------------------------------------- - ! If the TIME is greater than the time for the last file read, read another set of files until we straddle the current time. - ! Stick with the last file if we've exhausted the data. - ! We're assuming here that the simulation time step is smaller than the wind-file time step. - !------------------------------------------------------------------------------------------------- - - IF ( Time < PrevTime .AND. Time < FDTime(Ind4Dold) ) THEN ! bjj: GET THE CORRECT TIME if we're going backward! - - !---------------------------------------------------------------------------------------------- - ! Determine the first file needed for this simulation. - !---------------------------------------------------------------------------------------------- - Ind4Dold = 1 ! Put the old stuff in the first part of the array. - Ind4Dnew = 2 ! Put the new stuff in the second part of the array. - - FDFileNo = Num4Dt - DO IT=1,Num4Dt - IF ( Times4D(IT) > Time ) THEN - FDFileNo = IT - 1 - EXIT - END IF - END DO ! IT - - !---------------------------------------------------------------------------------------------- - ! Open, read, and close the first set of files. - !---------------------------------------------------------------------------------------------- - FDTime(Ind4Dold) = Times4D(FDFileNo) ! Set the time for this file. - - IF ( ADVECT ) THEN - CALL Load4DData(Ind4Dold) ! load data stored in FDuData, FDvData, and FDwData arrays - ELSE - CALL LoadLESData( FDUnit, FDFileNo, Ind4Dold, ErrStat ) - END IF - - !---------------------------------------------------------------------------------------------- - ! Open, read, and close the second set of files. - !---------------------------------------------------------------------------------------------- - FDFileNo = MIN(FDFileNo + 1, Num4Dt) - Shft4Dnew = 0 - - IF ( ADVECT ) THEN - FDFileNo = MOD(FDFileNo-1,Num4Dt) + 1 - - IF (FDFileNo == 1) THEN - Shft4Dnew = Shft4Dnew + 1 - - IF (Ind4DAdv <= NumAdvect) THEN ! Ind4DAdv was set in ReadFDP - IF ( MOD( Shft4Dnew, Num4Dx ) == 0 ) THEN - CALL ReadAll4DData(FDUnit, ErrStat) - IF ( ErrStat /= 0 ) RETURN - END IF - END IF - - ENDIF - - FDTime(Ind4Dnew) = Times4D(FDFileNo) + Shft4Dnew*FDPer ! Set the time for this file. - - CALL Load4DData( Ind4Dnew ) ! shift the data - - ELSE - FDTime(Ind4Dnew) = Times4D(FDFileNo) ! Set the time for this file. -! - CALL LoadLESData( FDUnit, FDFileNo, Ind4Dnew, ErrStat ) - ENDIF - - END IF - - !------------------------------------------------------------------------------------------------- - ! Move forward in time - !------------------------------------------------------------------------------------------------- - - DO WHILE ( Time > FDTime(Ind4Dnew) .AND. ( Time < T_4D_En .OR. ADVECT ) ) - - Ind4Dnew = Ind4Dold ! Reverse array indices (1 or 2). - Ind4Dold = 3 - Ind4Dnew - FDFileNo = FDFileNo + 1 ! Increment file number. - - - IF ( ADVECT ) THEN - FDFileNo = MOD(FDFileNo-1,Num4Dt) + 1 - - IF (FDFileNo == 1) THEN - Shft4Dnew = Shft4Dnew + 1 - - IF (Ind4DAdv <= NumAdvect) THEN - IF ( MOD( Shft4Dnew, Num4Dx ) == 0 ) THEN - CALL ReadAll4DData(FDUnit, ErrStat) - IF ( ErrStat /= 0 ) RETURN - END IF - ENDIF - - ENDIF - - FDTime(Ind4Dnew) = Times4D(FDFileNo) + Shft4Dnew*FDPer - - CALL Load4DData( Ind4Dnew ) ! shift the data - ELSE - FDTime(Ind4Dnew) = Times4D(FDFileNo) - - CALL LoadLESData( FDUnit, FDFileNo, Ind4Dnew, ErrStat ) - ENDIF - - ENDDO - - - !................................................................................................. - ! Find the bounding rows, columns, and planes for the X,Y,Z position. The near, lower-right - ! corner is (1,1,1) when looking downwind. Make sure the lowest possible value is 1. - !................................................................................................. - - - !------------------------------------------------------------------------------------------------- - ! get values of Time for interpolation. Linear interpolation; Nearest-neighbor extrapolation. - !------------------------------------------------------------------------------------------------- - - ! Find out fractionally how far we are between grids in time and between grid points in each direction. - ! Limit values to avoid extrapolation. We need this for interpolation later on. - - Tgrid = MIN( MAX( ( Time - FDTime(Ind4Dold) )/( FDTime(Ind4Dnew) - FDTime(Ind4Dold) ), 0.0 ), 1.0 ) - - - !------------------------------------------------------------------------------------------------- - ! get values of X for interpolation. Grid is periodic in X. - !------------------------------------------------------------------------------------------------- - Xnorm = ( Xt + InputPosition(1) )/Xmax - - DO WHILE ( Xnorm < 0.0 ) ! Ensure Xnorm is not negative. The wave is periodic in x. - Xnorm = Xnorm + 1.0 - ENDDO - - Xgrid = MIN( MAX( MOD( Xnorm, DelXgrid ), 0.0 ), 1.0 ) - IXLo = MAX( MOD( INT( Xnorm*Num4DxD1 ) + 1, Num4DxD1 ), 1 ) - IXHi = MOD( IXLo, Num4DxD ) + 1 - - !------------------------------------------------------------------------------------------------- - ! get values of Y for interpolation. Grid is periodic in Y. - !------------------------------------------------------------------------------------------------- - Ynorm = ( Yt + InputPosition(2) )/Ymax - - DO WHILE ( Ynorm < 0.0 ) ! Ensure Ynorm is not negative. The wave is periodic in y. - Ynorm = Ynorm + 1.0 - ENDDO - - Ygrid = MIN( MAX( MOD( Ynorm, DelYgrid ), 0.0 ), 1.0 ) - IYLo = MAX( MOD( INT( Ynorm*Num4DyD1 ) + 1, Num4DyD1 ), 1 ) - IYHi = MOD( IYLo, Num4DyD ) + 1 - - !------------------------------------------------------------------------------------------------- - ! get values of Z for interpolation. Linear interpolation; Nearest-neighbor extrapolation. - !------------------------------------------------------------------------------------------------- - Znorm = MIN( MAX( ( Zt + InputPosition(3) - ZRef )/Zmax, 0.0 ), 1.0 ) !bjj: define ZRef - - Zgrid = MIN( MAX( MOD( Znorm, DelZgrid ), 0.0 ), 1.0 ) - IZLo = MAX( INT( Znorm*Num4DzD1 ) + 1, 1 ) - - ! If we are located at the upper end of the z dimension, decrement the index by one and set the grid coordinate to 1. - - IF ( IZLo == Num4DzD ) THEN - IZLo = Num4DzD1 - Zgrid = 1.0 - ENDIF - IZHi = IZLo + 1 - - !.............................................................................................. - ! Find the equivalent Znorm (Znorm_w) for the w-component, which may be shifted vertically - ! by half the original grid spacing. - !.............................................................................................. - - IF ( VertShft ) THEN - Znorm_w = MAX( Znorm - 0.5*DelZgrid/FD_DF_Z, 0.0 ) - ELSE - Znorm_w = Znorm - ENDIF - - Zgrid_w = MIN( MAX( MOD( Znorm_w, DelZgrid ), 0.0 ), 1.0 ) - IZLo_w = MAX( INT( Znorm_w*Num4DzD1 ) + 1, 1 ) - - IF ( IZLo_w == Num4DzD ) THEN - IZLo_w = Num4DzD1 - Zgrid_w = 1.0 - ENDIF - - IZHi_w = IZLo_w + 1 - - - !------------------------------------------------------------------------------------------------- - ! Interpolate for u component of wind within the grid. - !------------------------------------------------------------------------------------------------- - - Iylz = ( FDu(IXLo,IYLo,IZHi,Ind4Dold) - FDu(IXLo,IYLo,IZLo,Ind4Dold) )*Zgrid + FDu(IXLo,IYLo,IZLo,Ind4Dold) - Iyhz = ( FDu(IXLo,IYHi,IZHi,Ind4Dold) - FDu(IXLo,IYHi,IZLo,Ind4Dold) )*Zgrid + FDu(IXLo,IYHi,IZLo,Ind4Dold) - Ixlyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Iylz = ( FDu(IXHi,IYLo,IZHi,Ind4Dold) - FDu(IXHi,IYLo,IZLo,Ind4Dold) )*Zgrid + FDu(IXHi,IYLo,IZLo,Ind4Dold) - Iyhz = ( FDu(IXHi,IYHi,IZHi,Ind4Dold) - FDu(IXHi,IYHi,IZLo,Ind4Dold) )*Zgrid + FDu(IXHi,IYHi,IZLo,Ind4Dold) - Ixhyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Ixyzo = ( Ixhyz - Ixlyz )*Xgrid + Ixlyz - - Iylz = ( FDu(IXLo,IYLo,IZHi,Ind4Dnew) - FDu(IXLo,IYLo,IZLo,Ind4Dnew) )*Zgrid + FDu(IXLo,IYLo,IZLo,Ind4Dnew) - Iyhz = ( FDu(IXLo,IYHi,IZHi,Ind4Dnew) - FDu(IXLo,IYHi,IZLo,Ind4Dnew) )*Zgrid + FDu(IXLo,IYHi,IZLo,Ind4Dnew) - Ixlyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Iylz = ( FDu(IXHi,IYLo,IZHi,Ind4Dnew) - FDu(IXHi,IYLo,IZLo,Ind4Dnew) )*Zgrid + FDu(IXHi,IYLo,IZLo,Ind4Dnew) - Iyhz = ( FDu(IXHi,IYHi,IZHi,Ind4Dnew) - FDu(IXHi,IYHi,IZLo,Ind4Dnew) )*Zgrid + FDu(IXHi,IYHi,IZLo,Ind4Dnew) - Ixhyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Ixyzn = ( Ixhyz - Ixlyz )*Xgrid + Ixlyz - -! FD_GetWindSpeed%Velocity(1) = ( Ixyzn - Ixyzo )*Tgrid + Ixyzo - TempWindSpeed(1) = ( Ixyzn - Ixyzo )*Tgrid + Ixyzo - - !------------------------------------------------------------------------------------------------- - ! Interpolate for v component of wind within the grid. - !------------------------------------------------------------------------------------------------- - - Iylz = ( FDv(IXLo,IYLo,IZHi,Ind4Dold) - FDv(IXLo,IYLo,IZLo,Ind4Dold) )*Zgrid + FDv(IXLo,IYLo,IZLo,Ind4Dold) - Iyhz = ( FDv(IXLo,IYHi,IZHi,Ind4Dold) - FDv(IXLo,IYHi,IZLo,Ind4Dold) )*Zgrid + FDv(IXLo,IYHi,IZLo,Ind4Dold) - Ixlyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Iylz = ( FDv(IXHi,IYLo,IZHi,Ind4Dold) - FDv(IXHi,IYLo,IZLo,Ind4Dold) )*Zgrid + FDv(IXHi,IYLo,IZLo,Ind4Dold) - Iyhz = ( FDv(IXHi,IYHi,IZHi,Ind4Dold) - FDv(IXHi,IYHi,IZLo,Ind4Dold) )*Zgrid + FDv(IXHi,IYHi,IZLo,Ind4Dold) - Ixhyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Ixyzo = ( Ixhyz - Ixlyz )*Xgrid + Ixlyz - - Iylz = ( FDv(IXLo,IYLo,IZHi,Ind4Dnew) - FDv(IXLo,IYLo,IZLo,Ind4Dnew) )*Zgrid + FDv(IXLo,IYLo,IZLo,Ind4Dnew) - Iyhz = ( FDv(IXLo,IYHi,IZHi,Ind4Dnew) - FDv(IXLo,IYHi,IZLo,Ind4Dnew) )*Zgrid + FDv(IXLo,IYHi,IZLo,Ind4Dnew) - Ixlyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Iylz = ( FDv(IXHi,IYLo,IZHi,Ind4Dnew) - FDv(IXHi,IYLo,IZLo,Ind4Dnew) )*Zgrid + FDv(IXHi,IYLo,IZLo,Ind4Dnew) - Iyhz = ( FDv(IXHi,IYHi,IZHi,Ind4Dnew) - FDv(IXHi,IYHi,IZLo,Ind4Dnew) )*Zgrid + FDv(IXHi,IYHi,IZLo,Ind4Dnew) - Ixhyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Ixyzn = ( Ixhyz - Ixlyz )*Xgrid + Ixlyz - -!FIXME:delete -! FD_GetWindSpeed%Velocity(2) = ( Ixyzn - Ixyzo )*Tgrid + Ixyzo - TempWindSpeed(2) = ( Ixyzn - Ixyzo )*Tgrid + Ixyzo - - !------------------------------------------------------------------------------------------------- - ! Interpolate for w component of wind within the grid. - !------------------------------------------------------------------------------------------------- - !bjj: should Zgrid actually be Zgrid_w here? I changed it so that it's consistent - - Iylz = ( FDw(IXLo,IYLo,IZHi_w,Ind4Dold) - FDw(IXLo,IYLo,IZLo_w,Ind4Dold) )*Zgrid_w + FDw(IXLo,IYLo,IZLo_w,Ind4Dold) - Iyhz = ( FDw(IXLo,IYHi,IZHi_w,Ind4Dold) - FDw(IXLo,IYHi,IZLo_w,Ind4Dold) )*Zgrid_w + FDw(IXLo,IYHi,IZLo_w,Ind4Dold) - Ixlyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Iylz = ( FDw(IXHi,IYLo,IZHi_w,Ind4Dold) - FDw(IXHi,IYLo,IZLo_w,Ind4Dold) )*Zgrid_w + FDw(IXHi,IYLo,IZLo_w,Ind4Dold) - Iyhz = ( FDw(IXHi,IYHi,IZHi_w,Ind4Dold) - FDw(IXHi,IYHi,IZLo_w,Ind4Dold) )*Zgrid_w + FDw(IXHi,IYHi,IZLo_w,Ind4Dold) - Ixhyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Ixyzo = ( Ixhyz - Ixlyz )*Xgrid + Ixlyz - - Iylz = ( FDw(IXLo,IYLo,IZHi_w,Ind4Dnew) - FDw(IXLo,IYLo,IZLo_w,Ind4Dnew) )*Zgrid_w + FDw(IXLo,IYLo,IZLo_w,Ind4Dnew) - Iyhz = ( FDw(IXLo,IYHi,IZHi_w,Ind4Dnew) - FDw(IXLo,IYHi,IZLo_w,Ind4Dnew) )*Zgrid_w + FDw(IXLo,IYHi,IZLo_w,Ind4Dnew) - Ixlyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Iylz = ( FDw(IXHi,IYLo,IZHi_w,Ind4Dnew) - FDw(IXHi,IYLo,IZLo_w,Ind4Dnew) )*Zgrid_w + FDw(IXHi,IYLo,IZLo_w,Ind4Dnew) - Iyhz = ( FDw(IXHi,IYHi,IZHi_w,Ind4Dnew) - FDw(IXHi,IYHi,IZLo_w,Ind4Dnew) )*Zgrid_w + FDw(IXHi,IYHi,IZLo_w,Ind4Dnew) - Ixhyz = ( Iyhz - Iylz )*Ygrid + Iylz - - Ixyzn = ( Ixhyz - Ixlyz )*Xgrid + Ixlyz - -!FIXME:delete -! FD_GetWindSpeed%Velocity(3) = ( Ixyzn - Ixyzo )*Tgrid + Ixyzo - TempWindSpeed(3) = ( Ixyzn - Ixyzo )*Tgrid + Ixyzo - - ! Copy the windspeed info to the output - FD_GetWindSpeed = TempWindSpeed - - !------------------------------------------------------------------------------------------------- - ! Set the previous time here to compare with later... - !------------------------------------------------------------------------------------------------- - PrevTime = Time - - RETURN - -END FUNCTION FD_GetWindSpeed -!==================================================================================================== -SUBROUTINE FD_Terminate( ErrStat ) -! This subroutine deallocates arrays, closes files, and un-sets the initialization flag. -!---------------------------------------------------------------------------------------------------- - - INTEGER, INTENT(OUT) :: ErrStat ! return 0 if no errors; non-zero otherwise - - - CLOSE( FDunit ) - - ErrStat = 0 - - IF ( ALLOCATED( FDu ) ) DEALLOCATE( FDu, STAT=ErrStat ) - IF ( ALLOCATED( FDv ) ) DEALLOCATE( FDv, STAT=ErrStat ) - IF ( ALLOCATED( FDw ) ) DEALLOCATE( FDw, STAT=ErrStat ) - IF ( ALLOCATED( FDuData ) ) DEALLOCATE( FDuData, STAT=ErrStat ) - IF ( ALLOCATED( FDvData ) ) DEALLOCATE( FDvData, STAT=ErrStat ) - IF ( ALLOCATED( FDwData ) ) DEALLOCATE( FDwData, STAT=ErrStat ) - IF ( ALLOCATED( Times4D ) ) DEALLOCATE( Times4D, STAT=ErrStat ) - IF ( ALLOCATED( Times4DIx ) ) DEALLOCATE( Times4DIx, STAT=ErrStat ) - IF ( ALLOCATED( AdvFiles ) ) DEALLOCATE( AdvFiles, STAT=ErrStat ) - - Initialized = .FALSE. - -END SUBROUTINE FD_Terminate -!==================================================================================================== -END MODULE FDWind diff --git a/modules/inflowwind/src/FlowField_IO_Types.f90 b/modules/inflowwind/src/FlowField_IO_Types.f90 deleted file mode 100644 index ada6b8bc91..0000000000 --- a/modules/inflowwind/src/FlowField_IO_Types.f90 +++ /dev/null @@ -1,3534 +0,0 @@ -!STARTOFREGISTRYGENERATEDFILE 'FlowField_IO_Types.f90' -! -! WARNING This file is generated automatically by the FAST registry. -! Do not edit. Your changes to this file will be lost. -! -! FAST Registry -!********************************************************************************************************************************* -! FlowField_IO_Types -!................................................................................................................................. -! This file is part of FlowField_IO. -! -! Copyright (C) 2012-2016 National Renewable Energy Laboratory -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -! -! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. -! -!********************************************************************************************************************************* -!> This module contains the user-defined types needed in FlowField_IO. It also contains copy, destroy, pack, and -!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE FlowField_IO_Types -!--------------------------------------------------------------------------------------------------------------------------------- -USE IfW_FlowField_Types -USE NWTC_Library -IMPLICIT NONE -! ========= SteadyInitInputType ======= - TYPE, PUBLIC :: SteadyInitInputType - REAL(ReKi) :: HWindSpeed !< Horizontal wind speed [m/s] - REAL(ReKi) :: RefHt !< Reference height for horizontal wind speed [meters] - REAL(ReKi) :: PLExp !< Power law exponent [-] - END TYPE SteadyInitInputType -! ======================= -! ========= UniformInitInputType ======= - TYPE, PUBLIC :: UniformInitInputType - character(1024) :: WindFileName !< Name of the wind file to use [-] - REAL(ReKi) :: RefHt !< Reference height for horizontal wind speed [meters] - REAL(ReKi) :: RefLength !< Reference length for linear horizontal and vertical sheer [-] - REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] - LOGICAL :: UseInputFile = .true. !< Flag for toggling file based IO in wind type 2. [-] - TYPE(FileInfoType) :: PassedFileData !< Optional slot for wind type 2 data if file IO is not used. [-] - END TYPE UniformInitInputType -! ======================= -! ========= Grid3DInitInputType ======= - TYPE, PUBLIC :: Grid3DInitInputType - INTEGER(IntKi) :: ScaleMethod = 0 !< Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] [-] - REAL(ReKi) , DIMENSION(1:3) :: SF !< Turbulence scaling factor for each direction [ScaleMethod=1] [-] - REAL(ReKi) , DIMENSION(1:3) :: SigmaF !< Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] [-] - INTEGER(IntKi) :: WindProfileType = -1 !< Wind profile type (0=constant;1=logarithmic;2=power law) [-] - REAL(ReKi) :: RefHt = 0 !< Reference (hub) height of the grid [meters] - REAL(ReKi) :: URef = 0 !< Mean u-component wind speed at the reference height [meters] - REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] - REAL(ReKi) :: VLinShr = 0 !< Vertical linear wind shear coefficient (used for vertical linear wind profile type only) [-] - REAL(ReKi) :: HLinShr = 0 !< Horizontal linear wind shear coefficient (used for horizontal wind profile type only) [-] - REAL(ReKi) :: RefLength = 1 !< Reference (rotor) length of the grid (used for horizontal wind profile type only) [-] - REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] - REAL(ReKi) :: XOffset = 0 !< distance offset for FF wind files [m] - END TYPE Grid3DInitInputType -! ======================= -! ========= TurbSimInitInputType ======= - TYPE, PUBLIC :: TurbSimInitInputType - character(1024) :: WindFileName !< Name of the wind file to use [-] - END TYPE TurbSimInitInputType -! ======================= -! ========= BladedInitInputType ======= - TYPE, PUBLIC :: BladedInitInputType - character(1024) :: WindFileName !< Root filename [-] - LOGICAL :: NativeBladedFmt !< Whether this is native Bladed (needs wind profile and TI scaling) or not [-] - LOGICAL :: TowerFileExist !< Tower file exists [-] - INTEGER(IntKi) :: TurbineID = 0 !< Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm) [-] - LOGICAL :: FixedWindFileRootName = .false. !< Do the wind data files have a fixed (DEFAULT) file name? (used by FAST.Farm) [-] - END TYPE BladedInitInputType -! ======================= -! ========= BladedInitOutputType ======= - TYPE, PUBLIC :: BladedInitOutputType - REAL(ReKi) , DIMENSION(1:3) :: TI !< Turbulence intensity given in the file [-] - REAL(ReKi) :: PropagationDir !< Propogation direction from native Bladed format [degrees] - REAL(ReKi) :: VFlowAngle !< Vertical flow angle from native Bladed format [degrees] - END TYPE BladedInitOutputType -! ======================= -! ========= HAWCInitInputType ======= - TYPE, PUBLIC :: HAWCInitInputType - character(1024) , DIMENSION(1:3) :: WindFileName !< Name of the wind file to use [-] - INTEGER(IntKi) :: nx = 0 !< Number of grids in the x direction (in the 3 files above) [-] - INTEGER(IntKi) :: ny = 0 !< Number of grids in the y direction (in the 3 files above) [-] - INTEGER(IntKi) :: nz = 0 !< Number of grids in the z direction (in the 3 files above) [-] - REAL(ReKi) :: dx = 0 !< size of grids in the x direction (in the 3 files above) [-] - REAL(ReKi) :: dy = 0 !< size of grids in the y direction (in the 3 files above) [-] - REAL(ReKi) :: dz = 0 !< size of grids in the z direction (in the 3 files above) [-] - TYPE(Grid3DInitInputType) :: G3D !< Grid3D initialization input [-] - END TYPE HAWCInitInputType -! ======================= -! ========= UserInitInputType ======= - TYPE, PUBLIC :: UserInitInputType - REAL(SiKi) :: Dummy !< User field initialization input dummy value [-] - END TYPE UserInitInputType -! ======================= -! ========= Grid4DInitInputType ======= - TYPE, PUBLIC :: Grid4DInitInputType - INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of grid points in the x, y, z, and t directions [-] - REAL(ReKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s] - REAL(ReKi) , DIMENSION(1:3) :: pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:)) [m] - END TYPE Grid4DInitInputType -! ======================= -! ========= PointsInitInputType ======= - TYPE, PUBLIC :: PointsInitInputType - INTEGER(IntKi) :: Dummy !< Point field initialization input dummy value [-] - END TYPE PointsInitInputType -! ======================= -! ========= FlowField_IO_InitInputType ======= - TYPE, PUBLIC :: FlowField_IO_InitInputType - INTEGER(IntKi) :: WindType = 0 !< Type of the windfile [-] - INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file (-1 for none). Provided by IfW. [-] - REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] - REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [-] - LOGICAL :: VelInterpCubic = .false. !< Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7] [-] - LOGICAL :: OutputAccel = .false. !< Flag to indicate that wind acceleration should be output [-] - TYPE(SteadyInitInputType) :: Steady !< [-] - TYPE(UniformInitInputType) :: Uniform !< [-] - TYPE(TurbSimInitInputType) :: TurbSim !< [-] - TYPE(BladedInitInputType) :: Bladed !< [-] - TYPE(HAWCInitInputType) :: HAWC !< [-] - TYPE(UserInitInputType) :: User !< [-] - TYPE(Grid4DInitInputType) :: Grid4D !< [-] - TYPE(PointsInitInputType) :: Points !< [-] - END TYPE FlowField_IO_InitInputType -! ======================= -! ========= WindFileDat ======= - TYPE, PUBLIC :: WindFileDat - character(1024) :: FileName !< Name of the windfile retrieved [-] - INTEGER(IntKi) :: WindType = 0 !< Type of the windfile [-] - REAL(ReKi) :: RefHt !< Reference height given in file [meters] - LOGICAL :: RefHt_Set !< Reference height was given in file [-] - REAL(DbKi) :: DT !< TimeStep of the wind file -- zero value for none [seconds] - INTEGER(IntKi) :: NumTSteps !< Number of timesteps in the time range of wind file [-] - LOGICAL :: ConstantDT !< Timesteps are the same throughout file [-] - REAL(ReKi) , DIMENSION(1:2) :: TRange !< Time range of the wind file [seconds] - LOGICAL :: TRange_Limited !< TRange limits strictly enforced [-] - REAL(ReKi) , DIMENSION(1:2) :: YRange !< Range in y direction [meters] - LOGICAL :: YRange_Limited !< YRange limits strictly enforced [-] - REAL(ReKi) , DIMENSION(1:2) :: ZRange !< Range in z direction [meters] - LOGICAL :: ZRange_Limited !< ZRange limits strictly enforced [-] - INTEGER(IntKi) :: BinaryFormat !< Binary format identifier [-] - LOGICAL :: IsBinary !< Windfile is a binary file [-] - REAL(ReKi) , DIMENSION(1:3) :: TI !< Turbulence intensity (U,V,W) [-] - LOGICAL :: TI_listed !< Turbulence intesity given in file [-] - REAL(ReKi) :: MWS !< Approximate mean wind speed [-] - END TYPE WindFileDat -! ======================= -! ========= FlowField_IO_InitOutputType ======= - TYPE, PUBLIC :: FlowField_IO_InitOutputType - TYPE(ProgDesc) :: Ver !< Version information off FFWind submodule [-] - TYPE(WindFileDat) :: FileDat !< [-] - TYPE(BladedInitOutputType) :: Bladed !< [-] - END TYPE FlowField_IO_InitOutputType -! ======================= -CONTAINS - SUBROUTINE FlowField_IO_CopySteadyInitInputType( SrcSteadyInitInputTypeData, DstSteadyInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(SteadyInitInputType), INTENT(IN) :: SrcSteadyInitInputTypeData - TYPE(SteadyInitInputType), INTENT(INOUT) :: DstSteadyInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopySteadyInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstSteadyInitInputTypeData%HWindSpeed = SrcSteadyInitInputTypeData%HWindSpeed - DstSteadyInitInputTypeData%RefHt = SrcSteadyInitInputTypeData%RefHt - DstSteadyInitInputTypeData%PLExp = SrcSteadyInitInputTypeData%PLExp - END SUBROUTINE FlowField_IO_CopySteadyInitInputType - - SUBROUTINE FlowField_IO_DestroySteadyInitInputType( SteadyInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(SteadyInitInputType), INTENT(INOUT) :: SteadyInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroySteadyInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroySteadyInitInputType - - SUBROUTINE FlowField_IO_PackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(SteadyInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackSteadyInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! HWindSpeed - Re_BufSz = Re_BufSz + 1 ! RefHt - Re_BufSz = Re_BufSz + 1 ! PLExp - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%HWindSpeed - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PLExp - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackSteadyInitInputType - - SUBROUTINE FlowField_IO_UnPackSteadyInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(SteadyInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackSteadyInitInputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%HWindSpeed = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefHt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%PLExp = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackSteadyInitInputType - - SUBROUTINE FlowField_IO_CopyUniformInitInputType( SrcUniformInitInputTypeData, DstUniformInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(UniformInitInputType), INTENT(IN) :: SrcUniformInitInputTypeData - TYPE(UniformInitInputType), INTENT(INOUT) :: DstUniformInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyUniformInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstUniformInitInputTypeData%WindFileName = SrcUniformInitInputTypeData%WindFileName - DstUniformInitInputTypeData%RefHt = SrcUniformInitInputTypeData%RefHt - DstUniformInitInputTypeData%RefLength = SrcUniformInitInputTypeData%RefLength - DstUniformInitInputTypeData%PropagationDir = SrcUniformInitInputTypeData%PropagationDir - DstUniformInitInputTypeData%UseInputFile = SrcUniformInitInputTypeData%UseInputFile - CALL NWTC_Library_Copyfileinfotype( SrcUniformInitInputTypeData%PassedFileData, DstUniformInitInputTypeData%PassedFileData, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE FlowField_IO_CopyUniformInitInputType - - SUBROUTINE FlowField_IO_DestroyUniformInitInputType( UniformInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(UniformInitInputType), INTENT(INOUT) :: UniformInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyUniformInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL NWTC_Library_Destroyfileinfotype( UniformInitInputTypeData%PassedFileData, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE FlowField_IO_DestroyUniformInitInputType - - SUBROUTINE FlowField_IO_PackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(UniformInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackUniformInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName - Re_BufSz = Re_BufSz + 1 ! RefHt - Re_BufSz = Re_BufSz + 1 ! RefLength - Re_BufSz = Re_BufSz + 1 ! PropagationDir - Int_BufSz = Int_BufSz + 1 ! UseInputFile - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! PassedFileData: size of buffers for each call to pack subtype - CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedFileData, ErrStat2, ErrMsg2, .TRUE. ) ! PassedFileData - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! PassedFileData - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! PassedFileData - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! PassedFileData - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%WindFileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefLength - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PropagationDir - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%UseInputFile, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedFileData, ErrStat2, ErrMsg2, OnlySize ) ! PassedFileData - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE FlowField_IO_PackUniformInitInputType - - SUBROUTINE FlowField_IO_UnPackUniformInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(UniformInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackUniformInitInputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%WindFileName) - OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%RefHt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefLength = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%PropagationDir = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%UseInputFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseInputFile) - Int_Xferred = Int_Xferred + 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackfileinfotype( Re_Buf, Db_Buf, Int_Buf, OutData%PassedFileData, ErrStat2, ErrMsg2 ) ! PassedFileData - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE FlowField_IO_UnPackUniformInitInputType - - SUBROUTINE FlowField_IO_CopyGrid3DInitInputType( SrcGrid3DInitInputTypeData, DstGrid3DInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(Grid3DInitInputType), INTENT(IN) :: SrcGrid3DInitInputTypeData - TYPE(Grid3DInitInputType), INTENT(INOUT) :: DstGrid3DInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyGrid3DInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstGrid3DInitInputTypeData%ScaleMethod = SrcGrid3DInitInputTypeData%ScaleMethod - DstGrid3DInitInputTypeData%SF = SrcGrid3DInitInputTypeData%SF - DstGrid3DInitInputTypeData%SigmaF = SrcGrid3DInitInputTypeData%SigmaF - DstGrid3DInitInputTypeData%WindProfileType = SrcGrid3DInitInputTypeData%WindProfileType - DstGrid3DInitInputTypeData%RefHt = SrcGrid3DInitInputTypeData%RefHt - DstGrid3DInitInputTypeData%URef = SrcGrid3DInitInputTypeData%URef - DstGrid3DInitInputTypeData%PLExp = SrcGrid3DInitInputTypeData%PLExp - DstGrid3DInitInputTypeData%VLinShr = SrcGrid3DInitInputTypeData%VLinShr - DstGrid3DInitInputTypeData%HLinShr = SrcGrid3DInitInputTypeData%HLinShr - DstGrid3DInitInputTypeData%RefLength = SrcGrid3DInitInputTypeData%RefLength - DstGrid3DInitInputTypeData%Z0 = SrcGrid3DInitInputTypeData%Z0 - DstGrid3DInitInputTypeData%XOffset = SrcGrid3DInitInputTypeData%XOffset - END SUBROUTINE FlowField_IO_CopyGrid3DInitInputType - - SUBROUTINE FlowField_IO_DestroyGrid3DInitInputType( Grid3DInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(Grid3DInitInputType), INTENT(INOUT) :: Grid3DInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyGrid3DInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyGrid3DInitInputType - - SUBROUTINE FlowField_IO_PackGrid3DInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(Grid3DInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackGrid3DInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! ScaleMethod - Re_BufSz = Re_BufSz + SIZE(InData%SF) ! SF - Re_BufSz = Re_BufSz + SIZE(InData%SigmaF) ! SigmaF - Int_BufSz = Int_BufSz + 1 ! WindProfileType - Re_BufSz = Re_BufSz + 1 ! RefHt - Re_BufSz = Re_BufSz + 1 ! URef - Re_BufSz = Re_BufSz + 1 ! PLExp - Re_BufSz = Re_BufSz + 1 ! VLinShr - Re_BufSz = Re_BufSz + 1 ! HLinShr - Re_BufSz = Re_BufSz + 1 ! RefLength - Re_BufSz = Re_BufSz + 1 ! Z0 - Re_BufSz = Re_BufSz + 1 ! XOffset - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = InData%ScaleMethod - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%SF,1), UBOUND(InData%SF,1) - ReKiBuf(Re_Xferred) = InData%SF(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%SigmaF,1), UBOUND(InData%SigmaF,1) - ReKiBuf(Re_Xferred) = InData%SigmaF(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = InData%WindProfileType - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%URef - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PLExp - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VLinShr - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%HLinShr - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefLength - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Z0 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%XOffset - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackGrid3DInitInputType - - SUBROUTINE FlowField_IO_UnPackGrid3DInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(Grid3DInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackGrid3DInitInputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%ScaleMethod = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%SF,1) - i1_u = UBOUND(OutData%SF,1) - DO i1 = LBOUND(OutData%SF,1), UBOUND(OutData%SF,1) - OutData%SF(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%SigmaF,1) - i1_u = UBOUND(OutData%SigmaF,1) - DO i1 = LBOUND(OutData%SigmaF,1), UBOUND(OutData%SigmaF,1) - OutData%SigmaF(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%WindProfileType = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%RefHt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%URef = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%PLExp = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VLinShr = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%HLinShr = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefLength = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Z0 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%XOffset = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackGrid3DInitInputType - - SUBROUTINE FlowField_IO_CopyTurbSimInitInputType( SrcTurbSimInitInputTypeData, DstTurbSimInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(TurbSimInitInputType), INTENT(IN) :: SrcTurbSimInitInputTypeData - TYPE(TurbSimInitInputType), INTENT(INOUT) :: DstTurbSimInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyTurbSimInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstTurbSimInitInputTypeData%WindFileName = SrcTurbSimInitInputTypeData%WindFileName - END SUBROUTINE FlowField_IO_CopyTurbSimInitInputType - - SUBROUTINE FlowField_IO_DestroyTurbSimInitInputType( TurbSimInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(TurbSimInitInputType), INTENT(INOUT) :: TurbSimInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyTurbSimInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyTurbSimInitInputType - - SUBROUTINE FlowField_IO_PackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(TurbSimInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackTurbSimInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%WindFileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END SUBROUTINE FlowField_IO_PackTurbSimInitInputType - - SUBROUTINE FlowField_IO_UnPackTurbSimInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(TurbSimInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackTurbSimInitInputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%WindFileName) - OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END SUBROUTINE FlowField_IO_UnPackTurbSimInitInputType - - SUBROUTINE FlowField_IO_CopyBladedInitInputType( SrcBladedInitInputTypeData, DstBladedInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(BladedInitInputType), INTENT(IN) :: SrcBladedInitInputTypeData - TYPE(BladedInitInputType), INTENT(INOUT) :: DstBladedInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyBladedInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstBladedInitInputTypeData%WindFileName = SrcBladedInitInputTypeData%WindFileName - DstBladedInitInputTypeData%NativeBladedFmt = SrcBladedInitInputTypeData%NativeBladedFmt - DstBladedInitInputTypeData%TowerFileExist = SrcBladedInitInputTypeData%TowerFileExist - DstBladedInitInputTypeData%TurbineID = SrcBladedInitInputTypeData%TurbineID - DstBladedInitInputTypeData%FixedWindFileRootName = SrcBladedInitInputTypeData%FixedWindFileRootName - END SUBROUTINE FlowField_IO_CopyBladedInitInputType - - SUBROUTINE FlowField_IO_DestroyBladedInitInputType( BladedInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(BladedInitInputType), INTENT(INOUT) :: BladedInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyBladedInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyBladedInitInputType - - SUBROUTINE FlowField_IO_PackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(BladedInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackBladedInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName - Int_BufSz = Int_BufSz + 1 ! NativeBladedFmt - Int_BufSz = Int_BufSz + 1 ! TowerFileExist - Int_BufSz = Int_BufSz + 1 ! TurbineID - Int_BufSz = Int_BufSz + 1 ! FixedWindFileRootName - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%WindFileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = TRANSFER(InData%NativeBladedFmt, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%TowerFileExist, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%TurbineID - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%FixedWindFileRootName, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE FlowField_IO_PackBladedInitInputType - - SUBROUTINE FlowField_IO_UnPackBladedInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(BladedInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackBladedInitInputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%WindFileName) - OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%NativeBladedFmt = TRANSFER(IntKiBuf(Int_Xferred), OutData%NativeBladedFmt) - Int_Xferred = Int_Xferred + 1 - OutData%TowerFileExist = TRANSFER(IntKiBuf(Int_Xferred), OutData%TowerFileExist) - Int_Xferred = Int_Xferred + 1 - OutData%TurbineID = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%FixedWindFileRootName = TRANSFER(IntKiBuf(Int_Xferred), OutData%FixedWindFileRootName) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackBladedInitInputType - - SUBROUTINE FlowField_IO_CopyBladedInitOutputType( SrcBladedInitOutputTypeData, DstBladedInitOutputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(BladedInitOutputType), INTENT(IN) :: SrcBladedInitOutputTypeData - TYPE(BladedInitOutputType), INTENT(INOUT) :: DstBladedInitOutputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyBladedInitOutputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstBladedInitOutputTypeData%TI = SrcBladedInitOutputTypeData%TI - DstBladedInitOutputTypeData%PropagationDir = SrcBladedInitOutputTypeData%PropagationDir - DstBladedInitOutputTypeData%VFlowAngle = SrcBladedInitOutputTypeData%VFlowAngle - END SUBROUTINE FlowField_IO_CopyBladedInitOutputType - - SUBROUTINE FlowField_IO_DestroyBladedInitOutputType( BladedInitOutputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(BladedInitOutputType), INTENT(INOUT) :: BladedInitOutputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyBladedInitOutputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyBladedInitOutputType - - SUBROUTINE FlowField_IO_PackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(BladedInitOutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackBladedInitOutputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI - Re_BufSz = Re_BufSz + 1 ! PropagationDir - Re_BufSz = Re_BufSz + 1 ! VFlowAngle - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO i1 = LBOUND(InData%TI,1), UBOUND(InData%TI,1) - ReKiBuf(Re_Xferred) = InData%TI(i1) - Re_Xferred = Re_Xferred + 1 - END DO - ReKiBuf(Re_Xferred) = InData%PropagationDir - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VFlowAngle - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackBladedInitOutputType - - SUBROUTINE FlowField_IO_UnPackBladedInitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(BladedInitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackBladedInitOutputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - i1_l = LBOUND(OutData%TI,1) - i1_u = UBOUND(OutData%TI,1) - DO i1 = LBOUND(OutData%TI,1), UBOUND(OutData%TI,1) - OutData%TI(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%PropagationDir = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VFlowAngle = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackBladedInitOutputType - - SUBROUTINE FlowField_IO_CopyHAWCInitInputType( SrcHAWCInitInputTypeData, DstHAWCInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(HAWCInitInputType), INTENT(IN) :: SrcHAWCInitInputTypeData - TYPE(HAWCInitInputType), INTENT(INOUT) :: DstHAWCInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyHAWCInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstHAWCInitInputTypeData%WindFileName = SrcHAWCInitInputTypeData%WindFileName - DstHAWCInitInputTypeData%nx = SrcHAWCInitInputTypeData%nx - DstHAWCInitInputTypeData%ny = SrcHAWCInitInputTypeData%ny - DstHAWCInitInputTypeData%nz = SrcHAWCInitInputTypeData%nz - DstHAWCInitInputTypeData%dx = SrcHAWCInitInputTypeData%dx - DstHAWCInitInputTypeData%dy = SrcHAWCInitInputTypeData%dy - DstHAWCInitInputTypeData%dz = SrcHAWCInitInputTypeData%dz - CALL FlowField_IO_Copygrid3dinitinputtype( SrcHAWCInitInputTypeData%G3D, DstHAWCInitInputTypeData%G3D, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE FlowField_IO_CopyHAWCInitInputType - - SUBROUTINE FlowField_IO_DestroyHAWCInitInputType( HAWCInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(HAWCInitInputType), INTENT(INOUT) :: HAWCInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyHAWCInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL FlowField_IO_Destroygrid3dinitinputtype( HAWCInitInputTypeData%G3D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE FlowField_IO_DestroyHAWCInitInputType - - SUBROUTINE FlowField_IO_PackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(HAWCInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackHAWCInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + SIZE(InData%WindFileName)*LEN(InData%WindFileName) ! WindFileName - Int_BufSz = Int_BufSz + 1 ! nx - Int_BufSz = Int_BufSz + 1 ! ny - Int_BufSz = Int_BufSz + 1 ! nz - Re_BufSz = Re_BufSz + 1 ! dx - Re_BufSz = Re_BufSz + 1 ! dy - Re_BufSz = Re_BufSz + 1 ! dz - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! G3D: size of buffers for each call to pack subtype - CALL FlowField_IO_Packgrid3dinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%G3D, ErrStat2, ErrMsg2, .TRUE. ) ! G3D - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! G3D - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! G3D - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! G3D - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO i1 = LBOUND(InData%WindFileName,1), UBOUND(InData%WindFileName,1) - DO I = 1, LEN(InData%WindFileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - IntKiBuf(Int_Xferred) = InData%nx - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%ny - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%nz - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%dx - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%dy - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%dz - Re_Xferred = Re_Xferred + 1 - CALL FlowField_IO_Packgrid3dinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%G3D, ErrStat2, ErrMsg2, OnlySize ) ! G3D - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE FlowField_IO_PackHAWCInitInputType - - SUBROUTINE FlowField_IO_UnPackHAWCInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(HAWCInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackHAWCInitInputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - i1_l = LBOUND(OutData%WindFileName,1) - i1_u = UBOUND(OutData%WindFileName,1) - DO i1 = LBOUND(OutData%WindFileName,1), UBOUND(OutData%WindFileName,1) - DO I = 1, LEN(OutData%WindFileName) - OutData%WindFileName(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - OutData%nx = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%ny = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%nz = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%dx = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%dy = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%dz = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackgrid3dinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%G3D, ErrStat2, ErrMsg2 ) ! G3D - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE FlowField_IO_UnPackHAWCInitInputType - - SUBROUTINE FlowField_IO_CopyUserInitInputType( SrcUserInitInputTypeData, DstUserInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(UserInitInputType), INTENT(IN) :: SrcUserInitInputTypeData - TYPE(UserInitInputType), INTENT(INOUT) :: DstUserInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyUserInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstUserInitInputTypeData%Dummy = SrcUserInitInputTypeData%Dummy - END SUBROUTINE FlowField_IO_CopyUserInitInputType - - SUBROUTINE FlowField_IO_DestroyUserInitInputType( UserInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(UserInitInputType), INTENT(INOUT) :: UserInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyUserInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyUserInitInputType - - SUBROUTINE FlowField_IO_PackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(UserInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackUserInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! Dummy - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%Dummy - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackUserInitInputType - - SUBROUTINE FlowField_IO_UnPackUserInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(UserInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackUserInitInputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackUserInitInputType - - SUBROUTINE FlowField_IO_CopyGrid4DInitInputType( SrcGrid4DInitInputTypeData, DstGrid4DInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(Grid4DInitInputType), INTENT(IN) :: SrcGrid4DInitInputTypeData - TYPE(Grid4DInitInputType), INTENT(INOUT) :: DstGrid4DInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyGrid4DInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstGrid4DInitInputTypeData%n = SrcGrid4DInitInputTypeData%n - DstGrid4DInitInputTypeData%delta = SrcGrid4DInitInputTypeData%delta - DstGrid4DInitInputTypeData%pZero = SrcGrid4DInitInputTypeData%pZero - END SUBROUTINE FlowField_IO_CopyGrid4DInitInputType - - SUBROUTINE FlowField_IO_DestroyGrid4DInitInputType( Grid4DInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(Grid4DInitInputType), INTENT(INOUT) :: Grid4DInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyGrid4DInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyGrid4DInitInputType - - SUBROUTINE FlowField_IO_PackGrid4DInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(Grid4DInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackGrid4DInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + SIZE(InData%n) ! n - Re_BufSz = Re_BufSz + SIZE(InData%delta) ! delta - Re_BufSz = Re_BufSz + SIZE(InData%pZero) ! pZero - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO i1 = LBOUND(InData%n,1), UBOUND(InData%n,1) - IntKiBuf(Int_Xferred) = InData%n(i1) - Int_Xferred = Int_Xferred + 1 - END DO - DO i1 = LBOUND(InData%delta,1), UBOUND(InData%delta,1) - ReKiBuf(Re_Xferred) = InData%delta(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%pZero,1), UBOUND(InData%pZero,1) - ReKiBuf(Re_Xferred) = InData%pZero(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END SUBROUTINE FlowField_IO_PackGrid4DInitInputType - - SUBROUTINE FlowField_IO_UnPackGrid4DInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(Grid4DInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackGrid4DInitInputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - i1_l = LBOUND(OutData%n,1) - i1_u = UBOUND(OutData%n,1) - DO i1 = LBOUND(OutData%n,1), UBOUND(OutData%n,1) - OutData%n(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - i1_l = LBOUND(OutData%delta,1) - i1_u = UBOUND(OutData%delta,1) - DO i1 = LBOUND(OutData%delta,1), UBOUND(OutData%delta,1) - OutData%delta(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%pZero,1) - i1_u = UBOUND(OutData%pZero,1) - DO i1 = LBOUND(OutData%pZero,1), UBOUND(OutData%pZero,1) - OutData%pZero(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END SUBROUTINE FlowField_IO_UnPackGrid4DInitInputType - - SUBROUTINE FlowField_IO_CopyPointsInitInputType( SrcPointsInitInputTypeData, DstPointsInitInputTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(PointsInitInputType), INTENT(IN) :: SrcPointsInitInputTypeData - TYPE(PointsInitInputType), INTENT(INOUT) :: DstPointsInitInputTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyPointsInitInputType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstPointsInitInputTypeData%Dummy = SrcPointsInitInputTypeData%Dummy - END SUBROUTINE FlowField_IO_CopyPointsInitInputType - - SUBROUTINE FlowField_IO_DestroyPointsInitInputType( PointsInitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(PointsInitInputType), INTENT(INOUT) :: PointsInitInputTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyPointsInitInputType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyPointsInitInputType - - SUBROUTINE FlowField_IO_PackPointsInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(PointsInitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackPointsInitInputType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! Dummy - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = InData%Dummy - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE FlowField_IO_PackPointsInitInputType - - SUBROUTINE FlowField_IO_UnPackPointsInitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(PointsInitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackPointsInitInputType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%Dummy = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackPointsInitInputType - - SUBROUTINE FlowField_IO_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FlowField_IO_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(FlowField_IO_InitInputType), INTENT(INOUT) :: DstInitInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyInitInput' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitInputData%WindType = SrcInitInputData%WindType - DstInitInputData%SumFileUnit = SrcInitInputData%SumFileUnit - DstInitInputData%PropagationDir = SrcInitInputData%PropagationDir - DstInitInputData%VFlowAngle = SrcInitInputData%VFlowAngle - DstInitInputData%VelInterpCubic = SrcInitInputData%VelInterpCubic - DstInitInputData%OutputAccel = SrcInitInputData%OutputAccel - CALL FlowField_IO_Copysteadyinitinputtype( SrcInitInputData%Steady, DstInitInputData%Steady, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copyuniforminitinputtype( SrcInitInputData%Uniform, DstInitInputData%Uniform, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copyturbsiminitinputtype( SrcInitInputData%TurbSim, DstInitInputData%TurbSim, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copybladedinitinputtype( SrcInitInputData%Bladed, DstInitInputData%Bladed, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copyhawcinitinputtype( SrcInitInputData%HAWC, DstInitInputData%HAWC, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copyuserinitinputtype( SrcInitInputData%User, DstInitInputData%User, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copygrid4dinitinputtype( SrcInitInputData%Grid4D, DstInitInputData%Grid4D, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copypointsinitinputtype( SrcInitInputData%Points, DstInitInputData%Points, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE FlowField_IO_CopyInitInput - - SUBROUTINE FlowField_IO_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(FlowField_IO_InitInputType), INTENT(INOUT) :: InitInputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyInitInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL FlowField_IO_Destroysteadyinitinputtype( InitInputData%Steady, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroyuniforminitinputtype( InitInputData%Uniform, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroyturbsiminitinputtype( InitInputData%TurbSim, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroybladedinitinputtype( InitInputData%Bladed, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroyhawcinitinputtype( InitInputData%HAWC, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroyuserinitinputtype( InitInputData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroygrid4dinitinputtype( InitInputData%Grid4D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroypointsinitinputtype( InitInputData%Points, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE FlowField_IO_DestroyInitInput - - SUBROUTINE FlowField_IO_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(FlowField_IO_InitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackInitInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! WindType - Int_BufSz = Int_BufSz + 1 ! SumFileUnit - Re_BufSz = Re_BufSz + 1 ! PropagationDir - Re_BufSz = Re_BufSz + 1 ! VFlowAngle - Int_BufSz = Int_BufSz + 1 ! VelInterpCubic - Int_BufSz = Int_BufSz + 1 ! OutputAccel - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Steady: size of buffers for each call to pack subtype - CALL FlowField_IO_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, .TRUE. ) ! Steady - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Steady - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Steady - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Steady - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! Uniform: size of buffers for each call to pack subtype - CALL FlowField_IO_Packuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, .TRUE. ) ! Uniform - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Uniform - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Uniform - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Uniform - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! TurbSim: size of buffers for each call to pack subtype - CALL FlowField_IO_Packturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%TurbSim, ErrStat2, ErrMsg2, .TRUE. ) ! TurbSim - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! TurbSim - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! TurbSim - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! TurbSim - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! Bladed: size of buffers for each call to pack subtype - CALL FlowField_IO_Packbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, .TRUE. ) ! Bladed - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Bladed - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Bladed - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Bladed - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! HAWC: size of buffers for each call to pack subtype - CALL FlowField_IO_Packhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%HAWC, ErrStat2, ErrMsg2, .TRUE. ) ! HAWC - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! HAWC - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! HAWC - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! HAWC - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! User: size of buffers for each call to pack subtype - CALL FlowField_IO_Packuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, .TRUE. ) ! User - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! User - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! User - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! User - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! Grid4D: size of buffers for each call to pack subtype - CALL FlowField_IO_Packgrid4dinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid4D - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Grid4D - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Grid4D - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Grid4D - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! Points: size of buffers for each call to pack subtype - CALL FlowField_IO_Packpointsinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, .TRUE. ) ! Points - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Points - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Points - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Points - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = InData%WindType - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%SumFileUnit - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PropagationDir - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VFlowAngle - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%VelInterpCubic, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%OutputAccel, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - CALL FlowField_IO_Packsteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Steady, ErrStat2, ErrMsg2, OnlySize ) ! Steady - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL FlowField_IO_Packuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Uniform, ErrStat2, ErrMsg2, OnlySize ) ! Uniform - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL FlowField_IO_Packturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%TurbSim, ErrStat2, ErrMsg2, OnlySize ) ! TurbSim - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL FlowField_IO_Packbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, OnlySize ) ! Bladed - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL FlowField_IO_Packhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%HAWC, ErrStat2, ErrMsg2, OnlySize ) ! HAWC - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL FlowField_IO_Packuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%User, ErrStat2, ErrMsg2, OnlySize ) ! User - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL FlowField_IO_Packgrid4dinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, OnlySize ) ! Grid4D - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL FlowField_IO_Packpointsinitinputtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, OnlySize ) ! Points - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE FlowField_IO_PackInitInput - - SUBROUTINE FlowField_IO_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(FlowField_IO_InitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackInitInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%WindType = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%SumFileUnit = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%PropagationDir = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VFlowAngle = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VelInterpCubic = TRANSFER(IntKiBuf(Int_Xferred), OutData%VelInterpCubic) - Int_Xferred = Int_Xferred + 1 - OutData%OutputAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutputAccel) - Int_Xferred = Int_Xferred + 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpacksteadyinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Steady, ErrStat2, ErrMsg2 ) ! Steady - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackuniforminitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Uniform, ErrStat2, ErrMsg2 ) ! Uniform - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackturbsiminitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%TurbSim, ErrStat2, ErrMsg2 ) ! TurbSim - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackbladedinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Bladed, ErrStat2, ErrMsg2 ) ! Bladed - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackhawcinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%HAWC, ErrStat2, ErrMsg2 ) ! HAWC - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackuserinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%User, ErrStat2, ErrMsg2 ) ! User - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackgrid4dinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid4D, ErrStat2, ErrMsg2 ) ! Grid4D - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackpointsinitinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Points, ErrStat2, ErrMsg2 ) ! Points - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE FlowField_IO_UnPackInitInput - - SUBROUTINE FlowField_IO_CopyWindFileDat( SrcWindFileDatData, DstWindFileDatData, CtrlCode, ErrStat, ErrMsg ) - TYPE(WindFileDat), INTENT(IN) :: SrcWindFileDatData - TYPE(WindFileDat), INTENT(INOUT) :: DstWindFileDatData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyWindFileDat' -! - ErrStat = ErrID_None - ErrMsg = "" - DstWindFileDatData%FileName = SrcWindFileDatData%FileName - DstWindFileDatData%WindType = SrcWindFileDatData%WindType - DstWindFileDatData%RefHt = SrcWindFileDatData%RefHt - DstWindFileDatData%RefHt_Set = SrcWindFileDatData%RefHt_Set - DstWindFileDatData%DT = SrcWindFileDatData%DT - DstWindFileDatData%NumTSteps = SrcWindFileDatData%NumTSteps - DstWindFileDatData%ConstantDT = SrcWindFileDatData%ConstantDT - DstWindFileDatData%TRange = SrcWindFileDatData%TRange - DstWindFileDatData%TRange_Limited = SrcWindFileDatData%TRange_Limited - DstWindFileDatData%YRange = SrcWindFileDatData%YRange - DstWindFileDatData%YRange_Limited = SrcWindFileDatData%YRange_Limited - DstWindFileDatData%ZRange = SrcWindFileDatData%ZRange - DstWindFileDatData%ZRange_Limited = SrcWindFileDatData%ZRange_Limited - DstWindFileDatData%BinaryFormat = SrcWindFileDatData%BinaryFormat - DstWindFileDatData%IsBinary = SrcWindFileDatData%IsBinary - DstWindFileDatData%TI = SrcWindFileDatData%TI - DstWindFileDatData%TI_listed = SrcWindFileDatData%TI_listed - DstWindFileDatData%MWS = SrcWindFileDatData%MWS - END SUBROUTINE FlowField_IO_CopyWindFileDat - - SUBROUTINE FlowField_IO_DestroyWindFileDat( WindFileDatData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(WindFileDat), INTENT(INOUT) :: WindFileDatData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyWindFileDat' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE FlowField_IO_DestroyWindFileDat - - SUBROUTINE FlowField_IO_PackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(WindFileDat), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackWindFileDat' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%FileName) ! FileName - Int_BufSz = Int_BufSz + 1 ! WindType - Re_BufSz = Re_BufSz + 1 ! RefHt - Int_BufSz = Int_BufSz + 1 ! RefHt_Set - Db_BufSz = Db_BufSz + 1 ! DT - Int_BufSz = Int_BufSz + 1 ! NumTSteps - Int_BufSz = Int_BufSz + 1 ! ConstantDT - Re_BufSz = Re_BufSz + SIZE(InData%TRange) ! TRange - Int_BufSz = Int_BufSz + 1 ! TRange_Limited - Re_BufSz = Re_BufSz + SIZE(InData%YRange) ! YRange - Int_BufSz = Int_BufSz + 1 ! YRange_Limited - Re_BufSz = Re_BufSz + SIZE(InData%ZRange) ! ZRange - Int_BufSz = Int_BufSz + 1 ! ZRange_Limited - Int_BufSz = Int_BufSz + 1 ! BinaryFormat - Int_BufSz = Int_BufSz + 1 ! IsBinary - Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI - Int_BufSz = Int_BufSz + 1 ! TI_listed - Re_BufSz = Re_BufSz + 1 ! MWS - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%FileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%FileName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = InData%WindType - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%RefHt_Set, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DbKiBuf(Db_Xferred) = InData%DT - Db_Xferred = Db_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NumTSteps - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%ConstantDT, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%TRange,1), UBOUND(InData%TRange,1) - ReKiBuf(Re_Xferred) = InData%TRange(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%TRange_Limited, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%YRange,1), UBOUND(InData%YRange,1) - ReKiBuf(Re_Xferred) = InData%YRange(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%YRange_Limited, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%ZRange,1), UBOUND(InData%ZRange,1) - ReKiBuf(Re_Xferred) = InData%ZRange(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%ZRange_Limited, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%BinaryFormat - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%IsBinary, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%TI,1), UBOUND(InData%TI,1) - ReKiBuf(Re_Xferred) = InData%TI(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%TI_listed, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MWS - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_PackWindFileDat - - SUBROUTINE FlowField_IO_UnPackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(WindFileDat), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackWindFileDat' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%FileName) - OutData%FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%WindType = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%RefHt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefHt_Set = TRANSFER(IntKiBuf(Int_Xferred), OutData%RefHt_Set) - Int_Xferred = Int_Xferred + 1 - OutData%DT = DbKiBuf(Db_Xferred) - Db_Xferred = Db_Xferred + 1 - OutData%NumTSteps = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%ConstantDT = TRANSFER(IntKiBuf(Int_Xferred), OutData%ConstantDT) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%TRange,1) - i1_u = UBOUND(OutData%TRange,1) - DO i1 = LBOUND(OutData%TRange,1), UBOUND(OutData%TRange,1) - OutData%TRange(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%TRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%TRange_Limited) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%YRange,1) - i1_u = UBOUND(OutData%YRange,1) - DO i1 = LBOUND(OutData%YRange,1), UBOUND(OutData%YRange,1) - OutData%YRange(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%YRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%YRange_Limited) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%ZRange,1) - i1_u = UBOUND(OutData%ZRange,1) - DO i1 = LBOUND(OutData%ZRange,1), UBOUND(OutData%ZRange,1) - OutData%ZRange(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%ZRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%ZRange_Limited) - Int_Xferred = Int_Xferred + 1 - OutData%BinaryFormat = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%IsBinary = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsBinary) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%TI,1) - i1_u = UBOUND(OutData%TI,1) - DO i1 = LBOUND(OutData%TI,1), UBOUND(OutData%TI,1) - OutData%TI(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%TI_listed = TRANSFER(IntKiBuf(Int_Xferred), OutData%TI_listed) - Int_Xferred = Int_Xferred + 1 - OutData%MWS = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE FlowField_IO_UnPackWindFileDat - - SUBROUTINE FlowField_IO_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(FlowField_IO_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(FlowField_IO_InitOutputType), INTENT(INOUT) :: DstInitOutputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_CopyInitOutput' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copywindfiledat( SrcInitOutputData%FileDat, DstInitOutputData%FileDat, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL FlowField_IO_Copybladedinitoutputtype( SrcInitOutputData%Bladed, DstInitOutputData%Bladed, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE FlowField_IO_CopyInitOutput - - SUBROUTINE FlowField_IO_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(FlowField_IO_InitOutputType), INTENT(INOUT) :: InitOutputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_DestroyInitOutput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroywindfiledat( InitOutputData%FileDat, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL FlowField_IO_Destroybladedinitoutputtype( InitOutputData%Bladed, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE FlowField_IO_DestroyInitOutput - - SUBROUTINE FlowField_IO_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(FlowField_IO_InitOutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_PackInitOutput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Ver - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Ver - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Ver - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! FileDat: size of buffers for each call to pack subtype - CALL FlowField_IO_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%FileDat, ErrStat2, ErrMsg2, .TRUE. ) ! FileDat - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! FileDat - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! FileDat - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! FileDat - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! Bladed: size of buffers for each call to pack subtype - CALL FlowField_IO_Packbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, .TRUE. ) ! Bladed - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Bladed - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Bladed - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Bladed - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL FlowField_IO_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%FileDat, ErrStat2, ErrMsg2, OnlySize ) ! FileDat - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL FlowField_IO_Packbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, InData%Bladed, ErrStat2, ErrMsg2, OnlySize ) ! Bladed - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE FlowField_IO_PackInitOutput - - SUBROUTINE FlowField_IO_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(FlowField_IO_InitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'FlowField_IO_UnPackInitOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackwindfiledat( Re_Buf, Db_Buf, Int_Buf, OutData%FileDat, ErrStat2, ErrMsg2 ) ! FileDat - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL FlowField_IO_Unpackbladedinitoutputtype( Re_Buf, Db_Buf, Int_Buf, OutData%Bladed, ErrStat2, ErrMsg2 ) ! Bladed - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE FlowField_IO_UnPackInitOutput - -END MODULE FlowField_IO_Types -!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/IfW_4Dext.f90 b/modules/inflowwind/src/IfW_4Dext.f90 deleted file mode 100644 index dea5bd8e44..0000000000 --- a/modules/inflowwind/src/IfW_4Dext.f90 +++ /dev/null @@ -1,369 +0,0 @@ -!> This module is a placeholder for any user defined wind types. The end user can use this as a template for their code. -!! @note This module does not need to exactly conform to the FAST Modularization Framework standards. Three routines are required -!! though: -!! -- IfW_4Dext_Init -- Load or create any wind data. Only called at the start of FAST. -!! -- IfW_4Dext_CalcOutput -- This will be called at each timestep with a series of data points to give wind velocities at. -!! -- IfW_4Dext_End -- clear out any stored stuff. Only called at the end of FAST. -MODULE IfW_4Dext -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2016 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** - - USE NWTC_Library - USE IfW_4Dext_Types - - IMPLICIT NONE - PRIVATE - - TYPE(ProgDesc), PARAMETER :: IfW_4Dext_Ver = ProgDesc( 'IfW_4Dext', '', '' ) - - PUBLIC :: IfW_4Dext_Init - PUBLIC :: IfW_4Dext_End - PUBLIC :: IfW_4Dext_CalcOutput - -CONTAINS - -!==================================================================================================== - -!---------------------------------------------------------------------------------------------------- -!> A subroutine to initialize the UserWind module. This routine will initialize the module. -!---------------------------------------------------------------------------------------------------- -SUBROUTINE IfW_4Dext_Init(InitInp, p, m, Interval, InitOut, ErrStat, ErrMsg) - - - IMPLICIT NONE - - ! Passed Variables - - TYPE(IfW_4Dext_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization - TYPE(IfW_4Dext_ParameterType), INTENT( OUT) :: p !< Parameters - TYPE(IfW_4Dext_MiscVarType), INTENT( OUT) :: m !< Misc variables for optimization (not copied in glue code) - TYPE(IfW_4Dext_InitOutputType), INTENT( OUT) :: InitOut !< Initial output - - REAL(DbKi), INTENT(IN ) :: Interval !< Do not change this!! - - - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< A message about the error. See NWTC_Library info for ErrID_* levels. - - ! local variables - ! Put local variables used during initializing your wind here. DO NOT USE GLOBAL VARIABLES EVER! - INTEGER(IntKi) :: UnitWind ! Use this unit number if you need to read in a file. - - ! Temporary variables for error handling - INTEGER(IntKi) :: ErrStat2 ! Temp variable for the error status - CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary error message - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_Init' - - !------------------------------------------------------------------------------------------------- - ! Set the Error handling variables - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = "" - - - !------------------------------------------------------------------------------------------------- - ! Copy things from the InitData to the ParamData. - !------------------------------------------------------------------------------------------------- - p%n = InitInp%n ! number of points on the evenly-spaced grid (in each direction) - p%delta = InitInp%delta ! distance between consecutive grid points in each direction - p%pZero = InitInp%pZero ! fixed location of first XYZ grid point (i.e., XYZ coordinates of m%V(:,1,1,1,:)) - - - !------------------------------------------------------------------------------------------------- - ! Set the MiscVars: - ! Note that these could be considered inputs, but that would mean many extra copies of potentially - ! large arrays. I am using misc vars to avoid unnecessary duplication. The external code must - ! set values for m%TgridStart and m%V. - !------------------------------------------------------------------------------------------------- - m%TgridStart = 0.0_ReKi ! (time) location of first time grid point (i.e., XYZ coordinates of m%V(:,:,:,:,1)) - should be set with m%V - - call AllocAry( m%V, 3, p%n(1), p%n(2), p%n(3), p%n(4), 'V', ErrStat2, ErrMsg2 ) !uvw at x,y,z,t coordinate - call SetErrStat(ErrStat, ErrMsg, ErrStat2, ErrMsg2, RoutineName) - if (ErrStat >= AbortErrLev) return - m%V = 0.0_SiKi - - !------------------------------------------------------------------------------------------------- - ! Set the InitOutput information. Set any outputs here. - !------------------------------------------------------------------------------------------------- - - InitOut%Ver = IfW_4Dext_Ver - - RETURN - -END SUBROUTINE IfW_4Dext_Init - -!==================================================================================================== - -!------------------------------------------------------------------------------------------------- -!> This routine and its subroutines calculate the wind velocity at a set of points given in -!! PositionXYZ. The UVW velocities are returned in OutData%Velocity -!------------------------------------------------------------------------------------------------- -SUBROUTINE IfW_4Dext_CalcOutput(Time, PositionXYZ, p, Velocity, m, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_4Dext_CalcOutput" - - - ! Passed Variables - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - REAL(ReKi), INTENT(IN ) :: PositionXYZ(:,:) !< Array of XYZ coordinates, 3xN - TYPE(IfW_4Dext_ParameterType), INTENT(IN ) :: p !< Parameters - REAL(ReKi), INTENT(INOUT) :: Velocity(:,:) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) - TYPE(IfW_4Dext_MiscVarType), INTENT(IN ) :: m !< Misc variables for optimization (not copied in glue code) - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message - - - ! local counters - INTEGER(IntKi) :: PointNum ! a loop counter for the current point - - ! local variables - INTEGER(IntKi) :: NumPoints ! Number of points passed in - - ! temporary variables - INTEGER(IntKi) :: ErrStat2 ! temporary error status - CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary error message - - - - !------------------------------------------------------------------------------------------------- - ! Initialize some things - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = "" - - - ! The array is transposed so that the number of points is the second index, x/y/z is the first. - ! This is just in case we only have a single point, the SIZE command returns the correct number of points. - NumPoints = SIZE(PositionXYZ,DIM=2) - - - ! Step through all the positions and get the velocities - DO PointNum = 1, NumPoints - - - ! Calculate the velocity for the position - Velocity(:,PointNum) = Interp4D(Time, PositionXYZ(:,PointNum), p, m, ErrStat2, ErrMsg2 ) - - - ! Error handling - IF (ErrStat2 /= ErrID_None) THEN ! adding this so we don't have to convert numbers to strings every time - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName//" [position=("// & - TRIM(Num2LStr(PositionXYZ(1,PointNum)))//", "// & - TRIM(Num2LStr(PositionXYZ(2,PointNum)))//", "// & - TRIM(Num2LStr(PositionXYZ(3,PointNum)))//") in wind-file coordinates]" ) - IF (ErrStat >= AbortErrLev) RETURN - END IF - - - ENDDO - - RETURN - -END SUBROUTINE IfW_4Dext_CalcOutput - -!==================================================================================================== -!> This routine interpolates a 4-d dataset. -!! This method is described here: http://rjwagner49.com/Mathematics/Interpolation.pdf -FUNCTION Interp4D( Time, Position, p, m, ErrStat, ErrMsg ) - - ! I/O variables - - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - REAL(ReKi), INTENT(IN ) :: Position(3) !< Array of XYZ coordinates, 3 - TYPE(IfW_4Dext_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(IfW_4Dext_MiscVarType), INTENT(IN ) :: m !< Misc variables for optimization (not copied in glue code) - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - REAL(SiKi) :: Interp4D(3) !< The interpolated UVW from m%V - - CHARACTER(*), PARAMETER :: RoutineName = 'Interp4D' - - ! Local variables - - INTEGER(IntKi) :: i ! loop counter - INTEGER(IntKi) :: ic ! wind-component counter - - INTEGER(IntKi) :: Indx_Lo(4) ! index associated with lower bound of dimension 1-4 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) - INTEGER(IntKi) :: Indx_Hi(4) ! index associated with upper bound of dimension 1-4 where val(Indx_lo(i)) <= InCoord(i) <= val(Indx_hi(i)) - - REAL(SiKi) :: isopc(4) ! isoparametric coordinates - REAL(SiKi) :: N(16) ! size 2^n - REAL(SiKi) :: u(16) ! size 2^n - REAL(ReKi) :: Tmp ! temporary fraction of distance between two grid points - - - Interp4D = 0.0_ReKi - ErrStat = ErrID_None - ErrMsg = "" - - - - !------------------------------------------------------------------------------------------------- - ! Find the bounding indices for XYZ position - !------------------------------------------------------------------------------------------------- - do i=1,3 - Tmp = (Position(i) - p%pZero(i)) / p%delta(i) - Indx_Lo(i) = INT( Tmp ) + 1 ! convert REAL to INTEGER, then add one since our grid indices start at 1, not 0 - isopc(i) = 2.0_ReKi * (Tmp - REAL(Indx_Lo(i) - 1_IntKi, ReKi)) - 1.0_ReKi ! convert to value between -1 and 1 - enddo - - !------------------------------------------------------------------------------------------------- - ! Find the bounding indices for time - !------------------------------------------------------------------------------------------------- - i=4 - Tmp = (Time - m%TgridStart) / p%delta(i) - Indx_Lo(i) = INT( Tmp ) + 1 ! convert REAL to INTEGER, then add one since our grid indices start at 1, not 0 - isopc(i) = 2.0_ReKi * (Tmp - REAL(Indx_Lo(i) - 1_IntKi, ReKi)) - 1.0_ReKi ! convert to value between -1 and 1 - IF ( ( Indx_Lo(i) == p%n(i) ) ) then - if ( abs(isopc(i) + 1.0_SiKi) < 0.001_SiKi ) THEN ! Allow for the special case where Time = TgridStart + deltat*( n_high_low - 1 ) - Indx_Lo(i) = Indx_Lo(i) - 1 - isopc(i) = 1.0_SiKi - end if - END IF - - !------------------------------------------------------------------------------------------------- - ! to verify that we don't extrapolate, make sure isopc is bound between -1 and 1 (effectively nearest neighbor) - !------------------------------------------------------------------------------------------------- - DO i=1,size(isopc) - isopc(i) = min( 1.0_SiKi, isopc(i) ) - isopc(i) = max(-1.0_SiKi, isopc(i) ) - END DO - - !------------------------------------------------------------------------------------------------- - ! also make sure we're not outside the bounds - !------------------------------------------------------------------------------------------------- - DO i=1,size(p%n) - IF (Indx_Lo(i) <= 0) THEN - Indx_Lo(i) = 1 - CALL SetErrStat(ErrID_Fatal,'Outside the grid bounds.',ErrStat,ErrMsg,RoutineName) !error out if x,y,z, or time is outside the lower bounds - RETURN - ELSEIF (Indx_Lo(i) >= p%n(i) ) THEN - Indx_Lo(i) = max( p%n(i) - 1, 1 ) ! make sure it's a valid index - CALL SetErrStat(ErrID_Fatal,'Outside the grid bounds.',ErrStat,ErrMsg,RoutineName) !error out if x,y,z, or time is outside the upper bounds - RETURN - END IF - Indx_Hi(i) = min( Indx_Lo(i) + 1, p%n(i) ) ! make sure it's a valid index - END DO - - !------------------------------------------------------------------------------------------------- - ! compute weighting factors - !------------------------------------------------------------------------------------------------- - - N( 1) = ( 1.0_SiKi - isopc(1) ) * ( 1.0_SiKi - isopc(2) ) * ( 1.0_SiKi - isopc(3) ) * ( 1.0_SiKi - isopc(4) ) - N( 2) = ( 1.0_SiKi - isopc(1) ) * ( 1.0_SiKi - isopc(2) ) * ( 1.0_SiKi - isopc(3) ) * ( 1.0_SiKi + isopc(4) ) - N( 3) = ( 1.0_SiKi - isopc(1) ) * ( 1.0_SiKi - isopc(2) ) * ( 1.0_SiKi + isopc(3) ) * ( 1.0_SiKi - isopc(4) ) - N( 4) = ( 1.0_SiKi - isopc(1) ) * ( 1.0_SiKi - isopc(2) ) * ( 1.0_SiKi + isopc(3) ) * ( 1.0_SiKi + isopc(4) ) - N( 5) = ( 1.0_SiKi - isopc(1) ) * ( 1.0_SiKi + isopc(2) ) * ( 1.0_SiKi - isopc(3) ) * ( 1.0_SiKi - isopc(4) ) - N( 6) = ( 1.0_SiKi - isopc(1) ) * ( 1.0_SiKi + isopc(2) ) * ( 1.0_SiKi - isopc(3) ) * ( 1.0_SiKi + isopc(4) ) - N( 7) = ( 1.0_SiKi - isopc(1) ) * ( 1.0_SiKi + isopc(2) ) * ( 1.0_SiKi + isopc(3) ) * ( 1.0_SiKi - isopc(4) ) - N( 8) = ( 1.0_SiKi - isopc(1) ) * ( 1.0_SiKi + isopc(2) ) * ( 1.0_SiKi + isopc(3) ) * ( 1.0_SiKi + isopc(4) ) - N( 9) = ( 1.0_SiKi + isopc(1) ) * ( 1.0_SiKi - isopc(2) ) * ( 1.0_SiKi - isopc(3) ) * ( 1.0_SiKi - isopc(4) ) - N(10) = ( 1.0_SiKi + isopc(1) ) * ( 1.0_SiKi - isopc(2) ) * ( 1.0_SiKi - isopc(3) ) * ( 1.0_SiKi + isopc(4) ) - N(11) = ( 1.0_SiKi + isopc(1) ) * ( 1.0_SiKi - isopc(2) ) * ( 1.0_SiKi + isopc(3) ) * ( 1.0_SiKi - isopc(4) ) - N(12) = ( 1.0_SiKi + isopc(1) ) * ( 1.0_SiKi - isopc(2) ) * ( 1.0_SiKi + isopc(3) ) * ( 1.0_SiKi + isopc(4) ) - N(13) = ( 1.0_SiKi + isopc(1) ) * ( 1.0_SiKi + isopc(2) ) * ( 1.0_SiKi - isopc(3) ) * ( 1.0_SiKi - isopc(4) ) - N(14) = ( 1.0_SiKi + isopc(1) ) * ( 1.0_SiKi + isopc(2) ) * ( 1.0_SiKi - isopc(3) ) * ( 1.0_SiKi + isopc(4) ) - N(15) = ( 1.0_SiKi + isopc(1) ) * ( 1.0_SiKi + isopc(2) ) * ( 1.0_SiKi + isopc(3) ) * ( 1.0_SiKi - isopc(4) ) - N(16) = ( 1.0_SiKi + isopc(1) ) * ( 1.0_SiKi + isopc(2) ) * ( 1.0_SiKi + isopc(3) ) * ( 1.0_SiKi + isopc(4) ) - N = N / REAL( SIZE(N), SiKi ) ! normalize - - !------------------------------------------------------------------------------------------------- - ! interpolate - !------------------------------------------------------------------------------------------------- - - do ic=1,3 - - u( 1) = m%V( ic, Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4) ) - u( 2) = m%V( ic, Indx_Lo(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4) ) - u( 3) = m%V( ic, Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4) ) - u( 4) = m%V( ic, Indx_Lo(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4) ) - u( 5) = m%V( ic, Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4) ) - u( 6) = m%V( ic, Indx_Lo(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4) ) - u( 7) = m%V( ic, Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4) ) - u( 8) = m%V( ic, Indx_Lo(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4) ) - u( 9) = m%V( ic, Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Lo(4) ) - u(10) = m%V( ic, Indx_Hi(1), Indx_Lo(2), Indx_Lo(3), Indx_Hi(4) ) - u(11) = m%V( ic, Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Lo(4) ) - u(12) = m%V( ic, Indx_Hi(1), Indx_Lo(2), Indx_Hi(3), Indx_Hi(4) ) - u(13) = m%V( ic, Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Lo(4) ) - u(14) = m%V( ic, Indx_Hi(1), Indx_Hi(2), Indx_Lo(3), Indx_Hi(4) ) - u(15) = m%V( ic, Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Lo(4) ) - u(16) = m%V( ic, Indx_Hi(1), Indx_Hi(2), Indx_Hi(3), Indx_Hi(4) ) - - Interp4D(ic) = SUM ( N * u ) - - end do - -END FUNCTION Interp4D - -!---------------------------------------------------------------------------------------------------- -!> This routine deallocates any memory in the FDext module. -SUBROUTINE IfW_4Dext_End( ParamData, MiscVars, ErrStat, ErrMsg) - - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_4Dext_End" - - - ! Passed Variables - TYPE(IfW_4Dext_ParameterType), INTENT(INOUT) :: ParamData !< Parameters - TYPE(IfW_4Dext_MiscVarType), INTENT(INOUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Local Variables - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - ErrMsg = '' - ErrStat = ErrID_None - - - - ! Destroy parameter data - - CALL IfW_4Dext_DestroyParam( ParamData, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - - ! Destroy the misc data - - CALL IfW_4Dext_DestroyMisc( MiscVars, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - -END SUBROUTINE IfW_4Dext_End -!==================================================================================================== -END MODULE IfW_4Dext diff --git a/modules/inflowwind/src/IfW_4Dext.txt b/modules/inflowwind/src/IfW_4Dext.txt deleted file mode 100644 index 5a4543981e..0000000000 --- a/modules/inflowwind/src/IfW_4Dext.txt +++ /dev/null @@ -1,39 +0,0 @@ -################################################################################################################################### -# Registry for IfW_UserWind, creates MODULE IfW_UserWind_Types -# Module IfW_UserWind_Types contains all of the user-defined types needed in IfW_UserWind. It also contains copy, destroy, pack, and -# unpack routines associated with each defined data types. -################################################################################################################################### -# Entries are of the form -# keyword -################################################################################################################################### - -include Registry_NWTC_Library.txt - - -######################### - -typedef IfW_4Dext/IfW_4Dext InitInputType IntKi n 4 - - "number of grid points in the x, y, z, and t directions" - -typedef ^ InitInputType ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" -typedef ^ InitInputType ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" - - -# Init Output -typedef ^ InitOutputType ProgDesc Ver - - - "Version information of this submodule" - - - -# ..... Misc/Optimization variables................................................................................................. -# Define any data that are used only for efficiency purposes (these variables are not associated with time): -# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType SiKi V ::::: - - "this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt]; it is stored as a miscVar instead of an input so that we don't have 4 copies of a very large field" - -typedef ^ MiscVarType ReKi TgridStart - - - "this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1))" s - -# ..... Parameters ................................................................................................................ -# Define parameters here: -# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType IntKi n 4 - - "number of evenly-spaced grid points in the x, y, z, and t directions" - -typedef ^ ParameterType ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" -typedef ^ ParameterType ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" - - - - diff --git a/modules/inflowwind/src/IfW_4Dext_Types.f90 b/modules/inflowwind/src/IfW_4Dext_Types.f90 deleted file mode 100644 index a764d703ad..0000000000 --- a/modules/inflowwind/src/IfW_4Dext_Types.f90 +++ /dev/null @@ -1,879 +0,0 @@ -!STARTOFREGISTRYGENERATEDFILE 'IfW_4Dext_Types.f90' -! -! WARNING This file is generated automatically by the FAST registry. -! Do not edit. Your changes to this file will be lost. -! -! FAST Registry -!********************************************************************************************************************************* -! IfW_4Dext_Types -!................................................................................................................................. -! This file is part of IfW_4Dext. -! -! Copyright (C) 2012-2016 National Renewable Energy Laboratory -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -! -! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. -! -!********************************************************************************************************************************* -!> This module contains the user-defined types needed in IfW_4Dext. It also contains copy, destroy, pack, and -!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE IfW_4Dext_Types -!--------------------------------------------------------------------------------------------------------------------------------- -USE NWTC_Library -IMPLICIT NONE -! ========= IfW_4Dext_InitInputType ======= - TYPE, PUBLIC :: IfW_4Dext_InitInputType - INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of grid points in the x, y, z, and t directions [-] - REAL(ReKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s] - REAL(ReKi) , DIMENSION(1:3) :: pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:)) [m] - END TYPE IfW_4Dext_InitInputType -! ======================= -! ========= IfW_4Dext_InitOutputType ======= - TYPE, PUBLIC :: IfW_4Dext_InitOutputType - TYPE(ProgDesc) :: Ver !< Version information of this submodule [-] - END TYPE IfW_4Dext_InitOutputType -! ======================= -! ========= IfW_4Dext_MiscVarType ======= - TYPE, PUBLIC :: IfW_4Dext_MiscVarType - REAL(SiKi) , DIMENSION(:,:,:,:,:), ALLOCATABLE :: V !< this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt]; it is stored as a miscVar instead of an input so that we don't have 4 copies of a very large field [-] - REAL(ReKi) :: TgridStart !< this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1)) [s] - END TYPE IfW_4Dext_MiscVarType -! ======================= -! ========= IfW_4Dext_ParameterType ======= - TYPE, PUBLIC :: IfW_4Dext_ParameterType - INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of evenly-spaced grid points in the x, y, z, and t directions [-] - REAL(ReKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s] - REAL(ReKi) , DIMENSION(1:3) :: pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:)) [m] - END TYPE IfW_4Dext_ParameterType -! ======================= -CONTAINS - SUBROUTINE IfW_4Dext_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_4Dext_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(IfW_4Dext_InitInputType), INTENT(INOUT) :: DstInitInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_CopyInitInput' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitInputData%n = SrcInitInputData%n - DstInitInputData%delta = SrcInitInputData%delta - DstInitInputData%pZero = SrcInitInputData%pZero - END SUBROUTINE IfW_4Dext_CopyInitInput - - SUBROUTINE IfW_4Dext_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_4Dext_InitInputType), INTENT(INOUT) :: InitInputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_DestroyInitInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_4Dext_DestroyInitInput - - SUBROUTINE IfW_4Dext_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_4Dext_InitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_PackInitInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + SIZE(InData%n) ! n - Re_BufSz = Re_BufSz + SIZE(InData%delta) ! delta - Re_BufSz = Re_BufSz + SIZE(InData%pZero) ! pZero - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO i1 = LBOUND(InData%n,1), UBOUND(InData%n,1) - IntKiBuf(Int_Xferred) = InData%n(i1) - Int_Xferred = Int_Xferred + 1 - END DO - DO i1 = LBOUND(InData%delta,1), UBOUND(InData%delta,1) - ReKiBuf(Re_Xferred) = InData%delta(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%pZero,1), UBOUND(InData%pZero,1) - ReKiBuf(Re_Xferred) = InData%pZero(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END SUBROUTINE IfW_4Dext_PackInitInput - - SUBROUTINE IfW_4Dext_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_4Dext_InitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_UnPackInitInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - i1_l = LBOUND(OutData%n,1) - i1_u = UBOUND(OutData%n,1) - DO i1 = LBOUND(OutData%n,1), UBOUND(OutData%n,1) - OutData%n(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - i1_l = LBOUND(OutData%delta,1) - i1_u = UBOUND(OutData%delta,1) - DO i1 = LBOUND(OutData%delta,1), UBOUND(OutData%delta,1) - OutData%delta(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%pZero,1) - i1_u = UBOUND(OutData%pZero,1) - DO i1 = LBOUND(OutData%pZero,1), UBOUND(OutData%pZero,1) - OutData%pZero(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END SUBROUTINE IfW_4Dext_UnPackInitInput - - SUBROUTINE IfW_4Dext_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_4Dext_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(IfW_4Dext_InitOutputType), INTENT(INOUT) :: DstInitOutputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_CopyInitOutput' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_4Dext_CopyInitOutput - - SUBROUTINE IfW_4Dext_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_4Dext_InitOutputType), INTENT(INOUT) :: InitOutputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_DestroyInitOutput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_4Dext_DestroyInitOutput - - SUBROUTINE IfW_4Dext_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_4Dext_InitOutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_PackInitOutput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Ver - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Ver - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Ver - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE IfW_4Dext_PackInitOutput - - SUBROUTINE IfW_4Dext_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_4Dext_InitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_UnPackInitOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_4Dext_UnPackInitOutput - - SUBROUTINE IfW_4Dext_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_4Dext_MiscVarType), INTENT(IN) :: SrcMiscData - TYPE(IfW_4Dext_MiscVarType), INTENT(INOUT) :: DstMiscData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_CopyMisc' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcMiscData%V)) THEN - i1_l = LBOUND(SrcMiscData%V,1) - i1_u = UBOUND(SrcMiscData%V,1) - i2_l = LBOUND(SrcMiscData%V,2) - i2_u = UBOUND(SrcMiscData%V,2) - i3_l = LBOUND(SrcMiscData%V,3) - i3_u = UBOUND(SrcMiscData%V,3) - i4_l = LBOUND(SrcMiscData%V,4) - i4_u = UBOUND(SrcMiscData%V,4) - i5_l = LBOUND(SrcMiscData%V,5) - i5_u = UBOUND(SrcMiscData%V,5) - IF (.NOT. ALLOCATED(DstMiscData%V)) THEN - ALLOCATE(DstMiscData%V(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u,i5_l:i5_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%V.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstMiscData%V = SrcMiscData%V -ENDIF - DstMiscData%TgridStart = SrcMiscData%TgridStart - END SUBROUTINE IfW_4Dext_CopyMisc - - SUBROUTINE IfW_4Dext_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_4Dext_MiscVarType), INTENT(INOUT) :: MiscData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_DestroyMisc' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - -IF (ALLOCATED(MiscData%V)) THEN - DEALLOCATE(MiscData%V) -ENDIF - END SUBROUTINE IfW_4Dext_DestroyMisc - - SUBROUTINE IfW_4Dext_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_4Dext_MiscVarType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_PackMisc' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! V allocated yes/no - IF ( ALLOCATED(InData%V) ) THEN - Int_BufSz = Int_BufSz + 2*5 ! V upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%V) ! V - END IF - Re_BufSz = Re_BufSz + 1 ! TgridStart - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%V) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%V,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%V,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%V,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%V,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%V,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%V,3) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%V,4) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%V,4) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%V,5) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%V,5) - Int_Xferred = Int_Xferred + 2 - - DO i5 = LBOUND(InData%V,5), UBOUND(InData%V,5) - DO i4 = LBOUND(InData%V,4), UBOUND(InData%V,4) - DO i3 = LBOUND(InData%V,3), UBOUND(InData%V,3) - DO i2 = LBOUND(InData%V,2), UBOUND(InData%V,2) - DO i1 = LBOUND(InData%V,1), UBOUND(InData%V,1) - ReKiBuf(Re_Xferred) = InData%V(i1,i2,i3,i4,i5) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END DO - END DO - END IF - ReKiBuf(Re_Xferred) = InData%TgridStart - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_4Dext_PackMisc - - SUBROUTINE IfW_4Dext_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_4Dext_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: i5, i5_l, i5_u ! bounds (upper/lower) for an array dimension 5 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! V not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i4_l = IntKiBuf( Int_Xferred ) - i4_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i5_l = IntKiBuf( Int_Xferred ) - i5_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%V)) DEALLOCATE(OutData%V) - ALLOCATE(OutData%V(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u,i5_l:i5_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%V.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i5 = LBOUND(OutData%V,5), UBOUND(OutData%V,5) - DO i4 = LBOUND(OutData%V,4), UBOUND(OutData%V,4) - DO i3 = LBOUND(OutData%V,3), UBOUND(OutData%V,3) - DO i2 = LBOUND(OutData%V,2), UBOUND(OutData%V,2) - DO i1 = LBOUND(OutData%V,1), UBOUND(OutData%V,1) - OutData%V(i1,i2,i3,i4,i5) = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END DO - END DO - END IF - OutData%TgridStart = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_4Dext_UnPackMisc - - SUBROUTINE IfW_4Dext_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_4Dext_ParameterType), INTENT(IN) :: SrcParamData - TYPE(IfW_4Dext_ParameterType), INTENT(INOUT) :: DstParamData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_CopyParam' -! - ErrStat = ErrID_None - ErrMsg = "" - DstParamData%n = SrcParamData%n - DstParamData%delta = SrcParamData%delta - DstParamData%pZero = SrcParamData%pZero - END SUBROUTINE IfW_4Dext_CopyParam - - SUBROUTINE IfW_4Dext_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_4Dext_ParameterType), INTENT(INOUT) :: ParamData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_DestroyParam' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_4Dext_DestroyParam - - SUBROUTINE IfW_4Dext_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_4Dext_ParameterType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_PackParam' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + SIZE(InData%n) ! n - Re_BufSz = Re_BufSz + SIZE(InData%delta) ! delta - Re_BufSz = Re_BufSz + SIZE(InData%pZero) ! pZero - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO i1 = LBOUND(InData%n,1), UBOUND(InData%n,1) - IntKiBuf(Int_Xferred) = InData%n(i1) - Int_Xferred = Int_Xferred + 1 - END DO - DO i1 = LBOUND(InData%delta,1), UBOUND(InData%delta,1) - ReKiBuf(Re_Xferred) = InData%delta(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%pZero,1), UBOUND(InData%pZero,1) - ReKiBuf(Re_Xferred) = InData%pZero(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END SUBROUTINE IfW_4Dext_PackParam - - SUBROUTINE IfW_4Dext_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_4Dext_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_4Dext_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - i1_l = LBOUND(OutData%n,1) - i1_u = UBOUND(OutData%n,1) - DO i1 = LBOUND(OutData%n,1), UBOUND(OutData%n,1) - OutData%n(i1) = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END DO - i1_l = LBOUND(OutData%delta,1) - i1_u = UBOUND(OutData%delta,1) - DO i1 = LBOUND(OutData%delta,1), UBOUND(OutData%delta,1) - OutData%delta(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%pZero,1) - i1_u = UBOUND(OutData%pZero,1) - DO i1 = LBOUND(OutData%pZero,1), UBOUND(OutData%pZero,1) - OutData%pZero(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END SUBROUTINE IfW_4Dext_UnPackParam - -END MODULE IfW_4Dext_Types -!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/IfW_BladedFFWind.f90 b/modules/inflowwind/src/IfW_BladedFFWind.f90 deleted file mode 100644 index c2e54892a4..0000000000 --- a/modules/inflowwind/src/IfW_BladedFFWind.f90 +++ /dev/null @@ -1,1925 +0,0 @@ -!> This module uses full-field binary wind files to determine the wind inflow. -!! This module assumes that the origin, (0,0,0), is located at the tower centerline at ground level, -!! and that all units are specified in the metric system (using meters and seconds). -!! Data is shifted by half the grid width to account for turbine yaw (so that data in the X -!! direction actually starts at -1*ParamData%FFYHWid meters). -MODULE IfW_BladedFFWind -!! -!! Created 25-Sep-2009 by B. Jonkman, National Renewable Energy Laboratory -!! using subroutines and modules from AeroDyn v12.58 -!! -!!---------------------------------------------------------------------------------------------------- -!! Feb 2013 v2.00.00 A. Platt -!! -- updated to the new framework -!! -- Modified to use NWTC_Library v. 2.0 -!! -- Note: Jacobians are not included in this version. -!! -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2015-2016 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** - - USE NWTC_Library - USE IfW_BladedFFWind_Types - USE IfW_FFWind_Base - - IMPLICIT NONE - PRIVATE - - TYPE(ProgDesc), PARAMETER :: IfW_BladedFFWind_Ver = ProgDesc( 'IfW_BladedFFWind', '', '' ) - - PUBLIC :: IfW_BladedFFWind_Init - PUBLIC :: IfW_BladedFFWind_End - PUBLIC :: IfW_BladedFFWind_CalcOutput - - - - -CONTAINS -!==================================================================================================== -!> This routine is used read the full-field turbulence data. -!! 09/25/1997 - Created by M. Buhl from GETFILES in ViewWind. -!! 09/23/2009 - modified by B. Jonkman: this subroutine was split into several subroutines (was ReadFF) -!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -SUBROUTINE IfW_BladedFFWind_Init(InitInp, ParamData, MiscVars, InitOutData, ErrStat, ErrMsg) - - CHARACTER(*), PARAMETER :: RoutineName="IfW_BladedFFWind_Init" - - ! Passed Variables - TYPE(IfW_BladedFFWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization data passed to the module - TYPE(IfW_BladedFFWind_ParameterType), INTENT( OUT) :: ParamData !< Parameters - TYPE(IfW_BladedFFWind_MiscVarType), INTENT( OUT) :: MiscVars !< misc/optimization data (storage for the main data) - TYPE(IfW_BladedFFWind_InitOutputType), INTENT( OUT) :: InitOutData !< Initial output - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Temporary variables for error handling - REAL(ReKi) :: TI(3) - REAL(ReKi) :: ScaleFactors(3) - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - TYPE(IfW_FFWind_InitInputType) :: FF_InitInp ! Initialization input data for FF scaling - - - - ErrMsg = '' - ErrStat = ErrID_None - - - CALL ReadFiles(InitInp, FF_InitInp, InitOutData, ParamData, TI, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - !------------------------------------------------------------------------------------------------- - ! If the wind file has zero-mean and unit standard deviation (native Bladed format), scale the data: - !------------------------------------------------------------------------------------------------- - ParamData%FF%AddMeanAfterInterp = .false. - ParamData%FF%Z0 = FF_InitInp%Z0 - ParamData%FF%PLExp = FF_InitInp%PLExp - ParamData%FF%VLinShr = FF_InitInp%VLinShr - ParamData%FF%HLinShr = FF_InitInp%HLinShr - ParamData%FF%RefLength = FF_InitInp%RefLength - - if (InitInp%NativeBladedFmt) then - ParamData%FF%InterpTower = .true. - ParamData%FF%AddMeanAfterInterp = .true. - ParamData%FF%WindProfileType = FF_InitInp%WindProfileType - - - ! Validate scaling data if we've got native-Bladed format - CALL FFWind_ValidateInput(FF_InitInp, ParamData%FF%NFFComp, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - ! scale to requested TI (or use requested scale factors) - call ScaleTurbulence(FF_InitInp, ParamData%FF%FFData(:,:,:,1:ParamData%FF%NFFSteps), ScaleFactors, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - ! Add the mean wind speed to the u component. - if (.not. ParamData%FF%AddMeanAfterInterp) call AddMeanVelocity(FF_InitInp, ParamData%FF%GridBase, 1.0_ReKi/ParamData%FF%InvFFZD, 1.0_ReKi/ParamData%FF%InvFFYD, ParamData%FF%FFData) - else - ParamData%FF%InterpTower = .false. - ParamData%FF%WindProfileType = WindProfileType_None - end if - - - IF (ParamData%FF%Periodic) THEN - ParamData%FF%InitXPosition = 0 ! start at the hub - ParamData%FF%TotalTime = ParamData%FF%NFFSteps*ParamData%FF%FFDTime - ELSE - ParamData%FF%InitXPosition = ParamData%FF%FFYHWid ! start half the grid width ahead of the turbine - ParamData%FF%TotalTime = (ParamData%FF%NFFSteps-1)*ParamData%FF%FFDTime - ENDIF - - ! overwrite the offset - IF (InitInp%NativeBladedFmt) THEN - ParamData%FF%InitXPosition = FF_InitInp%XOffset - END IF - - - !------------------------------------------------------------------------------------------------- - ! Set the InitOutput information - !------------------------------------------------------------------------------------------------- - - InitOutdata%Ver = IfW_BladedFFWind_Ver - InitOutdata%TI = TI - - - - !------------------------------------------------------------------------------------------------- - ! Write to the summary file - !------------------------------------------------------------------------------------------------- - - IF ( InitInp%SumFileUnit > 0 ) THEN - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) 'Bladed-style wind type. Read by InflowWind sub-module '// & - TRIM(IfW_BladedFFWind_Ver%Name)//' '//TRIM(IfW_BladedFFWind_Ver%Ver) - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) TRIM(TmpErrMsg) - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' FileName: '//TRIM(InitInp%WindFileName) - WRITE(InitInp%SumFileUnit,'(A34,I3)', IOSTAT=TmpErrStat) ' Binary file format id: ',ParamData%FF%WindFileFormat - WRITE(InitInp%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Reference height (m): ',ParamData%FF%RefHt - WRITE(InitInp%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Timestep (s): ',ParamData%FF%FFDTime - WRITE(InitInp%SumFileUnit,'(A34,I12)', IOSTAT=TmpErrStat) ' Number of timesteps: ',ParamData%FF%NFFSteps - WRITE(InitInp%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Mean windspeed (m/s): ',ParamData%FF%MeanFFWS - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Characteristic TI: [ '// & - TRIM(Num2LStr(TI(1)))//', '//TRIM(Num2LStr(TI(2)))//', '//TRIM(Num2LStr(TI(3)))//' ] ' - WRITE(InitInp%SumFileUnit,'(A34,L1)', IOSTAT=TmpErrStat) ' Windfile is periodic: ',ParamData%FF%Periodic - WRITE(InitInp%SumFileUnit,'(A34,L1)', IOSTAT=TmpErrStat) ' Windfile includes tower: ',ParamData%FF%NTGrids > 0 - - IF ( ParamData%FF%Periodic ) THEN - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Time range (s): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(ParamData%FF%TotalTime))//' ]' - ELSE ! Shift the time range to compensate for the shifting of the wind grid - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Time range (s): [ '// & - TRIM(Num2LStr(-ParamData%FF%InitXPosition*ParamData%FF%InvMFFWS))//' : '// & - TRIM(Num2LStr(ParamData%FF%TotalTime-ParamData%FF%InitXPosition*ParamData%FF%InvMFFWS))//' ]' - ENDIF - - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Y range (m): [ '// & - TRIM(Num2LStr(-ParamData%FF%FFYHWid))//' : '//TRIM(Num2LStr(ParamData%FF%FFYHWid))//' ]' - - IF ( ParamData%FF%NTGrids > 0 ) THEN - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Z range (m): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(ParamData%FF%RefHt + ParamData%FF%FFZHWid))//' ]' - ELSE - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Z range (m): [ '// & - TRIM(Num2LStr(ParamData%FF%RefHt - ParamData%FF%FFZHWid))//' : '//TRIM(Num2LStr(ParamData%FF%RefHt + ParamData%FF%FFZHWid))//' ]' - ENDIF - - - ! We are assuming that if the last line was written ok, then all of them were. - IF (TmpErrStat /= 0_IntKi) THEN - CALL SetErrStat(ErrID_Fatal,'Error writing to summary file.',ErrStat,ErrMsg,RoutineName) - RETURN - ENDIF - ENDIF - - - - - RETURN - -END SUBROUTINE IfW_BladedFFWind_Init -!======================================================================================================== -SUBROUTINE ReadFiles(InitInp, FF_InitInp, InitOut, ParamData, TI, ErrStat, ErrMsg) - - CHARACTER(*), PARAMETER :: RoutineName="ReadFiles" - - ! Passed Variables - TYPE(IfW_BladedFFWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization data passed to the module - TYPE(IfW_FFWind_InitInputType), INTENT( OUT) :: FF_InitInp !< Initialization data for scaling - TYPE(IfW_BladedFFWind_InitOutputType), INTENT(INOUT) :: InitOut !< Initial output - TYPE(IfW_BladedFFWind_ParameterType), INTENT( OUT) :: ParamData !< Parameters - REAL(ReKi) , INTENT( OUT) :: TI (3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - ! Local Variables: - - REAL(ReKi) :: BinTI (3) ! turbulence intensities of the wind components as defined in the FF binary file, not necessarially the actual TI - REAL(ReKi) :: NatTI (3) ! turbulence intensities of the wind components as defined in the native FF summary file - REAL(ReKi) :: UBar - REAL(ReKi) :: ZCenter - - INTEGER(IntKi) :: UnitWind ! Unit number for the InflowWind input file - INTEGER(B2Ki) :: Dum_Int2 - INTEGER(IntKi) :: I - LOGICAL :: CWise - LOGICAL :: LHR ! Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) - - LOGICAL :: Exists - CHARACTER( 1028 ) :: SumFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. - CHARACTER( 1028 ) :: TwrFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. - - CHARACTER(1024) :: BinFileName - CHARACTER(1024) :: PriPath - - - ErrMsg = '' - ErrStat = ErrID_None - - - if (InitInp%NativeBladedFmt) then - call Read_NativeBladedSummary(InitInp%WindFileName, FF_InitInp%PLExp, FF_InitInp%VLinShr, FF_InitInp%HLinShr, FF_InitInp%RefLength, & - NatTI, ParamData%FF%MeanFFWS, ParamData%FF%RefHt, InitOut%PropagationDir, InitOut%VFlowAngle, & - BinFileName, FF_InitInp%XOffset, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - - if (pathIsRelative(BinFileName)) then - CALL GetPath( InitInp%WindFileName, PriPath ) ! Binary file will be relative to the path where the primary input file is located. - BinFileName = TRIM(PriPath)//TRIM(BinFileName) - end if - - IF ( InitInp%FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data - IF ( InitInp%TurbineID == 0 ) THEN ! .TRUE. for the FAST.Farm low-resolution domain - BinFileName = TRIM(BinFileName)//TRIM(PathSep)//'Low' - ELSE ! FAST.Farm high-resolution domain(s) - BinFileName = TRIM(BinFileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) - ENDIF - ENDIF - - ! default values for Bladed Format - CWise = .false. - ZCenter = ParamData%FF%RefHt - ParamData%FF%Periodic = .true. - - FF_InitInp%ScaleMethod = ScaleMethod_StdDev - FF_InitInp%SigmaF = NatTI * ParamData%FF%MeanFFWS - FF_InitInp%sf = FF_InitInp%SigmaF -! FF_InitInp%ScaleMethod = ScaleMethod_Direct ! Bladed files should have std of 1, so we'll just multiply (closer to what Bladed does) - - FF_InitInp%RefHt = ParamData%FF%RefHt - FF_InitInp%URef = ParamData%FF%MeanFFWS - FF_InitInp%WindProfileType = WindProfileType_PL ! it could also have logarithmic, but I'm going to leave that off for now - - TI = 100.0_ReKi - UBar = 0.0_ReKi - LHR = .true. - - else - InitOut%PropagationDir = 0.0_ReKi - InitOut%VFlowAngle = 0.0_ReKi - FF_InitInp%VLinShr = 0.0_ReKi - FF_InitInp%HLinShr = 0.0_ReKi - FF_InitInp%RefLength = 1.0_ReKi - - BinFileName = InitInp%WindFileName - end if - - - ! Get a unit number to use - - CALL GetNewUnit(UnitWind, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - - !---------------------------------------------------------------------------------------------- - ! 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 SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - ! Read the first binary integer from the file to get info on the type. - ! Cannot use library read routines since this is a 2-byte integer. - READ ( UnitWind, IOSTAT=TmpErrStat ) Dum_Int2 - CLOSE( UnitWind ) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat(ErrID_Fatal,' Error reading first binary integer from file "'//TRIM(BinFileName)//'."', & - ErrStat,ErrMsg,RoutineName) - RETURN - ENDIF - - - !---------------------------------------------------------------------------------------------- - ! Read the files to get the required FF data. - !---------------------------------------------------------------------------------------------- - - ! Store the binary format information so the InflowWind code can use it. - ! Also changes to IntKi from INT(2) to compare in the SELECT below - ParamData%FF%WindFileFormat = Dum_Int2 - - - SELECT CASE (ParamData%FF%WindFileFormat) - - CASE ( -1, -2, -3, -99 ) ! Bladed-style binary format - - IF (.not. InitInp%NativeBladedFmt) THEN - - !........................................................................................... - ! Create full-field summary file name from binary file root name. Also get tower file - ! name. - !........................................................................................... - - CALL GetRoot(BinFileName, SumFile) - - TwrFile = TRIM(SumFile)//'.twr' - SumFile = TRIM(SumFile)//'.sum' - - - !........................................................................................... - ! Read the summary file to get necessary scaling information - !........................................................................................... - - CALL Read_Summary_FF (UnitWind, TRIM(SumFile), CWise, ZCenter, TI, UBar, ParamData%FF%RefHt, ParamData%FF%Periodic, LHR, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CLOSE ( UnitWind ) - RETURN - END IF - - END IF - - - !........................................................................................... - ! Open the binary file and read its header - !........................................................................................... - - CALL OpenBInpFile (UnitWind, TRIM(BinFileName), TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CLOSE ( UnitWind ) - RETURN - END IF - - IF ( Dum_Int2 == -99 ) THEN ! Newer-style BLADED format - CALL Read_Bladed_FF_Header1 (UnitWind, BinTI, ParamData%FF, InitInp%NativeBladedFmt, TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CLOSE ( UnitWind ) - RETURN - END IF - - ! If the TIs are also in the binary file (BinTI > 0), - ! use those numbers instead of ones from the summary file - - if (.not. InitInp%NativeBladedFmt) then - DO I =1,ParamData%FF%NFFComp - IF ( BinTI(I) > 0 ) TI(I) = BinTI(I) - ENDDO - end if - - - ELSE - CALL Read_Bladed_FF_Header0 (UnitWind, ParamData%FF, InitInp%NativeBladedFmt, TmpErrStat, TmpErrMsg) ! Older-style BLADED format - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CLOSE ( UnitWind ) - RETURN - END IF - - ENDIF - - - - !........................................................................................... - ! Let's see if the summary and binary FF wind files go together before continuing. - !........................................................................................... - - IF (.not. InitInp%NativeBladedFmt) THEN - IF ( ABS( UBar - ParamData%FF%MeanFFWS ) > 0.1 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error: Incompatible mean hub-height wind speeds in FF wind files. '//& - '(Check that the .sum and .wnd files were generated together.)', ErrStat, ErrMsg, RoutineName ) - CLOSE ( UnitWind ) - RETURN - ENDIF - - END IF - - !........................................................................................... - ! Calculate the height of the bottom of the grid - !........................................................................................... - - ParamData%FF%GridBase = ZCenter - ParamData%FF%FFZHWid ! the location, in meters, of the bottom of the grid - IF ( ParamData%FF%GridBase < 0.0_ReKi ) THEN - call SetErrStat( ErrID_Severe, 'WARNING: The bottom of the grid is located at a height of '//& - TRIM( Num2LStr(ParamData%FF%GridBase) )//' meters, which is below the ground.'//& - ' Winds below the ground will be set to 0.', ErrStat,ErrMsg, RoutineName) - END IF - - !........................................................................................... - ! Read the binary grids (converted to m/s) and close the file - !........................................................................................... - - CALL Read_Bladed_Grids( UnitWind, InitInp%NativeBladedFmt, CWise, LHR, TI, ParamData%FF, TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - CLOSE ( UnitWind ) - if (InitInp%NativeBladedFmt) TI = NatTI*100.0_ReKi ! report these TI for the native Bladed format in percent - - IF ( ErrStat >= AbortErrLev ) RETURN - - !........................................................................................... - ! Read the tower points file - !........................................................................................... - - IF ( InitInp%TowerFileExist .AND. .NOT. InitInp%NativeBladedFmt) THEN ! If we specified a tower file - INQUIRE ( FILE=TRIM(TwrFile) , EXIST=Exists ) - - ! Double check that the tower file exists and read it. If it was requested but doesn't exist, - ! throw fatal error and exit. - IF ( Exists ) THEN - CALL Read_FF_Tower( UnitWind, ParamData%FF, TwrFile, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CLOSE ( UnitWind ) - RETURN - END IF - ELSE - CALL SetErrStat( ErrID_Fatal, ' Tower file '//TRIM(TwrFile)//' specified for Bladed full-field '// & - 'wind files does not exist.', ErrStat, ErrMsg, RoutineName) - CLOSE ( UnitWind ) - RETURN - ENDIF - ELSE - ParamData%FF%NTGrids = 0_IntKi - ENDIF - - - CASE DEFAULT - CALL SetErrStat( ErrID_Fatal, ' This is not a bladed-style binary wind file (binary format identifier: '// & - TRIM(Num2LStr(ParamData%FF%WindFileFormat))//'. This might be a TurbSim binary wind file.', & - ErrStat, ErrMsg, RoutineName ) - RETURN - - END SELECT - -END SUBROUTINE ReadFiles - - !==================================================================================================== - !> This subroutine reads the text summary file to get normalizing parameters, the location of the - !! grid, and the direction the grid was written to the binary file - !! - !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 - SUBROUTINE Read_Summary_FF ( UnitWind, FileName, CWise, ZCenter, TI, UBar, RefHt, Periodic, LHR, ErrStat, ErrMsg ) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="Read_Summary_FF" - - - ! Passed variables - INTEGER(IntKi), INTENT(IN ) :: UnitWind !< unit number for the file to open - CHARACTER(*), INTENT(IN ) :: FileName !< name of the summary file - LOGICAL, INTENT( OUT) :: CWise !< rotation (for reading the order of the binary data) - REAL(ReKi), INTENT( OUT) :: ZCenter !< the height at the center of the grid - REAL(ReKi), INTENT( OUT) :: TI (3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI - REAL(ReKi), INTENT( OUT) :: UBar !< mean (advection) wind speed - REAL(ReKi), INTENT( OUT) :: RefHt !< Reference height - LOGICAL, INTENT( OUT) :: Periodic !< rotation (for reading the order of the binary data) - LOGICAL, INTENT( OUT) :: LHR !< Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< returns 0 if no error encountered in the subroutine - CHARACTER(*), INTENT( OUT) :: ErrMsg !< holds the error messages - - ! Local variables - REAL(ReKi) :: ZGOffset ! The vertical offset of the turbine on rectangular grid (allows turbulence not centered on turbine hub) - - INTEGER, PARAMETER :: NumStrings = 7 ! number of strings to be looking for in the file - - INTEGER(IntKi) :: FirstIndx ! The first character of a line where data is located - INTEGER(IntKi) :: I ! A loop counter - INTEGER(IntKi) :: LastIndx ! The last character of a line where data is located - INTEGER(IntKi) :: LineCount ! Number of lines that have been read in the file - - LOGICAL :: StrNeeded(NumStrings) ! if the string has been found - - CHARACTER(1024) :: LINE ! temporary storage for reading a line from the file - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - !---------------------------------------------------------------------------------------------- - ! Initialize some variables - !---------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = '' - - LineCount = 0 - StrNeeded(:) = .TRUE. - ZGOffset = 0.0 - RefHt = 0.0 - Periodic = .FALSE. - LHR = .FALSE. - CWise = .FALSE. ! default value, in case it is not in this file - - !---------------------------------------------------------------------------------------------- - ! Open summary file. - !---------------------------------------------------------------------------------------------- - - CALL OpenFInpFile ( UnitWind, TRIM( FileName ), TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - !---------------------------------------------------------------------------------------------- - ! Read the summary file. - !---------------------------------------------------------------------------------------------- - - ! Here are the strings we're looking for, in this order: - ! 1) 'CLOCKWISE' (optional) - ! 2) 'HUB HEIGHT' - ! 3) (unused; decided we didn't need to read data also stored in the binary file) - ! 4) 'UBAR' - ! 5) 'HEIGHT OFFSET' (optional) - ! 6) 'PERIODIC' (optional) - ! 7) 'BLADED LEFT-HAND RULE' (optional) - - - DO WHILE ( ( ErrStat == ErrID_None ) .AND. StrNeeded(NumStrings) ) - - LineCount = LineCount + 1 - - READ ( UnitWind, '(A)', IOSTAT=TmpErrStat ) LINE - IF ( TmpErrStat /= 0 ) THEN - - ! the "HEIGHT OFFSET", "PERIODIC", and "BLADED LEFT-HAND RULE" parameters are not necessary. We'll assume they are zero/false if we didn't find it. - ! We will also assume "CLOCKWISE" is false if we didn't find it. - IF ( StrNeeded(2) .OR. StrNeeded(4) ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading line #'//TRIM(Num2LStr(LineCount))//' of the summary file, "'// & - TRIM(FileName)//'". Could not find all of the required parameters.', ErrStat, ErrMsg, RoutineName ) - RETURN - ELSE - EXIT - ENDIF - - ENDIF - - CALL Conv2UC ( LINE ) - - - IF ( StrNeeded(2) ) THEN ! if "CLOCKWISE" (StrNeeded(1)) is in the file, we would have already read it. If not, it's not in this file. - - IF ( StrNeeded(1) ) THEN - - !------------------------------------------------------------------------------------------- - ! #1: Get the rotation direction, using the string "CLOCKWISE" - !------------------------------------------------------------------------------------------- - - IF ( INDEX( LINE, 'CLOCKWISE' ) > 0 ) THEN - - READ (LINE, *, IOSTAT = TmpErrStat) CWise ! Look for True/False values - - IF ( TmpErrStat /= 0 ) THEN ! Look for Yes/No values instead - - LINE = ADJUSTL ( LINE ) ! Remove leading spaces from input line - - SELECT CASE (LINE(1:1) ) - CASE ('Y') - CWise = .TRUE. - CASE ('N') - CWise = .FALSE. - CASE DEFAULT - CALL SetErrStat( ErrID_Fatal, ' Error reading rotation direction (CLOCKWISE) from FF summary file.', ErrStat, ErrMsg, RoutineName ) - RETURN - END SELECT - CYCLE - - ENDIF ! TmpErrStat /= 0 - StrNeeded(1) = .FALSE. - - ENDIF ! INDEX for "CLOCKWISE" - - END IF - - !------------------------------------------------------------------------------------------- - ! #2: Get the hub height, using the strings "HUB HEIGHT" or "ZHUB" - !------------------------------------------------------------------------------------------- - - IF ( INDEX( LINE, 'HUB HEIGHT' ) > 0 .OR. INDEX( LINE, 'ZHUB' ) > 0 ) THEN - - READ (LINE, *, IOSTAT = TmpErrStat) RefHt - - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading hub height from FF summary file.', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - StrNeeded(2) = .FALSE. - - ENDIF !INDEX for "HUB HEIGHT" or "ZHUB" - - ! ELSEIF ( StrNeeded(3) ) THEN - ! - ! !------------------------------------------------------------------------------------------- - ! ! #3: Get the grid width (& height, if available), using the strings "GRID WIDTH" or "RDIAM" - ! ! If GRID HEIGHT is specified, use it, too. -- THIS IS UNNECESSARY AS IT'S STORED IN THE BINARY FILE - ! !------------------------------------------------------------------------------------------- - - ELSEIF ( StrNeeded(4) ) THEN - - !------------------------------------------------------------------------------------------- - ! #4: Get the mean wind speed "UBAR" and turbulence intensities from following lines for - ! scaling Bladed-style FF binary files - !------------------------------------------------------------------------------------------- - - IF ( INDEX( LINE, 'UBAR') > 0 ) THEN - - FirstIndx = INDEX( LINE, '=' ) + 1 ! Look for the equal siqn to find the number we're looking for - - READ ( LINE( FirstIndx:LEN(LINE) ), *, IOSTAT=TmpErrStat ) UBar - - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading UBar binary data normalizing parameter from FF summary file.', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - DO I = 1,3 - - LineCount = LineCount + 1 - - READ ( UnitWind, '(A)', IOSTAT=TmpErrStat ) LINE - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading line #'//TRIM(Num2LStr(LineCount))//' of the summary file, "'//TRIM(FileName)//& - '". Could not find all of the required parameters.', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - FirstIndx = INDEX( LINE, '=' ) + 1 ! Read the number between the = and % signs - LastIndx = INDEX( LINE, '%' ) - 1 - - IF ( LastIndx <= FirstIndx ) LastIndx = LEN( LINE ) ! If there's no % sign, read to the end of the line - - READ ( LINE( FirstIndx:LastIndx ), *, IOSTAT=TmpErrStat ) TI(I) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading TI('//TRIM(Num2LStr(I))// & - ') binary data normalizing parameter from FF summary file.', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - ENDDO !I - - StrNeeded(4) = .FALSE. - - ENDIF - - ELSEIF ( StrNeeded(5) ) THEN - - !------------------------------------------------------------------------------------------- - ! #5: Get the grid "HEIGHT OFFSET", if it exists (in TurbSim). Otherwise, assume it's zero - ! ZGOffset = HH - GridBase - ParamData%FF%FFZHWid - !------------------------------------------------------------------------------------------- - IF ( INDEX( LINE, 'HEIGHT OFFSET' ) > 0 ) THEN - - FirstIndx = INDEX ( LINE, '=' ) + 1 - - READ ( LINE( FirstIndx:LEN(LINE) ), *, IOSTAT=TmpErrStat ) ZGOffset - - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading height offset from FF summary file.', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - StrNeeded(5) = .FALSE. - - ENDIF !INDEX for "HEIGHT OFFSET" - - ELSE - - IF ( StrNeeded(6) ) THEN - - !------------------------------------------------------------------------------------------- - ! #6: Get the grid "PERIODIC", if it exists (in TurbSim). Otherwise, assume it's - ! not a periodic file (would only show up if the HEIGHT OFFSET is in the file) - !------------------------------------------------------------------------------------------- - IF ( INDEX( LINE, 'PERIODIC' ) > 0 ) THEN - - Periodic = .TRUE. - StrNeeded(6) = .FALSE. - CYCLE - ENDIF !INDEX for "PERIODIC" - END IF - - IF ( StrNeeded(7) ) THEN - - IF ( INDEX( LINE, 'BLADED LEFT-HAND RULE') > 0 ) THEN - LHR = .TRUE. - StrNeeded(7) = .FALSE. - END IF ! INDEX for "BLADED LEFT-HAND RULE" - - END IF - - ENDIF ! StrNeeded - - ENDDO !WHILE - - !------------------------------------------------------------------------------------------------- - ! Close the summary file - !------------------------------------------------------------------------------------------------- - - CLOSE ( UnitWind ) - - - !------------------------------------------------------------------------------------------------- - ! Calculate the height of the grid center - !------------------------------------------------------------------------------------------------- - - ZCenter = RefHt - ZGOffset - - - END SUBROUTINE Read_Summary_FF - - !==================================================================================================== - !> Reads the binary headers from the turbulence files of the old Bladed variety. Note that - !! because of the normalization, neither ParamData%FF%NZGrids or ParamData%FF%NYGrids are larger than 32 points. - !! 21-Sep-2009 - B. Jonkman, NREL/NWTC. - !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 - SUBROUTINE Read_Bladed_FF_Header0 (UnitWind, p, NativeBladedFmt, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="Read_Bladed_FF_Header0" - - ! Passed Variables: - - INTEGER(IntKi), INTENT(IN ) :: UnitWind !< unit number of already-opened wind file - TYPE(IfW_FFWind_ParameterType), INTENT(INOUT) :: p !< Parameters - LOGICAL, INTENT(IN ) :: NativeBladedFmt !< Whether this should ignore the advection speed in the binary file - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message - - - ! Local Variables: - REAL(ReKi) :: FFXDelt - REAL(ReKi) :: FFYDelt - REAL(ReKi) :: FFZDelt - - INTEGER(B2Ki) :: Dum_Int2 - INTEGER(IntKi) :: I - - - ! Temporary Error Handling - INTEGER(IntKi) :: TmpErrStat ! for checking the IOSTAT from a READ or Open statement - - - !------------------------------------------------------------------------------------------------- - ! Initializations - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = '' - - - !------------------------------------------------------------------------------------------------- - ! Read the header (file has just been opened) - !------------------------------------------------------------------------------------------------- - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! -NFFC (file ID) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading number of wind components from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - p%NFFComp = -1*Dum_Int2 - - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! delta z (mm) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dz from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - FFZDelt = 0.001*Dum_Int2 - p%InvFFZD = 1.0/FFZDelt - - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! delta y (mm) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dy from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - FFYDelt = 0.001*Dum_Int2 - p%InvFFYD = 1.0/FFYDelt - - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! delta x (mm) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dx from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - FFXDelt = 0.001*Dum_Int2 - - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! half the number of time steps - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading number of time steps from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - p%NFFSteps = 2*Dum_Int2 - - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! 10 times the mean full-field wind speed - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading mean full-field wind speed from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - if (.not. NativeBladedFmt) p%MeanFFWS = 0.1*Dum_Int2 - p%InvMFFWS = 1.0/p%MeanFFWS - p%FFDTime = FFXDelt/p%MeanFFWS - p%FFRate = 1.0/p%FFDTime - - - DO I = 1,5 - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! unused variables: zLu, yLu, xLu, dummy, random seed - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 2-byte integers from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - END DO - - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! 1000*nz - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading nz from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - p%NZGrids = Dum_Int2/1000 - p%FFZHWid = 0.5*FFZDelt*( p%NZGrids - 1 ) ! half the vertical size of the grid - - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! 1000*ny - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading ny from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - p%NYGrids = Dum_Int2/1000 - p%FFYHWid = 0.5*FFYDelt*( p%NYGrids - 1 ) - - - IF (p%NFFComp == 3) THEN - - DO I=1,6 - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! unused variables: zLv, yLv, xLv, zLw, yLw, xLw - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 2-byte length scales from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ENDDO !I - - ENDIF !NFFComp - - - RETURN - - END SUBROUTINE Read_Bladed_FF_Header0 - !==================================================================================================== - !> Reads the binary headers from the turbulence files of the new Bladed variety. - !! 16-May-2002 - Windward Engineering. - !! 21-Sep-2009 - B. Jonkman, NREL. updated to trap errors and add extra parameters for MANN model - !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 - SUBROUTINE Read_Bladed_FF_Header1 (UnitWind, TI, p, NativeBladedFmt, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="Read_Bladed_FF_Header1" - - - ! Passed Variables: - - INTEGER(IntKi), INTENT(IN ) :: UnitWind !< unit number of already-opened wind file - REAL(ReKi), INTENT( OUT) :: TI(3) !< turbulence intensity contained in file header - TYPE(IfW_FFWind_ParameterType), INTENT(INOUT) :: p !< Parameters - LOGICAL, INTENT(IN ) :: NativeBladedFmt !< Whether this should ignore the advection speed in the binary file - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message - - - ! Local Variables: - - REAL(ReKi) :: FFXDelt - REAL(ReKi) :: FFYDelt - REAL(ReKi) :: FFZDelt - - REAL(SiKi) :: Dum_Real4 - INTEGER(B2Ki) :: Dum_Int2 - INTEGER(B4Ki) :: Dum_Int4 - - INTEGER(IntKi) :: I - INTEGER(IntKi) :: TurbType - - - ! Temporary Error Handling - INTEGER(IntKi) :: TmpErrStat - - - !------------------------------------------------------------------------------------------------- - ! Initializations - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = '' - - TI(:) = -1 !Initialize to -1 (not all models contain TI) - - !------------------------------------------------------------------------------------------------- - ! File reading - !------------------------------------------------------------------------------------------------- - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! -99 (file ID) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading integer from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! turbulence type - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading turbulence type from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - TurbType = Dum_Int2 - - - SELECT CASE (TurbType) - CASE(1, 2) - !---------------------------------------- - !1-component Von Karman (1) or Kaimal (2) - !---------------------------------------- - p%NFFComp = 1 - - CASE(3, 5) - !---------------------------------------- - !3-component Von Karman (3) or IEC-2 - ! Kaimal (5) - !---------------------------------------- - p%NFFComp = 3 - - CASE(4) - !---------------------------------------- - !improved Von Karman - !---------------------------------------- - - ! Read 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! number of components (should be 3) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading number of components from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - p%NFFComp = Dum_Int4 - - ! Read 4-byte real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! Latitude (deg) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading latitude from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ! Read 4-byte real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! Roughness length (m) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading roughness length from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ! Read 4-byte real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! Reference height (m) = Z(1) + GridHeight / 2.0 - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading reference height from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - - DO I = 1,3 - ! Read 4-byte real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! TI(u, v, w) (%) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading TI('//'TRIM(Num2LStr(I))'//') from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - TI(I) = Dum_Real4 ! This overwrites the TI read in the summary file - - END DO !I - - - CASE (7, 8) - !---------------------------------------- - ! General Kaimal (7) or Mann model (8) - !---------------------------------------- - - ! Read 4-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! number of bytes in header - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading number of header records from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ! Read 4-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! number of components - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading number of data from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - p%NFFComp = Dum_Int4 - - - CASE DEFAULT - - CALL SetErrStat( ErrID_Warn, ' InflowWind does not recognize the full-field turbulence file type ='// & - TRIM(Num2LStr(TurbType))//'.', ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - END SELECT !TurbType - - - ! Read 4-byte real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! delta z (m) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dz from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - FFZDelt = Dum_Real4 - p%InvFFZD = 1.0/FFZDelt - - - ! Read 4-byte real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! delta y (m) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dy from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - FFYDelt = Dum_Real4 - p%InvFFYD = 1.0/FFYDelt - - ! Read 4-byte real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! delta x (m) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dx from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - FFXDelt = Dum_Real4 - - - ! Read 4-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! half the number of time steps - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading number of time steps from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - p%NFFSteps = 2*Dum_Int4 - - - ! Read 4-byte real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! mean full-field wind speed - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading mean full-field wind speed from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - if (.not. NativeBladedFmt) p%MeanFFWS = Dum_Real4 - p%InvMFFWS = 1.0/p%MeanFFWS - p%FFDTime = FFXDelt/p%MeanFFWS - p%FFRate = 1.0/p%FFDTime - - - DO I = 1,3 - - ! Read 4-byte real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! unused variables: zLu, yLu, xLu - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 4-byte length scales from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - END DO - - - DO I = 1,2 - - ! Read 4-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! unused variables: dummy, random seed - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 4-byte integers from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - END DO - - - ! Read 4-integer real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! nz - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading nz from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - p%NZGrids = Dum_Int4 - p%FFZHWid = 0.5*FFZDelt*( p%NZGrids - 1 ) ! half the vertical size of the grid - - - ! Read 4-integer real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! ny - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading ny from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - p%NYGrids = Dum_Int4 - p%FFYHWid = 0.5*FFYDelt*( p%NYGrids - 1 ) - - - IF (p%NFFComp == 3) THEN - - DO I=1,6 - - ! Read 4-real real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! unused variables: zLv, yLv, xLv, zLw, yLw, xLw - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 4-byte length scales from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ENDDO !I - - ENDIF !NFFComp - - - - IF ( TurbType == 7 ) THEN ! General Kaimal model - - ! Read 4-real real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! unused variable: coherence decay constant - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading coherence decay constant from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ! Read 4-real real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! unused variables: coherence scale parameter in m - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading coherence scale parameter from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ELSE IF ( TurbType == 8 ) THEN ! Mann model - - DO I=1,2 - - ! Read 4-real real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! unused variables: shear parameter (gamma), scale length - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 4-byte parameters from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ENDDO !I - - DO I=1,4 - - ! Read 4-real real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! unused variables - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 4-byte parameters from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ENDDO !I - - DO I=1,3 - - ! Read 4-integer real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! unused variables - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 4-byte parameters from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ENDDO !I - - DO I=1,2 - - ! Read 4-real real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! unused variables - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 4-byte parameters from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ENDDO !I - - DO I=1,3 - - ! Read 4-integer real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! unused variables - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 4-byte parameters from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ENDDO !I - - DO I=1,2 - - ! Read 4-real real. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! unused variables - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading 4-byte parameters from binary FF file.', ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - - ENDDO !I - - - ENDIF !TurbType - - - RETURN - - END SUBROUTINE Read_Bladed_FF_Header1 - !==================================================================================================== - !> This subroutine continues reading UnitWind, starting after the headers have been read. - !! It reads the Grids and converts the data to un-normalized wind speeds in m/s. - !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 - SUBROUTINE Read_Bladed_Grids ( UnitWind, NativeBladedFmt, CWise, LHR, TI, p, ErrStat, ErrMsg ) - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="Read_Bladed_Grids" - - ! Passed variables - - INTEGER(IntKi), INTENT(IN ) :: UnitWind !< unit number of already-opened wind file - LOGICAL, INTENT(IN ) :: NativeBladedFmt !< whether this data is in native Bladed format (scale to zero mean and unit standard deviation) - LOGICAL, INTENT(IN ) :: CWise !< clockwise flag (determines if y is increasing or decreasing in file) - LOGICAL, INTENT(IN ) :: LHR !< Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) - REAL(ReKi), INTENT(IN ) :: TI (3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI - TYPE(IfW_FFWind_ParameterType), INTENT(INOUT) :: p !< Parameters - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message - - REAL(ReKi) :: FF_Scale(3) !< used for "un-normalizing" the data - REAL(ReKi) :: FF_Offset(3) !< used for "un-normalizing" the data - - INTEGER(IntKi) :: CFirst - INTEGER(IntKi) :: CLast - INTEGER(IntKi) :: CStep - INTEGER(B2Ki) :: Dum_Int2 - INTEGER(IntKi) :: I - INTEGER(IntKi) :: IC - INTEGER(IntKi) :: IR - INTEGER(IntKi) :: IT - - INTEGER(IntKi) :: TmpNumSteps - - ! Temporary variables for error handling - - INTEGER(IntKi) :: TmpErrStat ! for checking the result of IOSTAT on READ or Open statements - CHARACTER(ErrMsgLen) :: TmpErrMsg - - IF (NativeBladedFmt) THEN - FF_Scale = 0.001_ReKi - FF_Offset = 0.0_ReKi - ELSE - FF_Scale = 0.001_ReKi*p%MeanFFWS*TI/100.0_ReKi - FF_Offset= (/ p%MeanFFWS, 0.0_ReKi, 0.0_ReKi /) ! used for "un-normalizing" the data - END IF - - ! Bladed convention has positive V pointed along negative Y - IF (LHR) THEN ! left-hand rule - FF_Scale(2) = -FF_Scale(2) - END IF - - - !------------------------------------------------------------------------------------------------- - ! Generate an informative message. Initialize the ErrStat. - !------------------------------------------------------------------------------------------------- - ! This could take a while, so we'll write a message to tell users what's going on: - - CALL WrScr( NewLine//' Reading a '//TRIM( Num2LStr(p%NYGrids) )//'x'//TRIM( Num2LStr(p%NZGrids) )// & - ' grid ('//TRIM( Num2LStr(p%FFYHWid*2) )//' m wide, '// & - TRIM( Num2LStr(p%GridBase) )//' m to '// & - TRIM( Num2LStr(p%GridBase+p%FFZHWid*2) )//& - ' m above ground) with a characteristic wind speed of '//TRIM( Num2LStr(p%MeanFFWS) )//' m/s. ' ) - ErrMsg = "" - ErrStat = ErrID_None - - - !------------------------------------------------------------------------------------------------- - ! Allocate space for the FF array - !------------------------------------------------------------------------------------------------- - - TmpNumSteps = p%NFFSteps + 1 ! add another step, just in case there is an odd number of steps. - - !bjj: should we reorganize this FFData array so we access the data faster? - - IF ( .NOT. ALLOCATED( p%FFData ) ) THEN - CALL AllocAry( p%FFData, p%NZGrids,p%NYGrids,p%NFFComp,TmpNumSteps, & - 'Full-field wind data array.', TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - ELSE - IF (SIZE(p%FFData,1) /= p%NZGrids .OR. SIZE(p%FFData,2) /= p%NYGrids .OR. & - SIZE(p%FFData,3) /= p%NFFComp .OR. SIZE(p%FFData,3) /= TmpNumSteps ) THEN - - ! Let's make the array the correct size (we should never get here, but you never know) - - DEALLOCATE( p%FFData ) - - CALL AllocAry( p%FFData, p%NZGrids,p%NYGrids,p%NFFComp,TmpNumSteps, & - 'Full-field wind data array.', TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - ENDIF !Incorrect size - ENDIF ! allocated - - !------------------------------------------------------------------------------------------------- - ! Initialize the data and set column indexing to account for direction of turbine rotation (CWise) - !------------------------------------------------------------------------------------------------- - - p%FFData(:,:,:,:) = 0.0 ! we may have only one component - - IF ( CWise ) THEN - CFirst = p%NYGrids - CLast = 1 - CStep = -1 - ELSE - CFirst = 1 - CLast = p%NYGrids - CStep = 1 - ENDIF - - - !------------------------------------------------------------------------------------------------- - ! Loop through all the time steps, reading the data and converting to m/s - !------------------------------------------------------------------------------------------------- - !bjj: should we reorganize this FFData array so we access the data faster? - - p%NFFSteps = TmpNumSteps - - TIME_LOOP: DO IT=1,TmpNumSteps ! time (add 1 to see if there is an odd number of grids) - - DO IR=1,p%NZGrids ! the rows (vertical) - - DO IC=CFirst,CLast,CStep ! the columns (lateral) - - DO I=1,p%NFFComp ! wind components (U, V, W) - - ! Get the next integer from the file. - ! This is a 2-byte integer, so we can't use the library read routines. - READ (UnitWind,IOStat=TmpErrStat) Dum_Int2 - IF (TmpErrStat /= 0) THEN - IF ( IT == TmpNumSteps ) THEN ! There really were an even number of steps - p%NFFSteps = TmpNumSteps - 1 - ErrStat = 0 - EXIT TIME_LOOP - ELSE - CALL SetErrStat( ErrID_Fatal, ' Error reading binary data file. '// & - 'ic = '//TRIM(Num2LStr(ic))// & - ', ir = '//TRIM(Num2LStr(ir))// & - ', it = '//TRIM(Num2LStr(it))// & - ', nffsteps = '//TRIM(Num2LStr(p%NFFSteps)), ErrStat, ErrMsg, RoutineName) - RETURN - ENDIF - ELSE - p%FFData(IR,IC,I,IT) = FF_Offset(I)+FF_Scale(I)*Dum_Int2 - ENDIF - - END DO !I - - END DO !IC - - END DO !IR - - END DO TIME_LOOP !IT - - IF ( p%Periodic ) THEN - TmpErrMsg = ' Processed '//TRIM( Num2LStr( p%NFFSteps ) )//' time steps of '// & - TRIM( Num2LStr ( p%FFRate ) )//'-Hz full-field data (period of '// & - TRIM( Num2LStr( p%FFDTime*p%NFFSteps ) )//' seconds).' - - ELSE - TmpErrMsg= ' Processed '//TRIM( Num2LStr( p%NFFSteps ) )//' time steps of '// & - TRIM( Num2LStr ( p%FFRate ) )//'-Hz full-field data ('// & - TRIM( Num2LStr( p%FFDTime*( p%NFFSteps - 1 ) ) )//' seconds).' - ENDIF - CALL WrScr( NewLine//TRIM(TmpErrMsg) ) - !CALL SetErrStat( ErrID_Info, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - - - END SUBROUTINE Read_Bladed_Grids - !==================================================================================================== - !> This subroutine reads the binary tower file that corresponds with the Bladed-style FF binary file. - !! The FF grid must be read before this subroutine is called! (many checks are made to ensure the - !! files belong together) - !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 - SUBROUTINE Read_FF_Tower( UnitWind, p, TwrFileName, ErrStat, ErrMsg ) - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="Read_FF_Tower" - - - ! Passed Variables: - INTEGER(IntKi) :: UnitWind !< unit number of wind file to be opened - TYPE(IfW_FFWind_ParameterType), INTENT(INOUT) :: p !< Parameters - CHARACTER(*), INTENT(IN ) :: TwrFileName - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status return value (0=no error; non-zero is error) - CHARACTER(*), INTENT( OUT) :: ErrMsg !< a message for errors that occur - - ! Local Variables: - - REAL(SiKi) :: Dum_Real4 ! dummy 4-byte real number - INTEGER(B2Ki) :: Dum_Int2 ! dummy 2-byte integer - INTEGER(B4Ki) :: Dum_Int4 ! dummy 4-byte integer - - INTEGER(IntKi) :: IC ! loop counter for wind components - INTEGER(IntKi) :: IT ! loop counter for time - INTEGER(IntKi) :: IZ ! loop counter for z - - REAL(ReKi), PARAMETER :: TOL = 1E-4 ! tolerence for wind file comparisons - - REAL(ReKi), PARAMETER :: FF_Offset(3) = (/ 1.0, 0.0, 0.0 /) ! used for "un-normalizing" the data - REAL(SiKi) :: TI (3) ! scaling values for "un-normalizing the data" [approx. turbulence intensities of the wind components] - - - ! Temporary Error Handling - - INTEGER(IntKi) :: TmpErrStat ! IOSTAT value. - CHARACTER(ErrMsgLen) :: TmpErrMsg - - !------------------------------------------------------------------------------------------------- - ! Initialization - !------------------------------------------------------------------------------------------------- - - ErrMsg = '' - ErrStat = ErrID_None - - p%NTGrids = 0 - - IF ( p%NFFComp /= 3 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error: Tower binary files require 3 wind components.', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - !------------------------------------------------------------------------------------------------- - ! Open the file - !------------------------------------------------------------------------------------------------- - - CALL OpenBInpFile (UnitWind, TRIM(TwrFileName), TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF (ErrStat >= AbortErrLev) RETURN - - !------------------------------------------------------------------------------------------------- - ! Read the header information and check that it's compatible with the FF Bladed-style binary - ! parameters already read. - !------------------------------------------------------------------------------------------------- - ! This is a 4-byte real, so we can't use the library read routines. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! dz, in meters [4-byte REAL] - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dz in the binary tower file "'//TRIM( TwrFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - IF ( ABS(Dum_Real4*p%InvFFZD-1) > TOL ) THEN - CALL SetErrStat( ErrID_Fatal, ' Resolution in the FF binary file does not match the tower file.', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - - ! This is a 4-byte real, so we can't use the library read routines. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! dx, in meters [4-byte REAL] - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dx in the binary tower file "'//TRIM( TwrFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - IF ( ABS(Dum_Real4*p%InvMFFWS/p%FFDTime-1) > TOL ) THEN - CALL SetErrStat( ErrID_Fatal, ' Time resolution in the FF binary file does not match the tower file.', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - - ! This is a 4-byte real, so we can't use the library read routines. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! Zmax, in meters [4-byte REAL] - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading Zmax in the binary tower file "'//TRIM( TwrFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - IF ( ABS(Dum_Real4/p%GridBase-1) > TOL ) THEN - CALL SetErrStat( ErrID_Fatal, ' Height in the FF binary file does not match the tower file "'//TRIM( TwrFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - - ! This is a 4-byte integer, so we can't use the library read routines. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! NumOutSteps [4-byte INTEGER] - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading NumOutSteps in the binary tower file "'//TRIM( TwrFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - IF ( Dum_Int4 /= p%NFFSteps ) THEN - CALL SetErrStat( ErrID_Fatal, ' Number of time steps in the FF binary file does not match the tower file.', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - - ! This is a 4-byte integer, so we can't use the library read routines. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! NumZ [4-byte INTEGER] - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading NumZ in the binary tower file "'//TRIM( TwrFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - p%NTGrids = Dum_Int4 - - - ! This is a 4-byte real, so we can't use the library read routines. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! UHub [4-byte REAL] - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading UHub in the binary tower file "'//TRIM( TwrFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - IF ( ABS(Dum_Real4*p%InvMFFWS - 1) > TOL ) THEN - CALL SetErrStat( ErrID_Fatal, ' Mean wind speed in the FF binary file does not match the tower file.', ErrStat, ErrMsg, RoutineName ) - p%NTGrids = 0 - RETURN - ENDIF - - - DO IC=1,3 - ! Read the TI values fromthe tower file: 4-byte reals. - - !bjj: not sure you can call this routine to read from a binary file... - !CALL ReadVar( UnitWind, TRIM(InitInp%WindFileName), TI(IC), 'TI('//TRIM(Num2LStr(IC))//')', 'TI value for u,v, or w', TmpErrStat, TmpErrMsg ) - !IF (TmpErrStat /= ErrID_None) THEN - ! p%NTGrids = 0 - ! CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - ! IF (ErrStat >= AbortErrLev) RETURN - !ENDIF - ! - READ (UnitWind, IOSTAT=TmpErrStat) TI(IC) ! TI(u), TI(v), TI(w) [4-byte REAL] - - IF (TmpErrStat /= 0) THEN - p%NTGrids = 0 - CALL SetErrStat( ErrID_Fatal, ' Error reading TI('//TRIM(Num2LStr(IC))//') in the binary tower file "' & - //TRIM( TwrFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - END DO - - !---------------------------------------------------------------------------------------------- - ! Allocate arrays for the tower points - !---------------------------------------------------------------------------------------------- - - IF ( p%NTGrids > 0 ) THEN - - IF ( .NOT. ALLOCATED( p%FFTower ) ) THEN - CALL AllocAry( p%FFTower, p%NFFComp, p%NTGrids, p%NFFSteps, & - 'Tower wind data array.', TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF (ErrStat >= AbortErrLev) RETURN - - ELSE - ! Check sizes here! - ENDIF - - ENDIF - - !------------------------------------------------------------------------------------------------- - ! Read the 16-bit time-series data and scale it to 32-bit reals - !------------------------------------------------------------------------------------------------- - - ! Loop through time. - - DO IT=1,p%NFFSteps - - DO IZ=1,p%NTGrids ! If NTGrids<1, there are no tower points & FFTower is not allocated - - ! Ytower = 0 ! Lateral location of the tower data point, in m relative to tower centerline - ! Ztower(IZ) = Z1 - (IZ-1)*dz ! Vertical location of tower data point, in m relative to ground - - DO IC=1,p%NFFComp ! number of wind components - - ! Read in the 2-byte integer. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! normalized wind-component, INT(2) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading binary tower data file. it = '//TRIM(Num2LStr(it))// & - ', nffsteps = '//TRIM(Num2LStr(p%NFFSteps)), ErrStat, ErrMsg, RoutineName ) - p%NTGrids = 0 - RETURN - ENDIF - - p%FFTower(IC,IZ,IT) = p%MeanFFWS*(FF_Offset(IC)+0.00001*TI(IC)*Dum_Int2) ! wind-component scaled to m/s - - ENDDO !IC - - ENDDO ! IZ - - - ENDDO ! IT - - !------------------------------------------------------------------------------------------------- - ! Close the file - !------------------------------------------------------------------------------------------------- - CLOSE ( UnitWind ) - - TmpErrMsg = ' Processed '//TRIM( Num2LStr(p%NFFSteps) )//' time steps of '// & - TRIM( Num2LStr(p%NTGrids) )//'x1 tower data grids.' - - !CALL SetErrStat( ErrID_Info, ErrMsgLcl, ErrStat, ErrMsg, RoutineName ) - CALL WrScr( NewLine//TRIM(TmpErrMsg) ) - - RETURN - - END SUBROUTINE Read_FF_Tower -!==================================================================================================== -!> This subroutine reads the text summary file to get normalizing parameters, the location of the -!! grid, and the direction the grid was written to the binary file -SUBROUTINE Read_NativeBladedSummary ( FileName, PLExp, VLinShr, HLinShr, RefLength, TI, UBar, RefHt, PropagationDir, VFlowAngle, BinFileName, XOffset, ErrStat, ErrMsg ) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="Read_NativeBladedSummary" - - - ! Passed variables - CHARACTER(*), INTENT(IN ) :: FileName !< name of the summary file - REAL(ReKi), INTENT( OUT) :: PLExp !< the power-law exponent for vertical wind shear - REAL(ReKi), INTENT( OUT) :: VLinShr !< the linear shape for vertical wind shear - REAL(ReKi), INTENT( OUT) :: HLinShr !< the linear shape for horizontal wind shear - REAL(ReKi), INTENT( OUT) :: RefLength !< Reference (rotor) diameter - REAL(ReKi), INTENT( OUT) :: TI (3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI - REAL(ReKi), INTENT( OUT) :: UBar !< mean (advection) wind speed - REAL(ReKi), INTENT( OUT) :: RefHt !< Reference height - REAL(ReKi), INTENT( OUT) :: PropagationDir !< propagation direction - REAL(ReKi), INTENT( OUT) :: VFlowAngle !< vertical flow angle - CHARACTER(*), INTENT( OUT) :: BinFileName !< name of the binary file containing wind data - REAL(ReKi), INTENT( OUT) :: XOffset !< distance offset for start of wind files - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< returns 0 if no error encountered in the subroutine - CHARACTER(*), INTENT( OUT) :: ErrMsg !< holds the error messages - - ! Local variables - INTEGER(IntKi), PARAMETER :: UnEc= -1 ! echo file unit number (set to something else > 0 for debugging) - INTEGER(IntKi) :: CurLine ! Current line to parse in FileInfo data structure - INTEGER(IntKi) :: ErrStat2 ! temporary error status - CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary error message - - TYPE (FileInfoType) :: FileInfo ! The derived type for holding the file information. - - - !---------------------------------------------------------------------------------------------- - ! Initialize some variables - !---------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = '' - - !---------------------------------------------------------------------------------------------- - ! Open and read the summary file; store data in FileInfo structure. - !---------------------------------------------------------------------------------------------- - - CALL ProcessComFile ( FileName, FileInfo, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - END IF - - !------------------------------------------------------------------------------------------------- - ! Process the lines stored in FileInfo - !------------------------------------------------------------------------------------------------- - - CurLine = 1 - - CALL ParseVar ( FileInfo, CurLine, 'UBAR', UBar, ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL ParseVar ( FileInfo, CurLine, 'REFHT', RefHt, ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL ParseVar ( FileInfo, CurLine, 'TI', TI(1), ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL ParseVar ( FileInfo, CurLine, 'TI_V', TI(2), ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL ParseVar ( FileInfo, CurLine, 'TI_W', TI(3), ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL ParseVar ( FileInfo, CurLine, 'WDIR', PropagationDir, ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - PropagationDir = R2D*PropagationDir - - CALL ParseVar ( FileInfo, CurLine, 'FLINC', VFlowAngle, ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - VFlowAngle = R2D*VFlowAngle ! convert to degrees - - CALL ParseVar ( FileInfo, CurLine, 'WINDF', BinFileName, ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL ParseVar ( FileInfo, CurLine, 'WSHEAR', PLExp, ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - END IF - - - CALL ParseVar ( FileInfo, CurLine, 'VLINSHEAR', VLinShr, ErrStat2, ErrMsg2, UnEc ) - if (ErrStat2/=ErrID_None) then - VLinShr = 0.0_ReKi ! this will be the default if VLINSHEAR is not in the file - end if - - CALL ParseVar ( FileInfo, CurLine, 'HLINSHEAR', HLinShr, ErrStat2, ErrMsg2, UnEc ) - if (ErrStat2/=ErrID_None) then - HLinShr = 0.0_ReKi ! this will be the default if HLINSHEAR is not in the file - end if - - CALL ParseVar ( FileInfo, CurLine, 'REFLENGTH', RefLength, ErrStat2, ErrMsg2, UnEc ) - if (ErrStat2/=ErrID_None) then - RefLength = 0.0_ReKi ! this will be the default if RefLength is not in the file; it will cause an error if either of the linear shears are non-zero - end if - - CALL ParseVar ( FileInfo, CurLine, 'XOffset', XOffset, ErrStat2, ErrMsg2, UnEc ) - if (ErrStat2/=ErrID_None) then - XOffset = 0.0_ReKi ! this will be the default if offset is not in the file - end if - - - !------------------------------------------------------------------------------------------------- - ! Get rid of the FileInfo data structure (including pointers and allocatable array): - !------------------------------------------------------------------------------------------------- - - call Cleanup ( ) - - -CONTAINS - - SUBROUTINE Cleanup () - CALL NWTC_Library_DestroyFileInfoType (FileInfo, ErrStat2, ErrMsg2) - END SUBROUTINE Cleanup - -END SUBROUTINE Read_NativeBladedSummary -!==================================================================================================== - - -!==================================================================================================== -!> This routine acts as a wrapper for the GetWindSpeed routine. It steps through the array of input -!! positions and calls the GetWindSpeed routine to calculate the velocities at each point. -!! -!! There are inefficiencies in how this set of routines is coded, but that is a problem for another -!! day. For now, it merely needs to be functional. It can be fixed up and made all pretty later. -!! -!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -SUBROUTINE IfW_BladedFFWind_CalcOutput(Time, PositionXYZ, ParamData, Velocity, MiscVars, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_BladedFFWind_CalcOutput" - - ! Passed Variables - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - REAL(ReKi), INTENT(IN ) :: PositionXYZ(:,:) !< Array of XYZ coordinates, 3xN - TYPE(IfW_BladedFFWind_ParameterType), INTENT(IN ) :: ParamData !< Parameters - REAL(ReKi), INTENT(INOUT) :: Velocity(:,:) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) - TYPE(IfW_BladedFFWind_MiscVarType), INTENT(INOUT) :: MiscVars !< misc/optimization data (storage for the main data) - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message - - - - CALL IfW_FFWind_CalcOutput(Time, PositionXYZ, ParamData%FF, Velocity, ErrStat, ErrMsg) - - - RETURN - -END SUBROUTINE IfW_BladedFFWind_CalcOutput - -!==================================================================================================== -!! This subroutine cleans up any data that is still allocated. The (possibly) open files are -!! closed in InflowWindMod. -!! -!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -SUBROUTINE IfW_BladedFFWind_End( ParamData, MiscVars, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_BladedFFWind_End" - ! Passed Variables - TYPE(IfW_BladedFFWind_ParameterType), INTENT(INOUT) :: ParamData !< Parameters - TYPE(IfW_BladedFFWind_MiscVarType), INTENT(INOUT) :: MiscVars !< misc/optimization data (storage for the main data) - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Local Variables - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - !-=- Initialize the routine -=- - - ErrMsg = '' - ErrStat = ErrID_None - - - - ! Destroy parameter data - - CALL IfW_BladedFFWind_DestroyParam( ParamData, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - - ! Destroy the state data - - CALL IfW_BladedFFWind_DestroyMisc( MiscVars, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - - -END SUBROUTINE IfW_BladedFFWind_End - -!==================================================================================================== -END MODULE IfW_BladedFFWind diff --git a/modules/inflowwind/src/IfW_BladedFFWind.txt b/modules/inflowwind/src/IfW_BladedFFWind.txt deleted file mode 100644 index 76a57b1b5f..0000000000 --- a/modules/inflowwind/src/IfW_BladedFFWind.txt +++ /dev/null @@ -1,41 +0,0 @@ -################################################################################################################################### -# Registry for IfW_BladedFFWind, creates MODULE IfW_BladedFFWind_Types -# Module IfW_BladedFFWind_Types contains all of the user-defined types needed in IfW_BladedFFWind. It also contains copy, destroy, pack, and -# unpack routines associated with each defined data types. -################################################################################################################################### -# Entries are of the form -# keyword -################################################################################################################################### - -include Registry_NWTC_Library.txt -usefrom IfW_FFWind_Base.txt - - -######################### - -typedef IfW_BladedFFWind/IfW_BladedFFWind InitInputType CHARACTER(1024) WindFileName - - - "Name of the wind file to use" - -typedef ^ ^ Logical TowerFileExist - - - "Tower file exists" - -typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - -typedef ^ ^ Logical NativeBladedFmt - - - "Whether this is native Bladed (needs wind profile and TI scaling) or not" - -typedef ^ ^ IntKi TurbineID - 0 - "Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm)" - -typedef ^ ^ LOGICAL FixedWindFileRootName - .FALSE. - "Do the wind data files have a fixed (DEFAULT) file name? (used by FAST.Farm)" - -#typedef ^ ^ IfW_FFWind_InitInputType FF - - - "scaling data (provided for native Bladed format)" - - - -# Init Output -typedef ^ InitOutputType ProgDesc Ver - - - "Version information off FFWind submodule" - -typedef ^ ^ ReKi TI {3} - - "Turbulence intensity given in the file" - -typedef ^ InitOutputType ReKi PropagationDir - - - "Propogation direction from native Bladed format" degrees -typedef ^ InitOutputType ReKi VFlowAngle - - - "Vertical flow angle from native Bladed format" degrees - - -# ..... Misc/Optimization variables................................................................................................. -# Define any data that are used only for efficiency purposes (these variables are not associated with time): -# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType IntKi dummy - 0 - "An Index into the TData array" - - -# ..... Parameters ................................................................................................................ -# Define parameters here: -# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType IfW_FFWind_ParameterType FF - - - "Parameters used in all full-field wind types" - - diff --git a/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 b/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 deleted file mode 100644 index 4f0ea3b994..0000000000 --- a/modules/inflowwind/src/IfW_BladedFFWind_Types.f90 +++ /dev/null @@ -1,847 +0,0 @@ -!STARTOFREGISTRYGENERATEDFILE 'IfW_BladedFFWind_Types.f90' -! -! WARNING This file is generated automatically by the FAST registry. -! Do not edit. Your changes to this file will be lost. -! -! FAST Registry -!********************************************************************************************************************************* -! IfW_BladedFFWind_Types -!................................................................................................................................. -! This file is part of IfW_BladedFFWind. -! -! Copyright (C) 2012-2016 National Renewable Energy Laboratory -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -! -! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. -! -!********************************************************************************************************************************* -!> This module contains the user-defined types needed in IfW_BladedFFWind. It also contains copy, destroy, pack, and -!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE IfW_BladedFFWind_Types -!--------------------------------------------------------------------------------------------------------------------------------- -USE IfW_FFWind_Base_Types -USE NWTC_Library -IMPLICIT NONE -! ========= IfW_BladedFFWind_InitInputType ======= - TYPE, PUBLIC :: IfW_BladedFFWind_InitInputType - CHARACTER(1024) :: WindFileName !< Name of the wind file to use [-] - LOGICAL :: TowerFileExist !< Tower file exists [-] - INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file (-1 for none). Provided by IfW. [-] - LOGICAL :: NativeBladedFmt !< Whether this is native Bladed (needs wind profile and TI scaling) or not [-] - INTEGER(IntKi) :: TurbineID = 0 !< Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm) [-] - LOGICAL :: FixedWindFileRootName = .FALSE. !< Do the wind data files have a fixed (DEFAULT) file name? (used by FAST.Farm) [-] - END TYPE IfW_BladedFFWind_InitInputType -! ======================= -! ========= IfW_BladedFFWind_InitOutputType ======= - TYPE, PUBLIC :: IfW_BladedFFWind_InitOutputType - TYPE(ProgDesc) :: Ver !< Version information off FFWind submodule [-] - REAL(ReKi) , DIMENSION(1:3) :: TI !< Turbulence intensity given in the file [-] - REAL(ReKi) :: PropagationDir !< Propogation direction from native Bladed format [degrees] - REAL(ReKi) :: VFlowAngle !< Vertical flow angle from native Bladed format [degrees] - END TYPE IfW_BladedFFWind_InitOutputType -! ======================= -! ========= IfW_BladedFFWind_MiscVarType ======= - TYPE, PUBLIC :: IfW_BladedFFWind_MiscVarType - INTEGER(IntKi) :: dummy = 0 !< An Index into the TData array [-] - END TYPE IfW_BladedFFWind_MiscVarType -! ======================= -! ========= IfW_BladedFFWind_ParameterType ======= - TYPE, PUBLIC :: IfW_BladedFFWind_ParameterType - TYPE(IfW_FFWind_ParameterType) :: FF !< Parameters used in all full-field wind types [-] - END TYPE IfW_BladedFFWind_ParameterType -! ======================= -CONTAINS - SUBROUTINE IfW_BladedFFWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_BladedFFWind_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(IfW_BladedFFWind_InitInputType), INTENT(INOUT) :: DstInitInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_CopyInitInput' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitInputData%WindFileName = SrcInitInputData%WindFileName - DstInitInputData%TowerFileExist = SrcInitInputData%TowerFileExist - DstInitInputData%SumFileUnit = SrcInitInputData%SumFileUnit - DstInitInputData%NativeBladedFmt = SrcInitInputData%NativeBladedFmt - DstInitInputData%TurbineID = SrcInitInputData%TurbineID - DstInitInputData%FixedWindFileRootName = SrcInitInputData%FixedWindFileRootName - END SUBROUTINE IfW_BladedFFWind_CopyInitInput - - SUBROUTINE IfW_BladedFFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_BladedFFWind_InitInputType), INTENT(INOUT) :: InitInputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_DestroyInitInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_BladedFFWind_DestroyInitInput - - SUBROUTINE IfW_BladedFFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_BladedFFWind_InitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_PackInitInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName - Int_BufSz = Int_BufSz + 1 ! TowerFileExist - Int_BufSz = Int_BufSz + 1 ! SumFileUnit - Int_BufSz = Int_BufSz + 1 ! NativeBladedFmt - Int_BufSz = Int_BufSz + 1 ! TurbineID - Int_BufSz = Int_BufSz + 1 ! FixedWindFileRootName - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%WindFileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = TRANSFER(InData%TowerFileExist, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%SumFileUnit - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%NativeBladedFmt, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%TurbineID - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%FixedWindFileRootName, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_BladedFFWind_PackInitInput - - SUBROUTINE IfW_BladedFFWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_BladedFFWind_InitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_UnPackInitInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%WindFileName) - OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%TowerFileExist = TRANSFER(IntKiBuf(Int_Xferred), OutData%TowerFileExist) - Int_Xferred = Int_Xferred + 1 - OutData%SumFileUnit = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%NativeBladedFmt = TRANSFER(IntKiBuf(Int_Xferred), OutData%NativeBladedFmt) - Int_Xferred = Int_Xferred + 1 - OutData%TurbineID = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%FixedWindFileRootName = TRANSFER(IntKiBuf(Int_Xferred), OutData%FixedWindFileRootName) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_BladedFFWind_UnPackInitInput - - SUBROUTINE IfW_BladedFFWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_BladedFFWind_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(IfW_BladedFFWind_InitOutputType), INTENT(INOUT) :: DstInitOutputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_CopyInitOutput' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - DstInitOutputData%TI = SrcInitOutputData%TI - DstInitOutputData%PropagationDir = SrcInitOutputData%PropagationDir - DstInitOutputData%VFlowAngle = SrcInitOutputData%VFlowAngle - END SUBROUTINE IfW_BladedFFWind_CopyInitOutput - - SUBROUTINE IfW_BladedFFWind_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_BladedFFWind_InitOutputType), INTENT(INOUT) :: InitOutputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_DestroyInitOutput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_BladedFFWind_DestroyInitOutput - - SUBROUTINE IfW_BladedFFWind_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_BladedFFWind_InitOutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_PackInitOutput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Ver - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Ver - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Ver - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI - Re_BufSz = Re_BufSz + 1 ! PropagationDir - Re_BufSz = Re_BufSz + 1 ! VFlowAngle - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - DO i1 = LBOUND(InData%TI,1), UBOUND(InData%TI,1) - ReKiBuf(Re_Xferred) = InData%TI(i1) - Re_Xferred = Re_Xferred + 1 - END DO - ReKiBuf(Re_Xferred) = InData%PropagationDir - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VFlowAngle - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_BladedFFWind_PackInitOutput - - SUBROUTINE IfW_BladedFFWind_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_BladedFFWind_InitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_UnPackInitOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - i1_l = LBOUND(OutData%TI,1) - i1_u = UBOUND(OutData%TI,1) - DO i1 = LBOUND(OutData%TI,1), UBOUND(OutData%TI,1) - OutData%TI(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%PropagationDir = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VFlowAngle = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_BladedFFWind_UnPackInitOutput - - SUBROUTINE IfW_BladedFFWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_BladedFFWind_MiscVarType), INTENT(IN) :: SrcMiscData - TYPE(IfW_BladedFFWind_MiscVarType), INTENT(INOUT) :: DstMiscData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_CopyMisc' -! - ErrStat = ErrID_None - ErrMsg = "" - DstMiscData%dummy = SrcMiscData%dummy - END SUBROUTINE IfW_BladedFFWind_CopyMisc - - SUBROUTINE IfW_BladedFFWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_BladedFFWind_MiscVarType), INTENT(INOUT) :: MiscData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_DestroyMisc' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_BladedFFWind_DestroyMisc - - SUBROUTINE IfW_BladedFFWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_BladedFFWind_MiscVarType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_PackMisc' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! dummy - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = InData%dummy - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_BladedFFWind_PackMisc - - SUBROUTINE IfW_BladedFFWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_BladedFFWind_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%dummy = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_BladedFFWind_UnPackMisc - - SUBROUTINE IfW_BladedFFWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_BladedFFWind_ParameterType), INTENT(IN) :: SrcParamData - TYPE(IfW_BladedFFWind_ParameterType), INTENT(INOUT) :: DstParamData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_CopyParam' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL IfW_FFWind_CopyParam( SrcParamData%FF, DstParamData%FF, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_BladedFFWind_CopyParam - - SUBROUTINE IfW_BladedFFWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_BladedFFWind_ParameterType), INTENT(INOUT) :: ParamData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_DestroyParam' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL IfW_FFWind_DestroyParam( ParamData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_BladedFFWind_DestroyParam - - SUBROUTINE IfW_BladedFFWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_BladedFFWind_ParameterType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_PackParam' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype - CALL IfW_FFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! FF - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! FF - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! FF - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL IfW_FFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE IfW_BladedFFWind_PackParam - - SUBROUTINE IfW_BladedFFWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_BladedFFWind_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_BladedFFWind_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_FFWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_BladedFFWind_UnPackParam - -END MODULE IfW_BladedFFWind_Types -!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/IfW_FFWind_Base.f90 b/modules/inflowwind/src/IfW_FFWind_Base.f90 deleted file mode 100644 index 365feed37d..0000000000 --- a/modules/inflowwind/src/IfW_FFWind_Base.f90 +++ /dev/null @@ -1,1205 +0,0 @@ -!> This module uses full-field binary wind files to determine the wind inflow. -!! This module assumes that the origin, (0,0,0), is located at the tower centerline at ground level, -!! and that all units are specified in the metric system (using meters and seconds). -!! Data is shifted by half the grid width to account for turbine yaw (so that data in the X -!! direction actually starts at -1*p%FFYHWid meters). -MODULE IfW_FFWind_Base -!! -!! Created 25-Sep-2009 by B. Jonkman, National Renewable Energy Laboratory -!! using subroutines and modules from AeroDyn v12.58 -!! -!!---------------------------------------------------------------------------------------------------- -!! Feb 2013 v2.00.00 A. Platt -!! -- updated to the new framework -!! -- Modified to use NWTC_Library v. 2.0 -!! -- Note: Jacobians are not included in this version. -!! -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2015-2016 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** - - USE NWTC_Library - USE IfW_FFWind_Base_Types - - IMPLICIT NONE - - - INTEGER(IntKi), PARAMETER :: WindProfileType_None = -1 !< don't add a mean wind profile - INTEGER(IntKi), PARAMETER :: WindProfileType_Constant = 0 !< constant wind - INTEGER(IntKi), PARAMETER :: WindProfileType_Log = 1 !< logarithmic - INTEGER(IntKi), PARAMETER :: WindProfileType_PL = 2 !< power law - - INTEGER(IntKi), PARAMETER :: ScaleMethod_None = 0 !< no scaling - INTEGER(IntKi), PARAMETER :: ScaleMethod_Direct = 1 !< direct scaling factors - INTEGER(IntKi), PARAMETER :: ScaleMethod_StdDev = 2 !< requested standard deviation - - -CONTAINS -!==================================================================================================== - -!==================================================================================================== -!> This routine acts as a wrapper for the GetWindSpeed routine. It steps through the array of input -!! positions and calls the GetWindSpeed routine to calculate the velocities at each point. -SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, Velocity, ErrStat, ErrMsg) - - IMPLICIT NONE - - - ! Passed Variables - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - REAL(ReKi), INTENT(IN ) :: PositionXYZ(:,:) !< Array of XYZ coordinates, 3xN - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - REAL(ReKi), INTENT(INOUT) :: Velocity(:,:) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message - - ! local variables - INTEGER(IntKi) :: NumPoints ! Number of points specified by the PositionXYZ array - - ! local counters - INTEGER(IntKi) :: PointNum ! a loop counter for the current point - - ! temporary variables - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_CalcOutput' - - - !------------------------------------------------------------------------------------------------- - ! Check that the module has been initialized. - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = '' - - !------------------------------------------------------------------------------------------------- - ! Initialize some things - !------------------------------------------------------------------------------------------------- - - - ! The array is transposed so that the number of points is the second index, x/y/z is the first. - ! This is just in case we only have a single point, the SIZE command returns the correct number of points. - NumPoints = SIZE(PositionXYZ,2) - - - ! Step through all the positions and get the velocities - !OMP PARALLEL default(shared) if(NumPoints>1000) - !OMP do private(PointNum, TmpErrStat, TmpErrMsg ) schedule(runtime) - DO PointNum = 1, NumPoints - - ! Calculate the velocity for the position - Velocity(:,PointNum) = FFWind_Interp(Time,PositionXYZ(:,PointNum),p,TmpErrStat,TmpErrMsg) - - ! Error handling - IF (TmpErrStat /= ErrID_None) THEN ! adding this so we don't have to convert numbers to strings every time - !OMP CRITICAL ! Needed to avoid data race on ErrStat and ErrMsg - ErrStat = ErrID_None - ErrMsg = "" - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName//" [position=("// & - TRIM(Num2LStr(PositionXYZ(1,PointNum)))//", "// & - TRIM(Num2LStr(PositionXYZ(2,PointNum)))//", "// & - TRIM(Num2LStr(PositionXYZ(3,PointNum)))//") in wind-file coordinates]" ) - !OMP END CRITICAL - END IF - - ENDDO - !OMP END DO - !OMP END PARALLEL - IF (ErrStat >= AbortErrLev) RETURN ! Return cannot be in parallel loop - - IF (p%AddMeanAfterInterp) THEN - DO PointNum = 1, NumPoints - Velocity(1,PointNum) = Velocity(1,PointNum) + CalculateMeanVelocity(p,PositionXYZ(3,PointNum),PositionXYZ(2,PointNum)) - ENDDO - END IF - - - RETURN - -END SUBROUTINE IfW_FFWind_CalcOutput -!+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- -!> This function is used to interpolate into the full-field wind array or tower array if it has -!! been defined and is necessary for the given inputs. It receives X, Y, Z and -!! TIME from the calling routine. It then computes a time shift due to a nonzero X based upon -!! the average windspeed. The modified time is used to decide which pair of time slices to interpolate -!! within and between. After finding the two time slices, it decides which four grid points bound the -!! (Y,Z) pair. It does a bilinear interpolation for each time slice. Linear interpolation is then used -!! to interpolate between time slices. This routine assumes that X is downwind, Y is to the left when -!! looking downwind and Z is up. It also assumes that no extrapolation will be needed. -!! -!! If tower points are used, it assumes the velocity at the ground is 0. It interpolates between -!! heights and between time slices, but ignores the Y input. -!! -!! 11/07/1994 - Created by M. Buhl from the original TURBINT. -!! 09/25/1997 - Modified by M. Buhl to use f90 constructs and new variable names. Renamed to FF_Interp. -!! 09/23/2009 - Modified by B. Jonkman to use arguments instead of modules to determine time and position. -!! Height is now relative to the ground -!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -FUNCTION FFWind_Interp(Time, Position, p, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="FFWind_Interp" - - REAL(DbKi), INTENT(IN ) :: Time !< time (s) - REAL(ReKi), INTENT(IN ) :: Position(3) !< takes the place of XGrnd, YGrnd, ZGrnd - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - REAL(ReKi) :: FFWind_Interp(3) !< The U, V, W velocities - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message - - ! Local Variables: - - REAL(ReKi) :: TimeShifted - REAL(ReKi),PARAMETER :: Tol = 1.0E-3 ! a tolerance for determining if two reals are the same (for extrapolation) - REAL(ReKi) :: T - REAL(ReKi) :: TGRID - REAL(ReKi) :: Y - REAL(ReKi) :: YGRID - REAL(ReKi) :: Z - REAL(ReKi) :: ZGRID - REAL(ReKi) :: N(8) ! array for holding scaling factors for the interpolation algorithm - REAL(ReKi) :: u(8) ! array for holding the corner values for the interpolation algorithm across a cubic volume - REAL(ReKi) :: M(4) ! array for holding scaling factors for the interpolation algorithm - REAL(ReKi) :: v(4) ! array for holding the corner values for the interpolation algorithm across an area - - INTEGER(IntKi) :: IDIM - INTEGER(IntKi) :: ITHI - INTEGER(IntKi) :: ITLO - INTEGER(IntKi) :: IYHI - INTEGER(IntKi) :: IYLO - INTEGER(IntKi) :: IZHI - INTEGER(IntKi) :: IZLO - - LOGICAL :: OnGrid - - !------------------------------------------------------------------------------------------------- - ! Initialize variables - !------------------------------------------------------------------------------------------------- - - FFWind_Interp(:) = 0.0_ReKi ! the output velocities (in case p%NFFComp /= 3 or error) - - ErrStat = ErrID_None - ErrMsg = "" - - - !------------------------------------------------------------------------------------------------- - ! By definition, wind below the ground is always zero (no turbulence, either). - !------------------------------------------------------------------------------------------------- - IF ( Position(3) <= 0.0_ReKi ) THEN - FFWind_Interp = 0.0_ReKi - RETURN - END IF - - - !------------------------------------------------------------------------------------------------- - ! Find the bounding time slices. - !------------------------------------------------------------------------------------------------- - - ! Perform the time shift. At time=0, a point half the grid width downstream (p%FFYHWid) will index into the zero time slice. - ! If we did not do this, any point downstream of the tower at the beginning of the run would index outside of the array. - ! This all assumes the grid width is at least as large as the rotor. If it isn't, then the interpolation will not work. - - - TimeShifted = TIME + ( p%InitXPosition - Position(1) )*p%InvMFFWS ! in distance, X: InputInfo%Position(1) - p%InitXPosition - TIME*p%MeanFFWS - - - IF ( p%Periodic ) THEN ! translate TimeShifted to ( 0 <= TimeShifted < p%TotalTime ) - - TimeShifted = MODULO( TimeShifted, p%TotalTime ) - ! If TimeShifted is a very small negative number, modulo returns the incorrect value due to internal rounding errors. - ! See bug report #471 - IF (TimeShifted == p%TotalTime) TimeShifted = 0.0_ReKi - - TGRID = TimeShifted*p%FFRate - ITLO = INT( TGRID ) ! convert REAL to INTEGER (add 1 later because our grids start at 1, not 0) - T = 2.0_ReKi * ( TGRID - REAL(ITLO, ReKi) ) - 1.0_ReKi ! a value between -1 and 1 that indicates a relative position between ITLO and ITHI - - ITLO = ITLO + 1 - IF ( ITLO == p%NFFSteps ) THEN - ITHI = 1 - ELSE - IF (ITLO > p%NFFSteps) ITLO = 1 - ITHI = ITLO + 1 - ENDIF - - - ELSE - - TGRID = TimeShifted*p%FFRate - ITLO = INT( TGRID ) ! convert REAL to INTEGER (add 1 later because our grids start at 1, not 0) - T = 2.0_ReKi * ( TGRID - REAL(ITLO, ReKi) ) - 1.0_ReKi ! a value between -1 and 1 that indicates a relative position between ITLO and ITHI - - ITLO = ITLO + 1 ! add one since our grids start at 1, not 0 - ITHI = ITLO + 1 - - IF ( ITLO >= p%NFFSteps .OR. ITLO < 1 ) THEN - IF ( ITLO == p%NFFSteps ) THEN - ITHI = ITLO - IF ( T <= TOL ) THEN ! we're on the last point - T = -1.0_ReKi - ELSE ! We'll extrapolate one dt past the last value in the file - ITLO = ITHI - 1 - ENDIF - ELSE - ErrMsg = ' Error: FF wind array was exhausted at '//TRIM( Num2LStr( REAL( TIME, ReKi ) ) )// & - ' seconds (trying to access data at '//TRIM( Num2LStr( REAL( TimeShifted, ReKi ) ) )//' seconds).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ENDIF - - ENDIF - - - !------------------------------------------------------------------------------------------------- - ! Find the bounding rows for the Z position. [The lower-left corner is (1,1) when looking upwind.] - !------------------------------------------------------------------------------------------------- - - ZGRID = ( Position(3) - p%GridBase )*p%InvFFZD - - IF (ZGRID > -1*TOL) THEN - OnGrid = .TRUE. - - ! Index for start and end slices - IZLO = INT( ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - IZHI = IZLO + 1 - - ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. - ! Subtract 1_IntKi from Z since the indices are starting at 1, not 0 - Z = 2.0_ReKi * (ZGRID - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi - - IF ( IZLO < 1 ) THEN - IF ( IZLO == 0 .AND. Z >= 1.0-TOL ) THEN - Z = -1.0_ReKi - IZLO = 1 - ELSE - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& - TRIM(Num2LStr(Position(3)))//' m is below the grid).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ELSEIF ( IZLO >= p%NZGrids ) THEN - IF ( IZLO == p%NZGrids .AND. Z <= TOL ) THEN - Z = -1.0_ReKi - IZHI = IZLO ! We're right on the last point, which is still okay - ELSE - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& - TRIM(Num2LStr(Position(3)))//' m is above the grid).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ENDIF - - ELSE - - OnGrid = .FALSE. ! this is on the tower - - IF (p%InterpTower) then - - ! get Z between ground and bottom of grid - ZGRID = Position(3)/p%GridBase - Z = 2.0_ReKi * ZGRID - 1.0_ReKi - IZHI = 1 - IZLO = 0 - - IF ( ZGRID < 0.0_ReKi ) THEN - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & - '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the ground).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - - ELSE - - IF ( p%NTGrids < 1) THEN - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & - '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - - IZLO = INT( -1.0*ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - - - IF ( IZLO >= p%NTGrids ) THEN !our dz is the difference between the bottom tower point and the ground - IZLO = p%NTGrids - - ! Check that this isn't zero. Value between -1 and 1 corresponding to the relative position. - Z = 1.0_ReKi - 2.0_ReKi * (Position(3) / (p%GridBase - REAL(IZLO - 1_IntKi, ReKi)/p%InvFFZD)) - - ELSE - - ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. Used in the interpolation. - Z = 2.0_ReKi * (ABS(ZGRID) - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi - - ENDIF - IZHI = IZLO + 1 - - ENDIF - - END IF - - IF ( OnGrid ) THEN ! The tower points don't use this - - CALL GetInterpValues(); if (ErrStat/=ErrID_None) return - - !------------------------------------------------------------------------------------------------- - ! Interpolate on the grid - !------------------------------------------------------------------------------------------------- - - DO IDIM=1,p%NFFComp ! all the components - - u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) - u(2) = p%FFData( IZHI, IYHI, IDIM, ITLO ) - u(3) = p%FFData( IZLO, IYHI, IDIM, ITLO ) - u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) - u(5) = p%FFData( IZHI, IYLO, IDIM, ITHI ) - u(6) = p%FFData( IZHI, IYHI, IDIM, ITHI ) - u(7) = p%FFData( IZLO, IYHI, IDIM, ITHI ) - u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) - - FFWind_Interp(IDIM) = SUM ( N * u ) - - END DO !IDIM - - ELSE - - IF (p%InterpTower) THEN - - CALL GetInterpValues(); if (ErrStat >= AbortErrLev) return - - !------------------------------------------------------------------------------------------------- - ! Interpolate on the bottom of the grid to the ground - !------------------------------------------------------------------------------------------------- - - DO IDIM=1,p%NFFComp ! all the components - - u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) - u(2) = p%FFData( IZHI, IYHI, IDIM, ITLO ) - u(3) = 0.0_ReKi !p%FFData( IZLO, IYHI, IDIM, ITLO ) - u(4) = 0.0_ReKi !p%FFData( IZLO, IYLO, IDIM, ITLO ) - u(5) = p%FFData( IZHI, IYLO, IDIM, ITHI ) - u(6) = p%FFData( IZHI, IYHI, IDIM, ITHI ) - u(7) = 0.0_ReKi !p%FFData( IZLO, IYHI, IDIM, ITHI ) - u(8) = 0.0_ReKi !p%FFData( IZLO, IYLO, IDIM, ITHI ) - - FFWind_Interp(IDIM) = SUM ( N * u ) - - END DO !IDIM - - ELSE - - !------------------------------------------------------------------------------------------------- - ! Interpolate on the tower array - !------------------------------------------------------------------------------------------------- - ! Setup the scaling factors. Set the unused portion of the array to zero - M(1) = ( 1.0_ReKi + Z )*( 1.0_ReKi - T ) - M(2) = ( 1.0_ReKi + Z )*( 1.0_ReKi + T ) - M(3) = ( 1.0_ReKi - Z )*( 1.0_ReKi - T ) - M(4) = ( 1.0_ReKi - Z )*( 1.0_ReKi + T ) - M = M / 4.0_ReKi ! normalize - - - DO IDIM=1,p%NFFComp ! all the components - - !---------------------------------------------------------------------------------------------- - ! Interpolate between the two times using an area interpolation. - !---------------------------------------------------------------------------------------------- - - IF (IZHI > p%NTGrids) THEN - v(1) = 0.0_ReKi ! on the ground - v(2) = 0.0_ReKi ! on the ground - ELSE - v(1) = p%FFTower( IDIM, IZHI, ITLO ) - v(2) = p%FFTower( IDIM, IZHI, ITHI ) - END IF - - v(3) = p%FFTower( IDIM, IZLO, ITLO ) - v(4) = p%FFTower( IDIM, IZLO, ITHI ) - - FFWind_Interp(IDIM) = SUM ( M * v ) - - - END DO !IDIM - - END IF ! Interpolate below the grid - - ENDIF ! OnGrid - RETURN - -CONTAINS - SUBROUTINE GetInterpValues() - - !------------------------------------------------------------------------------------------------- - ! Find the bounding columns for the Y position. [The lower-left corner is (1,1) when looking upwind.] - !------------------------------------------------------------------------------------------------- - - YGRID = ( Position(2) + p%FFYHWid )*p%InvFFYD ! really, it's (Position(2) - -1.0*p%FFYHWid) - - IYLO = INT( YGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - IYHI = IYLO + 1 - - ! Set Y as a value between -1 and 1 for the relative location between IYLO and IYHI. Used in the interpolation. - ! Subtract 1_IntKi from IYLO since grids start at index 1, not 0 - Y = 2.0_ReKi * (YGRID - REAL(IYLO - 1_IntKi, ReKi)) - 1.0_ReKi - - IF ( IYLO >= p%NYGrids .OR. IYLO < 1 ) THEN - IF ( IYLO == 0 .AND. Y >= 1.0-TOL ) THEN - Y = -1.0_ReKi - IYLO = 1 - ELSE IF ( IYLO == p%NYGrids .AND. Y <= TOL ) THEN - Y = -1.0_ReKi - IYHI = IYLO ! We're right on the last point, which is still okay - ELSE - ErrMsg = ' FF wind array boundaries violated: Grid too small in Y direction. Y='// & - TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*p%FFYHWid))// & - ', '//TRIM(Num2LStr(p%FFYHWid))//']' - ErrStat = ErrID_Fatal ! we don't return anything - RETURN - ENDIF - ENDIF - - !------------------------------------------------------------------------------------------------- - ! Get normalization values for 3d-linear interpolation on the grid - !------------------------------------------------------------------------------------------------- - -!New Algorithm here - N(1) = ( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) - N(2) = ( 1.0_ReKi + Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) - N(3) = ( 1.0_ReKi - Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) - N(4) = ( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) - N(5) = ( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) - N(6) = ( 1.0_ReKi + Z )*( 1.0_ReKi + Y )*( 1.0_ReKi + T ) - N(7) = ( 1.0_ReKi - Z )*( 1.0_ReKi + Y )*( 1.0_ReKi + T ) - N(8) = ( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) - N = N / REAL( SIZE(N), ReKi ) ! normalize - - END SUBROUTINE GetInterpValues -END FUNCTION FFWind_Interp -!==================================================================================================== -!> This routine is used read scale the full-field turbulence data stored in HAWC format. -SUBROUTINE ScaleTurbulence(InitInp, FFData, ScaleFactors, ErrStat, ErrMsg) - - ! Passed Variables - TYPE(IfW_FFWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization input data passed to the module - REAL(SiKi), INTENT(INOUT) :: FFData(:,:,:,:) !< full-field wind inflow data - REAL(ReKi), INTENT( OUT) :: ScaleFactors(3) !< scaling factors that were used - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - ! Local Variables: - ! note that the variables used to compute statistics use double precision: - REAL(DbKi) :: v(3) ! instanteanous wind speed at target position - REAL(DbKi) :: vMean(3) ! average wind speeds over time at target position - REAL(DbKi) :: vSum(3) ! sum over time of wind speeds at target position - REAL(DbKi) :: vSum2(3) ! sum of wind speeds squared - REAL(ReKi) :: ActualSigma(3) ! computed standard deviation - - INTEGER :: ic ! Loop counter for wind component - INTEGER :: ix ! Loop counter for x or t - INTEGER :: iy ! Loop counter for y - INTEGER :: iz ! Loop counter for z - - INTEGER :: nc ! number of FF wind components - INTEGER :: nx ! size of x (or t) dimension of turbulence box - INTEGER :: ny ! size of y dimension of turbulence box - INTEGER :: nz ! size of z dimension of turbulence box - - CHARACTER(*), PARAMETER :: RoutineName = 'ScaleTurbulence' - - - - ErrStat = ErrID_None - ErrMsg = "" - - nz = size(FFData,1) - ny = size(FFData,2) - nc = size(FFData,3) - nx = size(FFData,4) - - if ( InitInp%ScaleMethod == ScaleMethod_None ) then - - ! don't scale FFWind: - ScaleFactors = 1.0_ReKi - - else ! ScaleMethod_Direct or ScaleMethod_StdDev - - !.............................. - ! determine the scaling factors: - !.............................. - - if ( InitInp%ScaleMethod == ScaleMethod_Direct ) then - ! Use the scaling factors specified in the input file: - ScaleFactors = InitInp%sf - - else !if ( InitInp%ScaleMethod == ScaleMethod_StdDev ) then - ! compute the scale factor to get requested sigma: - - ! find the center point of the grid (if we don't have an odd number of grid points, we'll pick the point closest to the center) - iz = (nz + 1) / 2 ! integer division - iy = (ny + 1) / 2 ! integer division - - ! compute the actual sigma at the point specified by (iy,iz). (This sigma should be close to 1.) - v = 0.0_ReKi - vSum = 0.0_ReKi - vSum2 = 0.0_ReKi - DO ix=1,nx - v(1:nc) = FFData(iz,iy,:,ix) - - vSum = vSum + v - vSum2 = vSum2 + v**2 - ENDDO ! IX - - vMean = vSum/nx - ActualSigma = SQRT( ABS( (vSum2/nx) - vMean**2 ) ) - - ! check that the ActualSigma isn't 0 - !InitOut%sf = InitInp%SigmaF / ActualSigma ! factor = Target / actual - do ic=1,nc - if ( EqualRealNos( ActualSigma(ic), 0.0_ReKi ) ) then - ScaleFactors(ic) = 0.0_ReKi - if ( .not. EqualRealNos( InitInp%SigmaF(ic), 0.0_ReKi ) ) then - call SetErrStat( ErrID_Fatal,"Computed standard deviation is zero; cannot scale to achieve target non-zero standard deviation.", ErrStat, ErrMsg, RoutineName ) - end if - else - ScaleFactors(ic) = InitInp%SigmaF(ic) / ActualSigma(ic) - end if - end do - - end if - - !.............................. - ! scale the data using our scaling factors: - !.............................. - - do ix=1,nx - do ic = 1,nc - FFData( :, :, ic, ix ) = ScaleFactors(ic) * FFData( :, :, ic, ix ) - end do !IC - end do - - end if - -END SUBROUTINE ScaleTurbulence -!==================================================================================================== -!> This routine is used to add a mean wind profile to the HAWC format turbulence data. -SUBROUTINE AddMeanVelocity(InitInp, GridBase, dz, dy, FFData) - - ! Passed Variables - TYPE(IfW_FFWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization input data passed to the module - REAL(ReKi), INTENT(IN ) :: GridBase !< height of the lowest point on the grid - REAL(ReKi), INTENT(IN ) :: dz !< distance between two zertically consectutive grid points - REAL(ReKi), INTENT(IN ) :: dy !< distance between two horizontal consectutive grid points - REAL(SiKi), INTENT(INOUT) :: FFData(:,:,:,:) !< FF wind-inflow data - - ! Local Variables: - REAL(ReKi) :: Z ! height - REAL(ReKi) :: Y ! distance from centre in horizontal direction - REAL(ReKi) :: U ! mean wind speed - INTEGER(IntKi) :: iz ! loop counter - INTEGER(IntKi) :: iy ! loop counter - INTEGER(IntKi) :: nz ! number of points in the z direction - INTEGER(IntKi) :: ny ! number of points in the z direction - INTEGER(IntKi) :: centre_y ! index of centre in y direction - - - nz = size(FFData,1) - - DO iz = 1,nz - - Z = GridBase + ( iz - 1 )*dz - if (Z <= 0.0_ReKi) cycle - - SELECT CASE ( InitInp%WindProfileType ) - - CASE ( WindProfileType_PL ) - - U = InitInp%URef*( Z / InitInp%RefHt )**InitInp%PLExp ! [IEC 61400-1 6.3.1.2 (10)] - - CASE ( WindProfileType_Log ) - - IF ( .not. EqualRealNos( InitInp%RefHt, InitInp%Z0 ) .and. Z > 0.0_ReKi ) THEN - U = InitInp%URef*( LOG( Z / InitInp%Z0 ) )/( LOG( InitInp%RefHt / InitInp%Z0 ) ) - ELSE - U = 0.0_ReKi - ENDIF - - CASE ( WindProfileType_Constant ) - - U = InitInp%URef - - CASE DEFAULT - - U = 0.0_ReKi - - END SELECT - - IF (InitInp%VLinShr .NE. 0.0_ReKi) THEN ! Add vertical linear shear, if has - U = U + InitInp%URef * InitInp%VLinShr * (Z - InitInp%RefHt) / InitInp%RefLength - ENDIF - - FFData( iz, :, 1, : ) = FFData( iz, :, 1, : ) + U - - END DO ! iz - - IF (InitInp%HLinShr .NE. 0.0_ReKi) THEN ! Add horizontal linear shear, if has - ny = size(FFData,2) - ! find the center point of the grid (if we don't have an odd number of grid points, we'll pick the point closest to the center) - centre_y = (ny + 1) / 2 ! integer division - DO iy = 1,ny - - Y = (iy - centre_y) * dy - - U = InitInp%URef * InitInp%HLinShr * Y / InitInp%RefLength - - FFData( :, iy, 1, : ) = FFData( :, iy, 1, : ) + U - - END DO ! iy - ENDIF ! IF InitInp%HLinShr - - -END SUBROUTINE AddMeanVelocity -!==================================================================================================== -FUNCTION CalculateMeanVelocity(p,z,y) RESULT(u) - - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - REAL(ReKi) , INTENT(IN ) :: Z ! height - REAL(ReKi) , INTENT(IN ) :: y ! lateral location - REAL(ReKi) :: u ! mean wind speed at position (y,z) - - SELECT CASE ( p%WindProfileType ) - - CASE ( WindProfileType_PL ) - - U = p%MeanFFWS*( Z / p%RefHt )**p%PLExp ! [IEC 61400-1 6.3.1.2 (10)] - - CASE ( WindProfileType_Log ) - - IF ( .not. EqualRealNos( p%RefHt, p%Z0 ) .and. Z > 0.0_ReKi ) THEN - U = p%MeanFFWS*( LOG( Z / p%Z0 ) )/( LOG( p%RefHt / p%Z0 ) ) - ELSE - U = 0.0_ReKi - ENDIF - - CASE ( WindProfileType_Constant ) - - U = p%MeanFFWS - - CASE DEFAULT - - U = 0.0_ReKi - - END SELECT - - - IF (p%VLinShr .NE. 0.0_ReKi) THEN ! Add vertical linear shear, if has - U = U + p%MeanFFWS * p%VLinShr * (Z - p%RefHt) / p%RefLength - ENDIF - - - IF (p%HLinShr .NE. 0.0_ReKi) THEN ! Add horizontal linear shear, if has - U = U + p%MeanFFWS * p%HLinShr * y / p%RefLength - ENDIF - -END FUNCTION CalculateMeanVelocity -!==================================================================================================== -!> This routine is used to add a subtract the mean wind speed from turbulence data (so that the added mean can be added later). -!! Note that this does NOT scale using the length of the wind simulation, so there may be differences with the HAWC implementation. -SUBROUTINE SubtractMeanVelocity(FFData) - - ! Passed Variables - REAL(SiKi), INTENT(INOUT) :: FFData(:,:,:,:) !< FF wind-inflow data - - ! Local Variables: - REAL(ReKi) :: MeanVal ! computed mean wind speed - INTEGER(IntKi) :: ic ! loop counter - INTEGER(IntKi) :: iy ! loop counter - INTEGER(IntKi) :: iz ! loop counter - INTEGER(IntKi) :: nt ! number of points in the x (time) direction - - - nt = size(FFData,4) - - DO ic = 1,1 !size(FFData,3) - DO iy = 1,size(FFData,2) - DO iz = 1,size(FFData,1) - meanVal = sum(FFData(iz,iy,ic,:)) / nt - - FFData( iz,iy,ic,: ) = FFData( iz,iy,ic,: ) - meanVal - END DO ! iz - END DO ! iy - END DO ! ic - - -END SUBROUTINE SubtractMeanVelocity -!==================================================================================================== -!> This routine is used to make sure the initInp data is valid. -SUBROUTINE FFWind_ValidateInput(InitInp, nffc, ErrStat, ErrMsg) - - ! Passed Variables - TYPE(IfW_FFWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization input data passed to the module - INTEGER(IntKi), INTENT(IN ) :: nffc !< number of full-field wind components (normally 3) - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - character(*), parameter :: RoutineName = 'FFWind_ValidateInput' - - integer(intki) :: ic ! loop counter - - ErrStat = ErrID_None - ErrMsg = "" - - IF ( InitInp%RefHt < 0.0_ReKi .or. EqualRealNos( InitInp%RefHt, 0.0_ReKi ) ) call SetErrStat( ErrID_Fatal, 'The grid reference height must be larger than 0.', ErrStat, ErrMsg, RoutineName ) - - if ( InitInp%ScaleMethod == ScaleMethod_Direct) then - do ic=1,nffc - if ( InitInp%sf(ic) < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'Turbulence scaling factors must not be negative.', ErrStat, ErrMsg, RoutineName ) - end do - elseif ( InitInp%ScaleMethod == ScaleMethod_StdDev ) then - do ic=1,nffc - if ( InitInp%sigmaf(ic) < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'Turbulence standard deviations must not be negative.', ErrStat, ErrMsg, RoutineName ) - end do -#ifdef UNUSED_INPUTFILE_LINES - if ( InitInp%TStart < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TStart for turbulence standard deviation calculations must not be negative.', ErrStat, ErrMsg, RoutineName ) - if ( InitInp%TEnd <= InitInp%TStart ) CALL SetErrStat( ErrID_Fatal, 'TEnd for turbulence standard deviation calculations must be after TStart.', ErrStat, ErrMsg, RoutineName ) -#endif - elseif ( InitInp%ScaleMethod /= ScaleMethod_None ) then - CALL SetErrStat( ErrID_Fatal, 'Turbulence scaling method must be 0 (none), 1 (direct scaling factors), or 2 (target standard deviation).', ErrStat, ErrMsg, RoutineName ) - end if - - - if (InitInp%WindProfileType == WindProfileType_Log) then - if ( InitInp%z0 < 0.0_ReKi .or. EqualRealNos( InitInp%z0, 0.0_ReKi ) ) & - call SetErrStat( ErrID_Fatal, 'The surface roughness length, Z0, must be greater than zero', ErrStat, ErrMsg, RoutineName ) - elseif ( InitInp%WindProfileType < WindProfileType_Constant .or. InitInp%WindProfileType > WindProfileType_PL) then - call SetErrStat( ErrID_Fatal, 'The WindProfile type must be 0 (constant), 1 (logarithmic) or 2 (power law).', ErrStat, ErrMsg, RoutineName ) - end if - - IF ( InitInp%URef < 0.0_ReKi ) call SetErrStat( ErrID_Fatal, 'The reference wind speed must not be negative.', ErrStat, ErrMsg, RoutineName ) - - IF ( EqualRealNos(InitInp%RefLength, 0.0_ReKi) .or. InitInp%RefLength < 0.0_ReKi ) THEN - IF (InitInp%VLinShr /= 0.0_ReKi .OR. InitInp%HLinShr /= 0.0_ReKi) THEN - call SetErrStat( ErrID_Fatal, 'The reference length must be a positive number when vertical or horizontal linear shear is used.', ErrStat, ErrMsg, RoutineName ) - END IF - END IF - -END SUBROUTINE FFWind_ValidateInput -!==================================================================================================== -SUBROUTINE ConvertFFWind_to_HAWC2(FileRootName, p, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - REAL(SiKi) :: delta(3) - - delta(1) = p%MeanFFWS * p%FFDTime - delta(2) = 1.0_SiKi / p%InvFFYD - delta(3) = 1.0_SiKi / p%InvFFZD - - CALL WrBinHAWC(FileRootName, p%FFData(:,:,:,1:p%NFFSteps), delta, ErrStat, ErrMsg) - - IF (.NOT. p%Periodic) THEN - call SetErrStat( ErrID_Severe, 'File converted to HAWC format is not periodic. Jumps may occur in resulting simulation.', & - ErrStat, ErrMsg, 'ConvertFFWind_to_HAWC2') - END IF - -END SUBROUTINE ConvertFFWind_to_HAWC2 -!==================================================================================================== -SUBROUTINE ConvertFFWind_to_Bladed(FileRootName, p, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - REAL(SiKi) :: delta(3) - - delta(1) = p%MeanFFWS * p%FFDTime - delta(2) = 1.0_SiKi / p%InvFFYD - delta(3) = 1.0_SiKi / p%InvFFZD - - CALL WrBinBladed(FileRootName, p%FFData(:,:,:,1:p%NFFSteps), delta, p%MeanFFWS, p%RefHt, p%GridBase, p%Periodic, p%AddMeanAfterInterp, ErrStat, ErrMsg) - -END SUBROUTINE ConvertFFWind_to_Bladed -!================================================================================================================================== -SUBROUTINE WrBinHAWC(FileRootName, FFWind, delta, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN) :: FileRootName !< Name of the file to write the output in - REAL(SiKi), INTENT(IN) :: FFWind(:,:,:,:) !< 4D wind speeds: index 1=z (height), 2=y (lateral), 3=dimension(u,v,w), 4=time or x - REAL(SiKi), INTENT(IN) :: delta(3) !< array containing dx, dy, dz in meters - INTEGER(IntKi), INTENT(OUT):: ErrStat !< Indicates whether an error occurred (see NWTC_Library) - CHARACTER(*), INTENT(OUT):: ErrMsg !< Error message associated with the ErrStat - - ! local variables - CHARACTER(*), PARAMETER :: Comp(3) = (/'u','v','w'/) - INTEGER(IntKi), PARAMETER :: AryDim(3) = (/4, 2, 1/) ! x,y,z dimensions of FFWind array - INTEGER(IntKi) :: nc - INTEGER(IntKi) :: IC, IX, IY, IZ - INTEGER(IntKi) :: UnWind - !REAL(SiKi) :: MeanVal(size(FFWind,1),size(FFWind,2)) - REAL(SiKi) :: MeanVal(size(FFWind,1)) - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'WrBinHAWC' - CHARACTER(1024) :: RootWithoutPathName - - ErrStat = ErrID_None - ErrMsg = "" - - CALL GetNewUnit( UnWind, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - nc = size(FFWind,3) ! check that nc == 3 ???? - - ! need to remove time-average value from DIM=1 - MeanVal = 0.0_SiKi - DO IX = 1,size(FFWind,4) - MeanVal = MeanVal + FFWind(:,1,1,ix) - END DO - MeanVal = MeanVal / size(FFWind,4) - - - ! write the summary file - CALL OpenFOutFile ( UnWind, trim(FileRootName)//'-HAWC.sum', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - WRITE( UnWind, '(A)' ) '; Wind file converted to HAWC format on '//CurDate()//' at '//CurTime() - - WRITE( UnWind, '()' ) - DO IZ = size(FFWind,AryDim(3)),1,-1 - WRITE( UnWind, '(A,I3,A,F15.5)' ) '; mean removed at z(', iz, ') = ', MeanVal(iz) - END DO - - WRITE( UnWind, '(A)' ) 'turb_format 1 ;' -! WRITE( UnWind, '(A)' ) 'center_pos0 0.0 0.0 '//trim(num2lstr( ';' - - WRITE( UnWind, '()' ) - WRITE( UnWind, '(A)' ) 'begin mann;' - - ic = INDEX( FileRootName, '\', BACK=.TRUE. ) - ic = MAX( ic, INDEX( FileRootName, '/', BACK=.TRUE. ) ) - RootWithoutPathName = FileRootName((ic+1):) - - - DO IC = 1,nc - WRITE( UnWind, '(2x,A, T30, A, " ;")' ) 'filename_'//Comp(IC), trim(RootWithoutPathName)//'-HAWC-'//Comp(IC)//'.bin' - END DO - DO IC = 1,nc - WRITE( UnWind, '(2x,A, T30, I8, 1x, F15.5, " ;")' ) 'box_dim_'//Comp(IC), size( FFWind, AryDim(ic) ), delta(ic) - END DO - WRITE( UnWind, '(2x,A)' ) 'dont_scale 1; converter did not rescale turbulence to unit standard deviation' - WRITE( UnWind, '(A)' ) 'end mann;' - CLOSE ( UnWind ) - - - ! write the binary files for each component - - DO IC = 1,nc - - CALL OpenBOutFile ( UnWind, trim(FileRootName)//'-HAWC-'//Comp(ic)//'.bin', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - DO IX = 1,size(FFWind,AryDim(1)) - DO IY = size(FFWind,AryDim(2)),1,-1 - WRITE( UnWind, IOSTAT=ErrStat2 ) FFWind(:,iy,ic,ix) - MeanVal(:) ! note that FFWind is SiKi (4-byte reals, not default kinds) - END DO - END DO - - CLOSE ( UnWind ) - - MeanVal = 0.0_SiKi - - END DO - -END SUBROUTINE WrBinHAWC -!================================================================================================================================== -SUBROUTINE WrBinBladed(FileRootName, FFWind, delta, MeanFFWS, HubHt, GridBase, Periodic, AddMeanAfterInterp, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN) :: FileRootName !< Name of the file to write the output in - REAL(SiKi), INTENT(IN) :: FFWind(:,:,:,:) !< 4D wind speeds: index 1=z (height), 2=y (lateral), 3=dimension(u,v,w), 4=time or x - REAL(SiKi), INTENT(IN) :: delta(3) !< array containing dx, dy, dz in meters - REAL(ReKi), INTENT(IN) :: MeanFFWS !< advection speed (mean wind speed at hub) - REAL(ReKi), INTENT(IN) :: HubHt !< hub height - REAL(ReKi), INTENT(IN) :: GridBase !< height of lowest grid point - LOGICAL, INTENT(IN) :: Periodic !< whether this wind file is periodic - LOGICAL, INTENT(IN) :: AddMeanAfterInterp !< whether this wind file contains a mean longditudinal wind speed - INTEGER(IntKi), INTENT(OUT):: ErrStat !< Indicates whether an error occurred (see NWTC_Library) - CHARACTER(*), INTENT(OUT):: ErrMsg !< Error message associated with the ErrStat - - ! local variables - INTEGER(IntKi), PARAMETER :: AryDim(3) = (/4, 2, 1/) ! x,y,z dimensions of FFWind array - INTEGER(IntKi) :: ic, it, iy, iz - INTEGER(IntKi) :: UnWind - REAL(SiKi) :: MeanVal(size(FFWind,1),size(FFWind,2)) - REAL(SiKi) :: SigmaGrid( size(FFWind,1),size(FFWind,2)) - REAL(SiKi) :: TI(3) !< array containing turbulence intensity (for scaling factors) - REAL(SiKi) :: Sigma(3) !< array containing standard deviations (for scaling factors) - REAL(SiKi) :: Scl(3) !< array containing scaling factors - REAL(SiKi) :: Off(3) !< array containing offsets - REAL(SiKi) :: Tmp - REAL(ReKi) :: MeanFFWS_nonZero !< advection speed (mean wind speed at hub) - - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'WrBinBladed' - - REAL(SiKi), PARAMETER :: Tolerance = 0.0001 ! The largest difference between two numbers that are assumed to be equal - - - ErrStat = ErrID_None - ErrMsg = "" - - !----------------------------------------------------- - ! Calculate the stats - !----------------------------------------------------- - - do ic=3,1,-1 - - ! mean values: - MeanVal = 0.0_SiKi - DO it = 1,size(FFWind,AryDim(1)) - MeanVal = MeanVal + FFWind(:,:,ic,it) - END DO - MeanVal = MeanVal / real( size(FFWind,AryDim(1)), SiKi) - - ! standard deviations (with 1/N scaling factor): - SigmaGrid = 0.0_SiKi - DO it = 1,size(FFWind,4) - SigmaGrid = SigmaGrid + FFWind(:,:,ic,it)**2 - END DO - SigmaGrid = SigmaGrid / size(FFWind,AryDim(1)) - SigmaGrid = SQRT( MAX( SigmaGrid - MeanVal**2, 0.0_SiKi ) ) - - ! now get the average standard deviation for each component: - Sigma(ic) = sum(SigmaGrid)/size(SigmaGrid) ! get the average sigma over the grid - Sigma(ic) = MAX(100.0_SiKi*Tolerance, Sigma(ic)) ! make sure this scaling isn't too small - - end do - - ! We need to take into account the shear across the grid in the sigma calculations for scaling the data, - ! and ensure that 32.767*sigma_u >= |V-UHub| so that we don't get values out of the range of our scaling values - ! in this BLADED-style binary output. Tmp is |V-UHub| - Tmp = MAX( ABS(MAXVAL(FFWind(:,:,1,:))-MeanFFWS), ABS(MINVAL(FFWind(:,:,1,:))-MeanFFWS) ) !Get the range of wind speed values for scaling in BLADED-format .wnd files - Sigma(1) = MAX(Sigma(1),0.05_SiKi*Tmp) - do ic=2,3 - Sigma(ic) = MAX( Sigma(ic), 0.05_SiKi*ABS(MAXVAL(FFWind(:,:,ic,:))), 0.05_SiKi*ABS(MINVAL(FFWind(:,:,ic,:))) ) ! put the abs() after the maxval() and minval() to avoid stack-overflow issues with large wind files - end do - - ! Put normalizing factors into the summary file. The user can use them to - ! tell a simulation program how to rescale the data. - - if ( abs(MeanFFWS) < 0.1_ReKi ) then - MeanFFWS_nonZero = sign( 0.1, MeanFFWS ) - else - MeanFFWS_nonZero = MeanFFWS - end if - - TI = Sigma / MeanFFWS_nonZero - - !----------------------------------------------------- - ! The summary file - !----------------------------------------------------- - CALL GetNewUnit( UnWind, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - CALL OpenFOutFile ( UnWind, trim(FileRootName)//'-Bladed.sum', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - !The string "TurbSim" needs to be in the 2nd line of the summary file if AeroDyn will read this. - WRITE( UnWind,"( / 'TurbSim - This summary file was generated by ', A, ' on ' , A , ' at ' , A , '.' / )") "NWTC_Library", CurDate(), CurTime() - WRITE( UnWind, '(/)' ) - WRITE( UnWind, '(/)' ) - WRITE( UnWind, '( L10, 2X, "Clockwise rotation when looking downwind?")' ) .FALSE. - WRITE( UnWind, '( F10.3, 2X, "Hub height [m]")' ) HubHt - WRITE( UnWind, '( F10.3, 2X, "Grid height [m]")' ) delta(3)*(size(FFWind,AryDim(3)) - 1) - WRITE( UnWind, '( F10.3, 2X, "Grid width [m]")' ) delta(2)*(size(FFWind,AryDim(2)) - 1) - WRITE( UnWind, '(/"BLADED-style binary scaling parameters:"/)' ) - WRITE( UnWind, '( 2X, "UBar = ", F9.4, " m/s")' ) MeanFFWS_nonZero - WRITE( UnWind, '( 2X, "TI(u) = ", F9.4, " %")' ) 100.0*TI(1) - WRITE( UnWind, '( 2X, "TI(v) = ", F9.4, " %")' ) 100.0*TI(2) - WRITE( UnWind, '( 2X, "TI(w) = ", F9.4, " %")' ) 100.0*TI(3) - WRITE( UnWind, '(/)' ) - WRITE( UnWind, '( 2X, "Height offset = ", F9.4, " m" )' ) HubHt - 0.5*delta(3)*(size(FFWind,AryDim(3)) - 1) - GridBase ! This will be zero for square grids - ! ZGOffset = ( HubHt - delta(3)*(size(FFWind,1) - 1) / 2.0 - Zbottom ) - WRITE( UnWind, '( 2X, "Grid Base = ", F9.4, " m" )' ) GridBase - if (Periodic) then - WRITE (UnWind,'()' ) - WRITE (UnWind,'( A)' ) 'Creating a PERIODIC output file.' - end if - WRITE (UnWind,'( A)' ) 'Creating a BLADED LEFT-HAND RULE output file.' - - - CLOSE (UnWind) - - !----------------------------------------------------- - ! The BINARY file - !----------------------------------------------------- - CALL OpenBOutFile ( UnWind, TRIM(FileRootName)//'-Bladed.wnd', ErrStat, ErrMsg ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - WRITE (UnWind) INT( -99 , B2Ki ) ! -99 = New Bladed format - WRITE (UnWind) INT( 4 , B2Ki ) ! 4 = improved von karman (not used, but needed for next 7 inputs) - WRITE (UnWind) INT( size(FFWind,3) , B4Ki ) ! size(FFWind,3) = 3 = number of wind components - WRITE (UnWind) REAL( 45.0_SiKi , SiKi ) ! Latitude (degrees) (informational, not used in FAST) - WRITE (UnWind) REAL( 0.03_SiKi , SiKi ) ! Roughness length (m) (informational, not used in FAST) - WRITE (UnWind) REAL( HubHt , SiKi ) ! Reference Height (m) (informational, not used in FAST) - WRITE (UnWind) REAL( 100.0*TI(1) , SiKi ) ! Longitudinal turbulence intensity (%) - WRITE (UnWind) REAL( 100.0*TI(2) , SiKi ) ! Lateral turbulence intensity (%) - WRITE (UnWind) REAL( 100.0*TI(3) , SiKi ) ! Vertical turbulence intensity (%) - - WRITE (UnWind) REAL( delta(3) , SiKi ) ! grid spacing in vertical direction, in m - WRITE (UnWind) REAL( delta(2) , SiKi ) ! grid spacing in lateral direction, in m - WRITE (UnWind) REAL( delta(1) , SiKi ) ! grid spacing in longitudinal direciton, in m - WRITE (UnWind) INT( size(FFWind,AryDim(1))/2 , B4Ki ) ! half the number of points in alongwind direction - WRITE (UnWind) REAL( MeanFFWS_nonZero , SiKi ) ! the mean wind speed in m/s - WRITE (UnWind) REAL( 0 , SiKi ) ! the vertical length scale of the longitudinal component in m - WRITE (UnWind) REAL( 0 , SiKi ) ! the lateral length scale of the longitudinal component in m - WRITE (UnWind) REAL( 0 , SiKi ) ! the longitudinal length scale of the longitudinal component in m - WRITE (UnWind) INT( 0 , B4Ki ) ! an unused integer - WRITE (UnWind) INT( 0 , B4Ki ) ! the random number seed - WRITE (UnWind) INT( size(FFWind,AryDim(3)) , B4Ki ) ! the number of grid points vertically - WRITE (UnWind) INT( size(FFWind,AryDim(2)) , B4Ki ) ! the number of grid points laterally - WRITE (UnWind) INT( 0 , B4Ki ) ! the vertical length scale of the lateral component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the lateral length scale of the lateral component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the longitudinal length scale of the lateral component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the vertical length scale of the vertical component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the lateral length scale of the vertical component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the longitudinal length scale of the vertical component, not used - - ! Scaling value to convert wind speeds to 16-bit integers - do ic = 1,3 - if (.not. EqualRealNos( Sigma(ic), 0.0_SiKi ) ) then - Scl(ic) = 1000.0/( Sigma(ic) ) - else - Scl(ic) = 1.0_SiKi - end if - end do - Scl(2) = -Scl(2) ! Bladed convention is positive V is pointed along negative Y (IEC turbine coordinate) - - ! Offset value to convert wind speeds to 16-bit integers - IF (AddMeanAfterInterp) THEN ! Note that this will not take into account any shear!!! - Off(1) = 0.0 - ELSE - Off(1) = MeanFFWS * Scl(1) - END IF - Off(2) = 0.0 - Off(3) = 0.0 - - DO it=1,size(FFWind,AryDim(1)) - DO iz=1,size(FFWind,AryDim(3)) ! 1=bottom of grid - DO iy=1,size(FFWind,AryDim(2)) ! 1=left of grid, i.e. y(1) = -GridWidth/2 - - ! Scale velocity for 16-bit integers: - WRITE ( UnWind ) NINT( FFWind(iz,iy,:,it) * Scl - Off , B2Ki ) ! scale to int16 - - ENDDO !IY - ENDDO !IZ - ENDDO !IT - - CLOSE( UnWind ) - - -END SUBROUTINE WrBinBladed -!==================================================================================================== -SUBROUTINE ConvertFFWind_toVTK(FileRootName, p, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - CHARACTER(1024) :: RootPathName - CHARACTER(1024) :: FileName - INTEGER :: UnWind - INTEGER :: i - INTEGER :: iy - INTEGER :: iz - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'ConvertFFWind_toVTK' - - - CALL GetPath ( FileRootName, RootPathName ) - CALL GetNewUnit( UnWind, ErrStat, ErrMsg ) - - do i = 1,p%NFFSteps - - ! Create the output vtk file with naming /vtk/DisYZ.t.vtk - - RootPathName = trim(RootPathName)//PathSep//"vtk" - call MkDir( trim(RootPathName) ) ! make this directory if it doesn't already exist - - !FileName = trim(RootPathName)//PathSep//"vtk"//PathSep//"DisYZ.t"//trim(num2lstr(i))//".vtp" - FileName = trim(RootPathName)//PathSep//"DisYZ.t"//trim(num2lstr(i))//".vtp" - - ! see WrVTK_SP_header - CALL OpenFOutFile ( UnWind, TRIM(FileName), ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - if (ErrStat >= AbortErrLev) return - - WRITE(UnWind,'(A)') '# vtk DataFile Version 3.0' - WRITE(UnWind,'(A)') "InflowWind YZ Slice at T= "//trim(num2lstr((i-1)*p%FFDTime))//" s" - WRITE(UnWind,'(A)') 'ASCII' - WRITE(UnWind,'(A)') 'DATASET STRUCTURED_POINTS' - - ! Note: gridVals must be stored such that the left-most dimension is X and the right-most dimension is Z - ! see WrVTK_SP_vectors3D() - WRITE(UnWind,'(A,3(i5,1X))') 'DIMENSIONS ', 1, p%NYGrids, p%NZGrids - WRITE(UnWind,'(A,3(f10.2,1X))') 'ORIGIN ' , p%InitXPosition, -p%FFYHWid, p%GridBase - WRITE(UnWind,'(A,3(f10.2,1X))') 'SPACING ' , 0.0_ReKi, 1.0_SiKi / p%InvFFYD, 1.0_SiKi / p%InvFFZD - WRITE(UnWind,'(A,i5)') 'POINT_DATA ', p%NYGrids*p%NZGrids - WRITE(UnWind,'(A)') 'VECTORS DisYZ float' - - DO iz=1,p%NZGrids - DO iy=1,p%NYGrids - WRITE(UnWind,'(3(f10.2,1X))') p%FFData(iz,iy,:,i) - END DO - END DO - - CLOSE(UnWind) - - end do - - -END SUBROUTINE ConvertFFWind_toVTK - - -!==================================================================================================== - -END MODULE IfW_FFWind_Base diff --git a/modules/inflowwind/src/IfW_FFWind_Base.txt b/modules/inflowwind/src/IfW_FFWind_Base.txt deleted file mode 100644 index 1febd8d685..0000000000 --- a/modules/inflowwind/src/IfW_FFWind_Base.txt +++ /dev/null @@ -1,59 +0,0 @@ -################################################################################################################################### -# Registry for IfW_BladedFFWind, creates MODULE IfW_BladedFFWind_Types -# Module IfW_BladedFFWind_Types contains all of the user-defined types needed in IfW_BladedFFWind. It also contains copy, destroy, pack, and -# unpack routines associated with each defined data types. -################################################################################################################################### -# Entries are of the form -# keyword -################################################################################################################################### - - -typedef IfW_FFWind_Base/IfW_FFWind InitInputType IntKi ScaleMethod - 0 - "Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation]" - -typedef ^ ^ ReKi SF 3 0 - "Turbulence scaling factor for each direction [ScaleMethod=1]" - -typedef ^ ^ ReKi SigmaF 3 0 - "Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2]" - -#typedef ^ ^ ReKi TStart - 0 - "" - -#typedef ^ ^ ReKi TEnd - 0 - "" - -typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - -typedef ^ ^ ReKi RefHt - 0 - "Reference (hub) height of the grid" meters -typedef ^ ^ ReKi URef - 0 - "Mean u-component wind speed at the reference height" meters -typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - -typedef ^ ^ ReKi VLinShr - 0 - "Vertical linear wind shear coefficient (used for vertical linear wind profile type only)" - -typedef ^ ^ ReKi HLinShr - 0 - "Horizontal linear wind shear coefficient (used for horizontal wind profile type only)" - -typedef ^ ^ ReKi RefLength - 1.0_ReKi - "Reference (rotor) length of the grid (used for horizontal wind profile type only)" - -typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - -typedef ^ ^ ReKi XOffset - 0 - "distance offset for FF wind files" m - - -# ..... Parameters ................................................................................................................ -# Define parameters here: -# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType Logical Periodic - .FALSE. - "Flag to indicate if the wind file is periodic" - -typedef ^ ParameterType Logical InterpTower - .FALSE. - "Flag to indicate if we should interpolate wind speeds below the tower" - -typedef ^ ^ SiKi FFData :::: - - "Array of FF data" - -typedef ^ ^ SiKi FFTower ::: - - "Array of data along tower, below FF array" - -typedef ^ ^ ReKi FFDTime - 0 - "Delta time" seconds -typedef ^ ^ ReKi FFRate - 0 - "Data rate (1/FFDTime)" Hertz -typedef ^ ^ ReKi FFYHWid - 0 - "Half the grid width" meters -typedef ^ ^ ReKi FFZHWid - 0 - "Half the grid height" meters -typedef ^ ^ ReKi RefHt - 0 - "Reference (hub) height of the grid" meters -typedef ^ ^ ReKi GridBase - 0 - "the height of the bottom of the grid" meters -typedef ^ ^ ReKi InitXPosition - 0 - "the initial x position of grid (distance in FF is offset)" meters -typedef ^ ^ ReKi InvFFYD - 0 - "reciprocal of delta y" 1/meters -typedef ^ ^ ReKi InvFFZD - 0 - "reciprocal of delta z" 1/meters -typedef ^ ^ ReKi InvMFFWS - 0 - "reciprocal of mean wind speed (MeanFFWS)" seconds/meter -typedef ^ ^ ReKi MeanFFWS - 0 - "Mean wind speed (as defined in FF file), not necessarily of the portion used" meters/second -typedef ^ ^ ReKi TotalTime - 0 - "The total time of the simulation" seconds -typedef ^ ^ IntKi NFFComp - 3 - "Number of wind components" - -typedef ^ ^ IntKi NFFSteps - 0 - "Number of time steps in the FF array" - -typedef ^ ^ IntKi NYGrids - 0 - "Number of points in the lateral (y) direction of the grids" - -typedef ^ ^ IntKi NZGrids - 0 - "Number of points in the vertical (z) direction of the grids" - -typedef ^ ^ IntKi NTGrids - 0 - "Number of points in the vertical (z) direction on the tower (below the grids)" - -typedef ^ ^ IntKi WindFileFormat - - - "Binary file format description number" - -typedef ^ ^ Logical AddMeanAfterInterp - .FALSE. - "Add the mean wind speed after interpolating at a given height?" - -typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - -typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - -typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - -typedef ^ ^ ReKi VLinShr - 0 - "Vertical linear wind shear coefficient (used for vertical linear wind profile type only)" - -typedef ^ ^ ReKi HLinShr - 0 - "Horizontal linear wind shear coefficient (used for horizontal wind profile type only)" - -typedef ^ ^ ReKi RefLength - 1.0_ReKi - "Reference (rotor) length of the grid (used for horizontal wind profile type only)" - - diff --git a/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 b/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 deleted file mode 100644 index 9f5c55c5d2..0000000000 --- a/modules/inflowwind/src/IfW_FFWind_Base_Types.f90 +++ /dev/null @@ -1,777 +0,0 @@ -!STARTOFREGISTRYGENERATEDFILE 'IfW_FFWind_Base_Types.f90' -! -! WARNING This file is generated automatically by the FAST registry. -! Do not edit. Your changes to this file will be lost. -! -! FAST Registry -!********************************************************************************************************************************* -! IfW_FFWind_Base_Types -!................................................................................................................................. -! This file is part of IfW_FFWind_Base. -! -! Copyright (C) 2012-2016 National Renewable Energy Laboratory -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -! -! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. -! -!********************************************************************************************************************************* -!> This module contains the user-defined types needed in IfW_FFWind_Base. It also contains copy, destroy, pack, and -!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE IfW_FFWind_Base_Types -!--------------------------------------------------------------------------------------------------------------------------------- -USE NWTC_Library -IMPLICIT NONE -! ========= IfW_FFWind_InitInputType ======= - TYPE, PUBLIC :: IfW_FFWind_InitInputType - INTEGER(IntKi) :: ScaleMethod = 0 !< Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] [-] - REAL(ReKi) , DIMENSION(1:3) :: SF !< Turbulence scaling factor for each direction [ScaleMethod=1] [-] - REAL(ReKi) , DIMENSION(1:3) :: SigmaF !< Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] [-] - INTEGER(IntKi) :: WindProfileType = -1 !< Wind profile type (0=constant;1=logarithmic;2=power law) [-] - REAL(ReKi) :: RefHt = 0 !< Reference (hub) height of the grid [meters] - REAL(ReKi) :: URef = 0 !< Mean u-component wind speed at the reference height [meters] - REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] - REAL(ReKi) :: VLinShr = 0 !< Vertical linear wind shear coefficient (used for vertical linear wind profile type only) [-] - REAL(ReKi) :: HLinShr = 0 !< Horizontal linear wind shear coefficient (used for horizontal wind profile type only) [-] - REAL(ReKi) :: RefLength = 1.0_ReKi !< Reference (rotor) length of the grid (used for horizontal wind profile type only) [-] - REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] - REAL(ReKi) :: XOffset = 0 !< distance offset for FF wind files [m] - END TYPE IfW_FFWind_InitInputType -! ======================= -! ========= IfW_FFWind_ParameterType ======= - TYPE, PUBLIC :: IfW_FFWind_ParameterType - LOGICAL :: Periodic = .FALSE. !< Flag to indicate if the wind file is periodic [-] - LOGICAL :: InterpTower = .FALSE. !< Flag to indicate if we should interpolate wind speeds below the tower [-] - REAL(SiKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: FFData !< Array of FF data [-] - REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: FFTower !< Array of data along tower, below FF array [-] - REAL(ReKi) :: FFDTime = 0 !< Delta time [seconds] - REAL(ReKi) :: FFRate = 0 !< Data rate (1/FFDTime) [Hertz] - REAL(ReKi) :: FFYHWid = 0 !< Half the grid width [meters] - REAL(ReKi) :: FFZHWid = 0 !< Half the grid height [meters] - REAL(ReKi) :: RefHt = 0 !< Reference (hub) height of the grid [meters] - REAL(ReKi) :: GridBase = 0 !< the height of the bottom of the grid [meters] - REAL(ReKi) :: InitXPosition = 0 !< the initial x position of grid (distance in FF is offset) [meters] - REAL(ReKi) :: InvFFYD = 0 !< reciprocal of delta y [1/meters] - REAL(ReKi) :: InvFFZD = 0 !< reciprocal of delta z [1/meters] - REAL(ReKi) :: InvMFFWS = 0 !< reciprocal of mean wind speed (MeanFFWS) [seconds/meter] - REAL(ReKi) :: MeanFFWS = 0 !< Mean wind speed (as defined in FF file), not necessarily of the portion used [meters/second] - REAL(ReKi) :: TotalTime = 0 !< The total time of the simulation [seconds] - INTEGER(IntKi) :: NFFComp = 3 !< Number of wind components [-] - INTEGER(IntKi) :: NFFSteps = 0 !< Number of time steps in the FF array [-] - INTEGER(IntKi) :: NYGrids = 0 !< Number of points in the lateral (y) direction of the grids [-] - INTEGER(IntKi) :: NZGrids = 0 !< Number of points in the vertical (z) direction of the grids [-] - INTEGER(IntKi) :: NTGrids = 0 !< Number of points in the vertical (z) direction on the tower (below the grids) [-] - INTEGER(IntKi) :: WindFileFormat !< Binary file format description number [-] - LOGICAL :: AddMeanAfterInterp = .FALSE. !< Add the mean wind speed after interpolating at a given height? [-] - INTEGER(IntKi) :: WindProfileType = -1 !< Wind profile type (0=constant;1=logarithmic;2=power law) [-] - REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] - REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] - REAL(ReKi) :: VLinShr = 0 !< Vertical linear wind shear coefficient (used for vertical linear wind profile type only) [-] - REAL(ReKi) :: HLinShr = 0 !< Horizontal linear wind shear coefficient (used for horizontal wind profile type only) [-] - REAL(ReKi) :: RefLength = 1.0_ReKi !< Reference (rotor) length of the grid (used for horizontal wind profile type only) [-] - END TYPE IfW_FFWind_ParameterType -! ======================= -CONTAINS - SUBROUTINE IfW_FFWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FFWind_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(IfW_FFWind_InitInputType), INTENT(INOUT) :: DstInitInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_CopyInitInput' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitInputData%ScaleMethod = SrcInitInputData%ScaleMethod - DstInitInputData%SF = SrcInitInputData%SF - DstInitInputData%SigmaF = SrcInitInputData%SigmaF - DstInitInputData%WindProfileType = SrcInitInputData%WindProfileType - DstInitInputData%RefHt = SrcInitInputData%RefHt - DstInitInputData%URef = SrcInitInputData%URef - DstInitInputData%PLExp = SrcInitInputData%PLExp - DstInitInputData%VLinShr = SrcInitInputData%VLinShr - DstInitInputData%HLinShr = SrcInitInputData%HLinShr - DstInitInputData%RefLength = SrcInitInputData%RefLength - DstInitInputData%Z0 = SrcInitInputData%Z0 - DstInitInputData%XOffset = SrcInitInputData%XOffset - END SUBROUTINE IfW_FFWind_CopyInitInput - - SUBROUTINE IfW_FFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FFWind_InitInputType), INTENT(INOUT) :: InitInputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_DestroyInitInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_FFWind_DestroyInitInput - - SUBROUTINE IfW_FFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FFWind_InitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_PackInitInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! ScaleMethod - Re_BufSz = Re_BufSz + SIZE(InData%SF) ! SF - Re_BufSz = Re_BufSz + SIZE(InData%SigmaF) ! SigmaF - Int_BufSz = Int_BufSz + 1 ! WindProfileType - Re_BufSz = Re_BufSz + 1 ! RefHt - Re_BufSz = Re_BufSz + 1 ! URef - Re_BufSz = Re_BufSz + 1 ! PLExp - Re_BufSz = Re_BufSz + 1 ! VLinShr - Re_BufSz = Re_BufSz + 1 ! HLinShr - Re_BufSz = Re_BufSz + 1 ! RefLength - Re_BufSz = Re_BufSz + 1 ! Z0 - Re_BufSz = Re_BufSz + 1 ! XOffset - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = InData%ScaleMethod - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%SF,1), UBOUND(InData%SF,1) - ReKiBuf(Re_Xferred) = InData%SF(i1) - Re_Xferred = Re_Xferred + 1 - END DO - DO i1 = LBOUND(InData%SigmaF,1), UBOUND(InData%SigmaF,1) - ReKiBuf(Re_Xferred) = InData%SigmaF(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = InData%WindProfileType - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%URef - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PLExp - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VLinShr - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%HLinShr - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefLength - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Z0 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%XOffset - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FFWind_PackInitInput - - SUBROUTINE IfW_FFWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FFWind_InitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_UnPackInitInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%ScaleMethod = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%SF,1) - i1_u = UBOUND(OutData%SF,1) - DO i1 = LBOUND(OutData%SF,1), UBOUND(OutData%SF,1) - OutData%SF(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - i1_l = LBOUND(OutData%SigmaF,1) - i1_u = UBOUND(OutData%SigmaF,1) - DO i1 = LBOUND(OutData%SigmaF,1), UBOUND(OutData%SigmaF,1) - OutData%SigmaF(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%WindProfileType = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%RefHt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%URef = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%PLExp = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VLinShr = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%HLinShr = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefLength = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Z0 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%XOffset = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FFWind_UnPackInitInput - - SUBROUTINE IfW_FFWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_FFWind_ParameterType), INTENT(IN) :: SrcParamData - TYPE(IfW_FFWind_ParameterType), INTENT(INOUT) :: DstParamData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_CopyParam' -! - ErrStat = ErrID_None - ErrMsg = "" - DstParamData%Periodic = SrcParamData%Periodic - DstParamData%InterpTower = SrcParamData%InterpTower -IF (ALLOCATED(SrcParamData%FFData)) THEN - i1_l = LBOUND(SrcParamData%FFData,1) - i1_u = UBOUND(SrcParamData%FFData,1) - i2_l = LBOUND(SrcParamData%FFData,2) - i2_u = UBOUND(SrcParamData%FFData,2) - i3_l = LBOUND(SrcParamData%FFData,3) - i3_u = UBOUND(SrcParamData%FFData,3) - i4_l = LBOUND(SrcParamData%FFData,4) - i4_u = UBOUND(SrcParamData%FFData,4) - IF (.NOT. ALLOCATED(DstParamData%FFData)) THEN - ALLOCATE(DstParamData%FFData(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FFData.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%FFData = SrcParamData%FFData -ENDIF -IF (ALLOCATED(SrcParamData%FFTower)) THEN - i1_l = LBOUND(SrcParamData%FFTower,1) - i1_u = UBOUND(SrcParamData%FFTower,1) - i2_l = LBOUND(SrcParamData%FFTower,2) - i2_u = UBOUND(SrcParamData%FFTower,2) - i3_l = LBOUND(SrcParamData%FFTower,3) - i3_u = UBOUND(SrcParamData%FFTower,3) - IF (.NOT. ALLOCATED(DstParamData%FFTower)) THEN - ALLOCATE(DstParamData%FFTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FFTower.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%FFTower = SrcParamData%FFTower -ENDIF - DstParamData%FFDTime = SrcParamData%FFDTime - DstParamData%FFRate = SrcParamData%FFRate - DstParamData%FFYHWid = SrcParamData%FFYHWid - DstParamData%FFZHWid = SrcParamData%FFZHWid - DstParamData%RefHt = SrcParamData%RefHt - DstParamData%GridBase = SrcParamData%GridBase - DstParamData%InitXPosition = SrcParamData%InitXPosition - DstParamData%InvFFYD = SrcParamData%InvFFYD - DstParamData%InvFFZD = SrcParamData%InvFFZD - DstParamData%InvMFFWS = SrcParamData%InvMFFWS - DstParamData%MeanFFWS = SrcParamData%MeanFFWS - DstParamData%TotalTime = SrcParamData%TotalTime - DstParamData%NFFComp = SrcParamData%NFFComp - DstParamData%NFFSteps = SrcParamData%NFFSteps - DstParamData%NYGrids = SrcParamData%NYGrids - DstParamData%NZGrids = SrcParamData%NZGrids - DstParamData%NTGrids = SrcParamData%NTGrids - DstParamData%WindFileFormat = SrcParamData%WindFileFormat - DstParamData%AddMeanAfterInterp = SrcParamData%AddMeanAfterInterp - DstParamData%WindProfileType = SrcParamData%WindProfileType - DstParamData%PLExp = SrcParamData%PLExp - DstParamData%Z0 = SrcParamData%Z0 - DstParamData%VLinShr = SrcParamData%VLinShr - DstParamData%HLinShr = SrcParamData%HLinShr - DstParamData%RefLength = SrcParamData%RefLength - END SUBROUTINE IfW_FFWind_CopyParam - - SUBROUTINE IfW_FFWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_FFWind_ParameterType), INTENT(INOUT) :: ParamData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_DestroyParam' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - -IF (ALLOCATED(ParamData%FFData)) THEN - DEALLOCATE(ParamData%FFData) -ENDIF -IF (ALLOCATED(ParamData%FFTower)) THEN - DEALLOCATE(ParamData%FFTower) -ENDIF - END SUBROUTINE IfW_FFWind_DestroyParam - - SUBROUTINE IfW_FFWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_FFWind_ParameterType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_PackParam' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! Periodic - Int_BufSz = Int_BufSz + 1 ! InterpTower - Int_BufSz = Int_BufSz + 1 ! FFData allocated yes/no - IF ( ALLOCATED(InData%FFData) ) THEN - Int_BufSz = Int_BufSz + 2*4 ! FFData upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FFData) ! FFData - END IF - Int_BufSz = Int_BufSz + 1 ! FFTower allocated yes/no - IF ( ALLOCATED(InData%FFTower) ) THEN - Int_BufSz = Int_BufSz + 2*3 ! FFTower upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%FFTower) ! FFTower - END IF - Re_BufSz = Re_BufSz + 1 ! FFDTime - Re_BufSz = Re_BufSz + 1 ! FFRate - Re_BufSz = Re_BufSz + 1 ! FFYHWid - Re_BufSz = Re_BufSz + 1 ! FFZHWid - Re_BufSz = Re_BufSz + 1 ! RefHt - Re_BufSz = Re_BufSz + 1 ! GridBase - Re_BufSz = Re_BufSz + 1 ! InitXPosition - Re_BufSz = Re_BufSz + 1 ! InvFFYD - Re_BufSz = Re_BufSz + 1 ! InvFFZD - Re_BufSz = Re_BufSz + 1 ! InvMFFWS - Re_BufSz = Re_BufSz + 1 ! MeanFFWS - Re_BufSz = Re_BufSz + 1 ! TotalTime - Int_BufSz = Int_BufSz + 1 ! NFFComp - Int_BufSz = Int_BufSz + 1 ! NFFSteps - Int_BufSz = Int_BufSz + 1 ! NYGrids - Int_BufSz = Int_BufSz + 1 ! NZGrids - Int_BufSz = Int_BufSz + 1 ! NTGrids - Int_BufSz = Int_BufSz + 1 ! WindFileFormat - Int_BufSz = Int_BufSz + 1 ! AddMeanAfterInterp - Int_BufSz = Int_BufSz + 1 ! WindProfileType - Re_BufSz = Re_BufSz + 1 ! PLExp - Re_BufSz = Re_BufSz + 1 ! Z0 - Re_BufSz = Re_BufSz + 1 ! VLinShr - Re_BufSz = Re_BufSz + 1 ! HLinShr - Re_BufSz = Re_BufSz + 1 ! RefLength - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = TRANSFER(InData%Periodic, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%InterpTower, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%FFData) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FFData,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFData,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FFData,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFData,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FFData,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFData,3) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FFData,4) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFData,4) - Int_Xferred = Int_Xferred + 2 - - DO i4 = LBOUND(InData%FFData,4), UBOUND(InData%FFData,4) - DO i3 = LBOUND(InData%FFData,3), UBOUND(InData%FFData,3) - DO i2 = LBOUND(InData%FFData,2), UBOUND(InData%FFData,2) - DO i1 = LBOUND(InData%FFData,1), UBOUND(InData%FFData,1) - ReKiBuf(Re_Xferred) = InData%FFData(i1,i2,i3,i4) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END DO - END IF - IF ( .NOT. ALLOCATED(InData%FFTower) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FFTower,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFTower,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FFTower,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFTower,2) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%FFTower,3) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%FFTower,3) - Int_Xferred = Int_Xferred + 2 - - DO i3 = LBOUND(InData%FFTower,3), UBOUND(InData%FFTower,3) - DO i2 = LBOUND(InData%FFTower,2), UBOUND(InData%FFTower,2) - DO i1 = LBOUND(InData%FFTower,1), UBOUND(InData%FFTower,1) - ReKiBuf(Re_Xferred) = InData%FFTower(i1,i2,i3) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END IF - ReKiBuf(Re_Xferred) = InData%FFDTime - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%FFRate - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%FFYHWid - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%FFZHWid - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%GridBase - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%InitXPosition - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%InvFFYD - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%InvFFZD - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%InvMFFWS - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MeanFFWS - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%TotalTime - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NFFComp - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NFFSteps - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NYGrids - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NZGrids - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NTGrids - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%WindFileFormat - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%AddMeanAfterInterp, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%WindProfileType - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PLExp - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Z0 - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VLinShr - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%HLinShr - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefLength - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FFWind_PackParam - - SUBROUTINE IfW_FFWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_FFWind_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: i3, i3_l, i3_u ! bounds (upper/lower) for an array dimension 3 - INTEGER(IntKi) :: i4, i4_l, i4_u ! bounds (upper/lower) for an array dimension 4 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%Periodic = TRANSFER(IntKiBuf(Int_Xferred), OutData%Periodic) - Int_Xferred = Int_Xferred + 1 - OutData%InterpTower = TRANSFER(IntKiBuf(Int_Xferred), OutData%InterpTower) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FFData not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i4_l = IntKiBuf( Int_Xferred ) - i4_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FFData)) DEALLOCATE(OutData%FFData) - ALLOCATE(OutData%FFData(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FFData.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i4 = LBOUND(OutData%FFData,4), UBOUND(OutData%FFData,4) - DO i3 = LBOUND(OutData%FFData,3), UBOUND(OutData%FFData,3) - DO i2 = LBOUND(OutData%FFData,2), UBOUND(OutData%FFData,2) - DO i1 = LBOUND(OutData%FFData,1), UBOUND(OutData%FFData,1) - OutData%FFData(i1,i2,i3,i4) = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! FFTower not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i3_l = IntKiBuf( Int_Xferred ) - i3_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%FFTower)) DEALLOCATE(OutData%FFTower) - ALLOCATE(OutData%FFTower(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%FFTower.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i3 = LBOUND(OutData%FFTower,3), UBOUND(OutData%FFTower,3) - DO i2 = LBOUND(OutData%FFTower,2), UBOUND(OutData%FFTower,2) - DO i1 = LBOUND(OutData%FFTower,1), UBOUND(OutData%FFTower,1) - OutData%FFTower(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END DO - END IF - OutData%FFDTime = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%FFRate = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%FFYHWid = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%FFZHWid = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefHt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%GridBase = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%InitXPosition = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%InvFFYD = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%InvFFZD = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%InvMFFWS = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%MeanFFWS = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%TotalTime = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%NFFComp = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%NFFSteps = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%NYGrids = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%NZGrids = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%NTGrids = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%WindFileFormat = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%AddMeanAfterInterp = TRANSFER(IntKiBuf(Int_Xferred), OutData%AddMeanAfterInterp) - Int_Xferred = Int_Xferred + 1 - OutData%WindProfileType = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%PLExp = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Z0 = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VLinShr = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%HLinShr = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefLength = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FFWind_UnPackParam - -END MODULE IfW_FFWind_Base_Types -!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index 45d821d67a..0faf659c9a 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -25,7 +25,9 @@ module IfW_FlowField implicit none public IfW_FlowField_GetVelAcc -public UniformField_CalcAccel, Grid3DField_CalcAccel +public IfW_UniformField_CalcAccel, IfW_Grid3DField_CalcAccel +public IfW_UniformWind_GetOP +public Grid3D_to_Uniform, Uniform_to_Grid3D integer(IntKi), parameter :: WindProfileType_None = -1 !< don't add wind profile; already included in input integer(IntKi), parameter :: WindProfileType_Constant = 0 !< constant wind @@ -119,7 +121,7 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A ! If cubic velocity interp requested, calculate operating point using ! cubic interpolation. Otherwise, use linear interpolation if (FF%VelInterpCubic) then - UFopVel = UniformField_IterpCubic(FF%Uniform, Time) + UFopVel = UniformField_InterpCubic(FF%Uniform, Time) else UFopVel = UniformField_InterpLinear(FF%Uniform, Time) end if @@ -132,7 +134,7 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A if (FF%VelInterpCubic) then UFopAcc = UFopVel else - UFopAcc = UniformField_IterpCubic(FF%Uniform, Time) + UFopAcc = UniformField_InterpCubic(FF%Uniform, Time) end if ! Loop throuh points and calcualate velocity and acceleration @@ -472,7 +474,7 @@ pure function UniformField_InterpLinear(UF, Time) result(op) end function -pure function UniformField_IterpCubic(UF, Time) result(op) +pure function UniformField_InterpCubic(UF, Time) result(op) type(UniformFieldType), intent(in) :: UF real(DbKi), intent(in) :: Time @@ -562,7 +564,7 @@ pure function UniformField_IterpCubic(UF, Time) result(op) end function -subroutine UniformField_CalcAccel(UF, ErrStat, ErrMsg) +subroutine IfW_UniformField_CalcAccel(UF, ErrStat, ErrMsg) type(UniformFieldType), intent(inout) :: UF integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg @@ -702,6 +704,28 @@ subroutine CalcCubicSplineDeriv(x, y, dy) end subroutine +!> Routine to compute the Jacobians of the output (Y) function with respect to the inputs (u). The partial +!! derivative dY/du is returned. This submodule does not follow the modularization framework. +subroutine IfW_UniformWind_GetOP(UF, t, InterpCubic, OP_out) + type(UniformFieldType), intent(IN) :: UF !< Parameters + real(DbKi), intent(IN) :: t !< Current simulation time in seconds + logical, intent(in) :: InterpCubic !< flag for using cubic interpolation + real(ReKi), intent(OUT) :: OP_out(2) !< operating point (HWindSpeed and PLexp + + type(UniformField_Interp) :: op ! interpolated values of InterpParams + + ! Linearly interpolate parameters in time at operating point (or use nearest-neighbor to extrapolate) + if (InterpCubic) then + op = UniformField_InterpCubic(UF, t) + else + op = UniformField_InterpLinear(UF, t) + end if + + OP_out(1) = op%VelH + OP_out(2) = op%ShrV + +end subroutine + subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, VelCell, AccCell, Xi, Is3D, ErrStat, ErrMsg) type(Grid3DFieldType), intent(in) :: G3D !< 3D Grid-Field data @@ -1128,7 +1152,7 @@ subroutine Grid3DField_GetVelAccCubic(DTime, VelCell, AccCell, Xi, Is3D, Velocit end subroutine -subroutine Grid3DField_CalcAccel(G3D, ErrStat, ErrMsg) +subroutine IfW_Grid3DField_CalcAccel(G3D, ErrStat, ErrMsg) type(Grid3DFieldType), intent(inout) :: G3D integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg @@ -1152,7 +1176,7 @@ subroutine Grid3DField_CalcAccel(G3D, ErrStat, ErrMsg) ! If number of time grids is 1 or 2, set all accelerations to zero, return if (G3D%NTGrids < 3) then G3D%Acc = 0.0_SiKi - return + return end if ! Allocate storage for U used in cubic spline derivative calc @@ -1384,4 +1408,347 @@ subroutine UserField_GetVel(UF, Time, Position, Velocity, ErrStat, ErrMsg) end subroutine +function CalculateMeanVelocity(G3D, z, y) result(u) + + type(Grid3DFieldType), intent(IN) :: G3D !< Parameters + real(ReKi), intent(IN) :: Z ! height + real(ReKi), intent(IN) :: y ! lateral location + real(ReKi) :: u ! mean wind speed at position (y,z) + + select case (G3D%WindProfileType) + + case (WindProfileType_PL) + + U = G3D%MeanWS*(Z/G3D%RefHeight)**G3D%PLExp ! [IEC 61400-1 6.3.1.2 (10)] + + case (WindProfileType_Log) + + if (.not. EqualRealNos(G3D%RefHeight, G3D%Z0) .and. Z > 0.0_ReKi) then + U = G3D%MeanWS*(LOG(Z/G3D%Z0))/(LOG(G3D%RefHeight/G3D%Z0)) + else + U = 0.0_ReKi + end if + + case (WindProfileType_Constant) + + U = G3D%MeanWS + + case DEFAULT + + U = 0.0_ReKi + + end select + + if (G3D%VLinShr .ne. 0.0_ReKi) then ! Add vertical linear shear, if has + U = U + G3D%MeanWS*G3D%VLinShr*(Z - G3D%RefHeight)/G3D%RefLength + end if + + if (G3D%HLinShr .ne. 0.0_ReKi) then ! Add horizontal linear shear, if has + U = U + G3D%MeanWS*G3D%HLinShr*y/G3D%RefLength + end if + +end function CalculateMeanVelocity + +subroutine Uniform_to_Grid3D(UF, InterpCubic, G3D, ErrStat, ErrMsg) + + type(UniformFieldType), intent(IN) :: UF !< UniformWind Parameters + logical, intent(in) :: InterpCubic !< Flag to use cubic interpolation + type(Grid3DFieldType), intent(OUT) :: G3D !< FF Parameters + integer(IntKi), intent(OUT) :: ErrStat !< error status + character(*), intent(OUT) :: ErrMsg !< error message + + character(*), parameter :: RoutineName = 'Uniform_to_FFWind' + integer(ReKi), parameter :: dz = 5.0 + integer(ReKi), parameter :: dy = 5.0 + real(DbKi) :: Time + real(ReKi) :: PositionXYZ(3) + type(UniformField_Interp) :: op + integer(IntKi) :: n, i, it, iy, iz + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + G3D%WindFileFormat = -1 ! Binary file format description number + G3D%NComp = 3 ! Number of wind components + G3D%Periodic = .false. + G3D%InterpTower = .true. + G3D%RefHeight = UF%RefHeight + G3D%NTGrids = 0 + G3D%InvDY = 1.0_ReKi/dy ! reciprocal of delta y (1/meters) + G3D%InvDZ = 1.0_ReKi/dz ! reciprocal of delta z (1/meters) + + ! Number of points in the lateral (y) direction of the grids + n = nint(UF%RefLength*1.1_ReKi*0.5_ReKi/dy) + G3D%NYGrids = n*2 + 1 + + ! Number of points in the vertical (z) direction of the grids + n = nint(UF%RefLength*1.1_ReKi*0.5_ReKi/dz) + G3D%NZGrids = nint(G3D%RefHeight/dy) + n + 1 + + ! Half the grid width (meters) + G3D%YHWid = 0.5_ReKi*dy*(G3D%NYGrids - 1) + + ! Half the grid height (meters) + G3D%ZHWid = 0.5_ReKi*dz*(G3D%NZGrids - 1) + + ! Height of the bottom of the grid (meters) + G3D%GridBase = G3D%RefHeight + n*dz - G3D%ZHWid*2.0_ReKi + + ! Initial x position of grid (distance in FF is offset) meters) + G3D%InitXPosition = 0.0_ReKi + + ! time will be the smallest delta t in this Uniform wind file + if (UF%DataSize < 2) then + G3D%DTime = 600.0_ReKi ! doesn't matter what the time step is + G3D%NSteps = 2 ! "Number of time steps in the FF array + else + if (G3D%DTime < 0.0001) then + G3D%DTime = minval(UF%Time(2:) - UF%Time(:size(UF%Time) - 1)) ! Delta time (seconds) + call SetErrStat(ErrID_Fatal, "Smallest time step in uniform wind file is less that 0.0001 seconds. "// & + "Increase the time step to convert to a FF file.", ErrStat, ErrMsg, RoutineName) + return + end if + G3D%NSteps = NINT(UF%Time(UF%DataSize)/G3D%DTime) + 1 + end if + + G3D%Rate = 1.0_ReKi/G3D%DTime ! Data rate (1/DTime) + G3D%AddMeanAfterInterp = .false. ! Add the mean wind speed after interpolating at a given height? + G3D%WindProfileType = WindProfileType_PL ! Wind profile type (0=constant;1=logarithmic;2=power law) + G3D%PLExp = GetAverageVal(UF%ShrV) ! Power law exponent (used for PL wind profile type only) + G3D%Z0 = 0.0_ReKi ! Surface roughness length (used for LOG wind profile type only) + G3D%TotalTime = (G3D%NSteps - 1)*G3D%DTime ! The total time of the simulation (seconds) + + ! Allocate velocity array + call AllocAry(G3D%Vel, G3D%NZGrids, G3D%NYGrids, G3D%NComp, G3D%NSteps, 'G3D%Vel', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Initialize position + PositionXYZ = 0.0_ReKi + + ! Loop through time steps + do it = 1, G3D%NSteps + + ! Calculate time + Time = (it - 1)*G3D%DTime + + ! Get operating point + if (InterpCubic) then + op = UniformField_InterpCubic(UF, Time) + else + op = UniformField_InterpLinear(UF, Time) + end if + + ! Loop through y grid + do iy = 1, G3D%NYGrids + + ! Calculate Y position + PositionXYZ(2) = (iy - 1)*dy - G3D%YHWid + + ! Loop through z grid + do iz = 1, G3D%NZGrids + + ! Calculate Z position + PositionXYZ(3) = (iz - 1)*dz + G3D%GridBase + + ! Calculate velocity at operating point and position, store in grid + G3D%Vel(:, iy, iz, it) = real(UniformField_GetVel(UF, op, PositionXYZ), SiKi) + + end do ! iz + end do ! iy + end do ! it + + ! compute some averages for this simulation + G3D%MeanWS = GetAverageVal(UF%VelH) ! Mean wind speed (advection speed) + G3D%InvMWS = 1.0_ReKi/G3D%MeanWS + +contains + + function GetAverageVal(Ary) result(Avg) + real(ReKi), intent(in) :: Ary(:) + real(ReKi) :: Avg + + ! If array has one element, average is first value + if (UF%DataSize < 2) then + Avg = Ary(1) + return + end if + + Avg = UF%Time(1)*Ary(1) ! in case tData(1) /= 0 + do i = 2, UF%DataSize + Avg = Avg + (UF%Time(i) - UF%Time(i - 1))*(Ary(i) + Ary(i - 1)) + end do + Avg = Avg/(UF%Time(UF%DataSize) - UF%Time(1))/2.0_ReKi + + end function GetAverageVal + +end subroutine Uniform_to_Grid3D + +subroutine Grid3D_to_Uniform(G3D, UF, ErrStat, ErrMsg, SmoothingRadius) + + type(Grid3DFieldType), intent(IN) :: G3D !< FF Parameters + type(UniformFieldType), intent(OUT) :: UF !< UniformWind Parameters + integer(IntKi), intent(OUT) :: ErrStat !< error status + character(*), intent(OUT) :: ErrMsg !< error message + real(ReKi), optional, intent(IN) :: SmoothingRadius !< length of time used for smoothing data, seconds (if omitted, no smoothing will occur) + + character(*), parameter :: RoutineName = 'FFWind_to_Uniform' + integer(IntKi) :: i + integer(IntKi) :: iy_ref, iz_ref, iz_p1 + integer(IntKi) :: iy, iz, ic + real(ReKi) :: meanVel(3) + real(ReKi) :: meanWindDir + real(ReKi) :: u_p1, z_p1 + real(ReKi) :: u_ref, z_ref + real(ReKi), parameter :: HubPositionX = 0.0_ReKi + real(ReKi) :: radius ! length of time to use for smoothing uniform wind data, seconds + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + real(SiKi), allocatable :: Vel(:, :, :, :) + real(ReKi), allocatable :: tmp(:) + real(R8Ki) :: transformMat(3, 3) + + ErrStat = ErrID_None + ErrMsg = "" + + if (G3D%RefLength > epsilon(0.0_ReKi)) then + UF%RefLength = G3D%VLinShr + else + UF%RefLength = (G3D%nYGrids - 1)/G3D%InvDY ! width of the FF wind field + end if + + UF%DataSize = G3D%NSteps + + call AllocAry(UF%Time, UF%DataSize, 'time', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(UF%VelH, UF%DataSize, 'horizontal wind speed', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(UF%AngleH, UF%DataSize, 'direction', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(UF%AngleV, UF%DataSize, 'upflow', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(UF%VelV, UF%DataSize, 'vertical wind speed', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(UF%ShrH, UF%DataSize, 'horizontal linear shear', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(UF%ShrV, UF%DataSize, 'vertical power-law shear exponent', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(UF%LinShrV, UF%DataSize, 'vertical linear shear', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(UF%VelGust, UF%DataSize, 'gust velocity', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + call AllocAry(Vel, G3D%NZGrids, G3D%NYGrids, G3D%NComp, G3D%NSteps, 'FFData', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + call AllocAry(tmp, G3D%NSteps, 'tmp', ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + if (ErrStat >= AbortErrLev .or. UF%DataSize < 1) then + if (allocated(Vel)) deallocate (Vel) + if (allocated(tmp)) deallocate (tmp) + return + end if + + ! we'll assume these are 0, for simplicity + UF%ShrH = G3D%HLinShr + UF%LinShrV = G3D%VLinShr + UF%VelGust = 0.0_ReKi + + ! fill time array with time at hub position + do i = 1, UF%DataSize + UF%Time(i) = (G3D%InitXPosition - HubPositionX)*G3D%InvMWS + (i - 1)*G3D%DTime + end do + + ! calculate mean velocity at grid point nearest lateral center of grid at reference height: + iy_ref = nint(G3D%nYGrids/2.0_ReKi) + iz_ref = nint((G3D%RefHeight - G3D%GridBase)*G3D%InvDZ) + 1 + UF%RefHeight = G3D%GridBase + (iz_ref - 1)/G3D%InvDZ ! make sure RefHt is on the grid + + meanVel = 0.0_ReKi + do i = 1, UF%DataSize + meanVel = meanVel + G3D%Vel(iz_ref, iy_ref, :, i) + end do + meanVel = meanVel/UF%DataSize + + ! calculate the average upflow angle + UF%AngleV = atan2(meanVel(3), TwoNorm(meanVel(1:2))) + meanWindDir = atan2(meanVel(2), meanVel(1)) + + ! rotate the FF wind to remove the mean upflow and direction + transformMat(1, 1) = cos(meanWindDir)*cos(UF%AngleV(1)) + transformMat(2, 1) = -sin(meanWindDir) + transformMat(3, 1) = -cos(meanWindDir)*sin(UF%AngleV(1)) + + transformMat(1, 2) = sin(meanWindDir)*cos(UF%AngleV(1)) + transformMat(2, 2) = cos(meanWindDir) + transformMat(3, 2) = -sin(meanWindDir)*sin(UF%AngleV(1)) + + transformMat(1, 3) = sin(UF%AngleV(1)) + transformMat(2, 3) = 0.0_R8Ki + transformMat(3, 3) = cos(UF%AngleV(1)) + + do i = 1, size(Vel, 4) + do iy = 1, size(Vel, 2) + do iz = 1, size(Vel, 1) + Vel(iz, iy, :, i) = matmul(transformMat, G3D%Vel(iz, iy, :, i)) + end do + end do + end do + + ! make sure we have the correct mean, or the direction will also be off here + if (G3D%AddMeanAfterInterp) then + Vel(iz_ref, iy_ref, 1, :) = Vel(iz_ref, iy_ref, 1, :) + CalculateMeanVelocity(G3D, UF%RefHeight, 0.0_ReKi) + end if + + meanVel = 0.0_ReKi + do i = 1, UF%DataSize + meanVel = meanVel + Vel(iz_ref, iy_ref, :, i) + end do + meanVel = meanVel/UF%DataSize + + ! Fill velocity arrays for uniform wind + do i = 1, UF%DataSize + UF%VelH(i) = TwoNorm(Vel(iz_ref, iy_ref, 1:2, i)) + end do + UF%VelV = Vel(iz_ref, iy_ref, 3, :) + + ! Fill wind direction array + do i = 1, UF%DataSize + UF%AngleH(i) = -(meanWindDir + atan2(Vel(iz_ref, iy_ref, 2, i), Vel(iz_ref, iy_ref, 1, i))) + end do + + ! Now, time average values, if desired: + if (present(SmoothingRadius)) then + radius = SmoothingRadius + else + radius = 0.0_ReKi + end if + + tmp = UF%VelH; call kernelSmoothing(UF%Time, tmp, kernelType_TRIWEIGHT, radius, UF%VelH) + tmp = UF%VelV; call kernelSmoothing(UF%Time, tmp, kernelType_TRIWEIGHT, radius, UF%VelV) + tmp = UF%AngleH; call kernelSmoothing(UF%Time, tmp, kernelType_TRIWEIGHT, radius, UF%AngleH) + + ! Calculate averaged power law coefficient: + if (G3D%WindProfileType == WindProfileType_PL) then + UF%ShrV = G3D%PLExp + else + iz_p1 = G3D%nZGrids ! pick a point to compute the power law exponent (least squares would be better than a single point) + z_p1 = G3D%GridBase + (iz_p1 - 1)/G3D%InvDZ + + if (G3D%AddMeanAfterInterp) then + u_p1 = CalculateMeanVelocity(G3D, z_p1, 0.0_ReKi) + else + u_p1 = 0.0_ReKi + do i = 1, UF%DataSize + u_p1 = u_p1 + Vel(iz_p1, iy_ref, 1, i) + end do + u_p1 = u_p1/UF%DataSize + end if + + if (EqualRealNos(meanVel(1), u_p1) .or. EqualRealNos(u_p1, 0.0_ReKi) .or. EqualRealNos(meanVel(1), 0.0_ReKi)) then + UF%ShrV = 0.0_ReKi + else + UF%ShrV = log(u_p1/meanVel(1))/log(z_p1/UF%RefHeight) + end if + end if + + ! clean up + + if (allocated(Vel)) deallocate (Vel) + if (allocated(tmp)) deallocate (tmp) + +end subroutine Grid3D_to_Uniform + end module diff --git a/modules/inflowwind/src/IfW_FlowField.txt b/modules/inflowwind/src/IfW_FlowField.txt index 3549a91431..930f6b5e4d 100644 --- a/modules/inflowwind/src/IfW_FlowField.txt +++ b/modules/inflowwind/src/IfW_FlowField.txt @@ -8,7 +8,7 @@ param IfW_FlowField - IntKi Undef_FieldTy param ^ - IntKi Uniform_FieldType - 1 - "Uniform FieldType from SteadyWind or Uniform Wind" - param ^ - IntKi Grid3D_FieldType - 2 - "3D Grid FieldType from TurbSim, Bladed, HAWC" - param ^ - IntKi Grid4D_FieldType - 3 - "4D Grid FieldType from FAST.Farm" - -param ^ - IntKi Point_FieldType - 4 - "Points FieldType from ExtInflow" - +param ^ - IntKi Point_FieldType - 4 - "Points FieldType from ExtInflow" - param ^ - IntKi User_FieldType - 5 - "User FieldType configured by the user" - #---------------------------------------------------------------------------------------------------------------------------------- @@ -84,23 +84,25 @@ typedef ^ ^ IntKi NTGrids typedef ^ ^ IntKi NSteps - 0 - "Number of time steps in the FF array" - typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - +typedef ^ ^ ReKi VLinShr - 0 - "Vertical linear wind shear coefficient (used for vertical linear wind profile type only)" - +typedef ^ ^ ReKi HLinShr - 0 - "Horizontal linear wind shear coefficient (used for horizontal wind profile type only)" - -#---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ UserFieldType SiKi Dummy - - - "" - #---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ Grid4DFieldType IntKi n 4 - - "number of evenly-spaced grid points in the x, y, z, and t directions" - +typedef ^ Grid4DFieldType IntKi n 4 - - "number of evenly-spaced grid points in the x, y, z, and t directions" - typedef ^ ^ ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" typedef ^ ^ SiKi Vel ::::: - - "this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt]" - typedef ^ ^ ReKi TimeStart - - - "this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1))" s #---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ PointsFieldType ReKi Vel :: - - "Point velocities populated by external driver [uvw,point]" - +typedef ^ PointsFieldType ReKi Vel :: - - "Point velocities populated by external driver [uvw,point]" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ UserFieldType SiKi Dummy - - - "" - #---------------------------------------------------------------------------------------------------------------------------------- typedef ^ FlowFieldType IntKi FieldType - 0 - "Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External}" - -typedef ^ ^ logical Enabled - .true. - "" - typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" radians @@ -110,7 +112,7 @@ typedef ^ ^ logical AccFieldValid typedef ^ ^ ReKi RotToWind {3}{3} - - "Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X')" - typedef ^ ^ ReKi RotFromWind {3}{3} - - "Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind)" - typedef ^ ^ UniformFieldType Uniform - - - "Uniform Flow Data" -typedef ^ ^ PointsFieldType Points - - - "External Point Flow Data" typedef ^ ^ Grid3DFieldType Grid3D - - - "Grid Field Wind Data" typedef ^ ^ Grid4DFieldType Grid4D - - - "External Grid Flow Data" +typedef ^ ^ PointsFieldType Points - - - "External Point Flow Data" typedef ^ ^ UserFieldType User - - - "User Field Wind Data" diff --git a/modules/inflowwind/src/IfW_FlowField_Types.f90 b/modules/inflowwind/src/IfW_FlowField_Types.f90 index 80de64b1fb..2d19f7a842 100644 --- a/modules/inflowwind/src/IfW_FlowField_Types.f90 +++ b/modules/inflowwind/src/IfW_FlowField_Types.f90 @@ -118,13 +118,10 @@ MODULE IfW_FlowField_Types INTEGER(IntKi) :: NSteps = 0 !< Number of time steps in the FF array [-] REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] + REAL(ReKi) :: VLinShr = 0 !< Vertical linear wind shear coefficient (used for vertical linear wind profile type only) [-] + REAL(ReKi) :: HLinShr = 0 !< Horizontal linear wind shear coefficient (used for horizontal wind profile type only) [-] END TYPE Grid3DFieldType ! ======================= -! ========= UserFieldType ======= - TYPE, PUBLIC :: UserFieldType - REAL(SiKi) :: Dummy !< [-] - END TYPE UserFieldType -! ======================= ! ========= Grid4DFieldType ======= TYPE, PUBLIC :: Grid4DFieldType INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of evenly-spaced grid points in the x, y, z, and t directions [-] @@ -139,10 +136,14 @@ MODULE IfW_FlowField_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vel !< Point velocities populated by external driver [uvw,point] [-] END TYPE PointsFieldType ! ======================= +! ========= UserFieldType ======= + TYPE, PUBLIC :: UserFieldType + REAL(SiKi) :: Dummy !< [-] + END TYPE UserFieldType +! ======================= ! ========= FlowFieldType ======= TYPE, PUBLIC :: FlowFieldType INTEGER(IntKi) :: FieldType = 0 !< Switch for flow field type {1=Uniform, 2=Grid, 3=User, 4=External} [-] - LOGICAL :: Enabled = .true. !< [-] REAL(ReKi) , DIMENSION(1:3) :: RefPosition !< Reference position (point where box is rotated) [meters] REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [radians] @@ -152,9 +153,9 @@ MODULE IfW_FlowField_Types REAL(ReKi) , DIMENSION(1:3,1:3) :: RotToWind !< Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X') [-] REAL(ReKi) , DIMENSION(1:3,1:3) :: RotFromWind !< Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind) [-] TYPE(UniformFieldType) :: Uniform !< Uniform Flow Data [-] - TYPE(PointsFieldType) :: Points !< External Point Flow Data [-] TYPE(Grid3DFieldType) :: Grid3D !< Grid Field Wind Data [-] TYPE(Grid4DFieldType) :: Grid4D !< External Grid Flow Data [-] + TYPE(PointsFieldType) :: Points !< External Point Flow Data [-] TYPE(UserFieldType) :: User !< User Field Wind Data [-] END TYPE FlowFieldType ! ======================= @@ -1581,6 +1582,8 @@ SUBROUTINE IfW_FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DF DstGrid3DFieldTypeData%NSteps = SrcGrid3DFieldTypeData%NSteps DstGrid3DFieldTypeData%PLExp = SrcGrid3DFieldTypeData%PLExp DstGrid3DFieldTypeData%Z0 = SrcGrid3DFieldTypeData%Z0 + DstGrid3DFieldTypeData%VLinShr = SrcGrid3DFieldTypeData%VLinShr + DstGrid3DFieldTypeData%HLinShr = SrcGrid3DFieldTypeData%HLinShr END SUBROUTINE IfW_FlowField_CopyGrid3DFieldType SUBROUTINE IfW_FlowField_DestroyGrid3DFieldType( Grid3DFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -1698,6 +1701,8 @@ SUBROUTINE IfW_FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata Int_BufSz = Int_BufSz + 1 ! NSteps Re_BufSz = Re_BufSz + 1 ! PLExp Re_BufSz = Re_BufSz + 1 ! Z0 + Re_BufSz = Re_BufSz + 1 ! VLinShr + Re_BufSz = Re_BufSz + 1 ! HLinShr IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1885,6 +1890,10 @@ SUBROUTINE IfW_FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%Z0 Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VLinShr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HLinShr + Re_Xferred = Re_Xferred + 1 END SUBROUTINE IfW_FlowField_PackGrid3DFieldType SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -2089,144 +2098,11 @@ SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outd Re_Xferred = Re_Xferred + 1 OutData%Z0 = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType - - SUBROUTINE IfW_FlowField_CopyUserFieldType( SrcUserFieldTypeData, DstUserFieldTypeData, CtrlCode, ErrStat, ErrMsg ) - TYPE(UserFieldType), INTENT(IN) :: SrcUserFieldTypeData - TYPE(UserFieldType), INTENT(INOUT) :: DstUserFieldTypeData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyUserFieldType' -! - ErrStat = ErrID_None - ErrMsg = "" - DstUserFieldTypeData%Dummy = SrcUserFieldTypeData%Dummy - END SUBROUTINE IfW_FlowField_CopyUserFieldType - - SUBROUTINE IfW_FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(UserFieldType), INTENT(INOUT) :: UserFieldTypeData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyUserFieldType' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_FlowField_DestroyUserFieldType - - SUBROUTINE IfW_FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(UserFieldType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackUserFieldType' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! Dummy - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%Dummy + OutData%VLinShr = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_PackUserFieldType - - SUBROUTINE IfW_FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(UserFieldType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackUserFieldType' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) + OutData%HLinShr = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_FlowField_UnPackUserFieldType + END SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType SUBROUTINE IfW_FlowField_CopyGrid4DFieldType( SrcGrid4DFieldTypeData, DstGrid4DFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(Grid4DFieldType), INTENT(IN) :: SrcGrid4DFieldTypeData @@ -2712,6 +2588,143 @@ SUBROUTINE IfW_FlowField_UnPackPointsFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outd END IF END SUBROUTINE IfW_FlowField_UnPackPointsFieldType + SUBROUTINE IfW_FlowField_CopyUserFieldType( SrcUserFieldTypeData, DstUserFieldTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(UserFieldType), INTENT(IN) :: SrcUserFieldTypeData + TYPE(UserFieldType), INTENT(INOUT) :: DstUserFieldTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_CopyUserFieldType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUserFieldTypeData%Dummy = SrcUserFieldTypeData%Dummy + END SUBROUTINE IfW_FlowField_CopyUserFieldType + + SUBROUTINE IfW_FlowField_DestroyUserFieldType( UserFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(UserFieldType), INTENT(INOUT) :: UserFieldTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_DestroyUserFieldType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE IfW_FlowField_DestroyUserFieldType + + SUBROUTINE IfW_FlowField_PackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(UserFieldType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_PackUserFieldType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! Dummy + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%Dummy + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_PackUserFieldType + + SUBROUTINE IfW_FlowField_UnPackUserFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(UserFieldType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FlowField_UnPackUserFieldType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE IfW_FlowField_UnPackUserFieldType + SUBROUTINE IfW_FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTypeData, CtrlCode, ErrStat, ErrMsg ) TYPE(FlowFieldType), INTENT(IN) :: SrcFlowFieldTypeData TYPE(FlowFieldType), INTENT(INOUT) :: DstFlowFieldTypeData @@ -2729,7 +2742,6 @@ SUBROUTINE IfW_FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTy ErrStat = ErrID_None ErrMsg = "" DstFlowFieldTypeData%FieldType = SrcFlowFieldTypeData%FieldType - DstFlowFieldTypeData%Enabled = SrcFlowFieldTypeData%Enabled DstFlowFieldTypeData%RefPosition = SrcFlowFieldTypeData%RefPosition DstFlowFieldTypeData%PropagationDir = SrcFlowFieldTypeData%PropagationDir DstFlowFieldTypeData%VFlowAngle = SrcFlowFieldTypeData%VFlowAngle @@ -2741,15 +2753,15 @@ SUBROUTINE IfW_FlowField_CopyFlowFieldType( SrcFlowFieldTypeData, DstFlowFieldTy CALL IfW_FlowField_Copyuniformfieldtype( SrcFlowFieldTypeData%Uniform, DstFlowFieldTypeData%Uniform, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_FlowField_Copypointsfieldtype( SrcFlowFieldTypeData%Points, DstFlowFieldTypeData%Points, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN CALL IfW_FlowField_Copygrid3dfieldtype( SrcFlowFieldTypeData%Grid3D, DstFlowFieldTypeData%Grid3D, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN CALL IfW_FlowField_Copygrid4dfieldtype( SrcFlowFieldTypeData%Grid4D, DstFlowFieldTypeData%Grid4D, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + CALL IfW_FlowField_Copypointsfieldtype( SrcFlowFieldTypeData%Points, DstFlowFieldTypeData%Points, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN CALL IfW_FlowField_Copyuserfieldtype( SrcFlowFieldTypeData%User, DstFlowFieldTypeData%User, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -2778,12 +2790,12 @@ SUBROUTINE IfW_FlowField_DestroyFlowFieldType( FlowFieldTypeData, ErrStat, ErrMs CALL IfW_FlowField_Destroyuniformfieldtype( FlowFieldTypeData%Uniform, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_FlowField_Destroypointsfieldtype( FlowFieldTypeData%Points, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL IfW_FlowField_Destroygrid3dfieldtype( FlowFieldTypeData%Grid3D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL IfW_FlowField_Destroygrid4dfieldtype( FlowFieldTypeData%Grid4D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL IfW_FlowField_Destroypointsfieldtype( FlowFieldTypeData%Points, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL IfW_FlowField_Destroyuserfieldtype( FlowFieldTypeData%User, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE IfW_FlowField_DestroyFlowFieldType @@ -2824,7 +2836,6 @@ SUBROUTINE IfW_FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Db_BufSz = 0 Int_BufSz = 0 Int_BufSz = Int_BufSz + 1 ! FieldType - Int_BufSz = Int_BufSz + 1 ! Enabled Re_BufSz = Re_BufSz + SIZE(InData%RefPosition) ! RefPosition Re_BufSz = Re_BufSz + 1 ! PropagationDir Re_BufSz = Re_BufSz + 1 ! VFlowAngle @@ -2851,54 +2862,54 @@ SUBROUTINE IfW_FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! Points: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, .TRUE. ) ! Points + Int_BufSz = Int_BufSz + 3 ! Grid3D: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid3D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! Points + IF(ALLOCATED(Re_Buf)) THEN ! Grid3D Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! Points + IF(ALLOCATED(Db_Buf)) THEN ! Grid3D Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! Points + IF(ALLOCATED(Int_Buf)) THEN ! Grid3D Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! Grid3D: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid3D + Int_BufSz = Int_BufSz + 3 ! Grid4D: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! Grid3D + IF(ALLOCATED(Re_Buf)) THEN ! Grid4D Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! Grid3D + IF(ALLOCATED(Db_Buf)) THEN ! Grid4D Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! Grid3D + IF(ALLOCATED(Int_Buf)) THEN ! Grid4D Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! Grid4D: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, .TRUE. ) ! Grid4D + Int_BufSz = Int_BufSz + 3 ! Points: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, .TRUE. ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN - IF(ALLOCATED(Re_Buf)) THEN ! Grid4D + IF(ALLOCATED(Re_Buf)) THEN ! Points Re_BufSz = Re_BufSz + SIZE( Re_Buf ) DEALLOCATE(Re_Buf) END IF - IF(ALLOCATED(Db_Buf)) THEN ! Grid4D + IF(ALLOCATED(Db_Buf)) THEN ! Points Db_BufSz = Db_BufSz + SIZE( Db_Buf ) DEALLOCATE(Db_Buf) END IF - IF(ALLOCATED(Int_Buf)) THEN ! Grid4D + IF(ALLOCATED(Int_Buf)) THEN ! Points Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF @@ -2948,8 +2959,6 @@ SUBROUTINE IfW_FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, IntKiBuf(Int_Xferred) = InData%FieldType Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%Enabled, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 DO i1 = LBOUND(InData%RefPosition,1), UBOUND(InData%RefPosition,1) ReKiBuf(Re_Xferred) = InData%RefPosition(i1) Re_Xferred = Re_Xferred + 1 @@ -3004,7 +3013,7 @@ SUBROUTINE IfW_FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, OnlySize ) ! Points + CALL IfW_FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, OnlySize ) ! Grid3D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3032,7 +3041,7 @@ SUBROUTINE IfW_FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid3D, ErrStat2, ErrMsg2, OnlySize ) ! Grid3D + CALL IfW_FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, OnlySize ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3060,7 +3069,7 @@ SUBROUTINE IfW_FlowField_PackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_FlowField_Packgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Grid4D, ErrStat2, ErrMsg2, OnlySize ) ! Grid4D + CALL IfW_FlowField_Packpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%Points, ErrStat2, ErrMsg2, OnlySize ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3148,8 +3157,6 @@ SUBROUTINE IfW_FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdat Int_Xferred = 1 OutData%FieldType = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 - OutData%Enabled = TRANSFER(IntKiBuf(Int_Xferred), OutData%Enabled) - Int_Xferred = Int_Xferred + 1 i1_l = LBOUND(OutData%RefPosition,1) i1_u = UBOUND(OutData%RefPosition,1) DO i1 = LBOUND(OutData%RefPosition,1), UBOUND(OutData%RefPosition,1) @@ -3259,7 +3266,7 @@ SUBROUTINE IfW_FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdat Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Points, ErrStat2, ErrMsg2 ) ! Points + CALL IfW_FlowField_Unpackgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid3D, ErrStat2, ErrMsg2 ) ! Grid3D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3299,7 +3306,7 @@ SUBROUTINE IfW_FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdat Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackgrid3dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid3D, ErrStat2, ErrMsg2 ) ! Grid3D + CALL IfW_FlowField_Unpackgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid4D, ErrStat2, ErrMsg2 ) ! Grid4D CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3339,7 +3346,7 @@ SUBROUTINE IfW_FlowField_UnPackFlowFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdat Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FlowField_Unpackgrid4dfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Grid4D, ErrStat2, ErrMsg2 ) ! Grid4D + CALL IfW_FlowField_Unpackpointsfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%Points, ErrStat2, ErrMsg2 ) ! Points CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN diff --git a/modules/inflowwind/src/IfW_HAWCWind.f90 b/modules/inflowwind/src/IfW_HAWCWind.f90 deleted file mode 100644 index c903ee66a6..0000000000 --- a/modules/inflowwind/src/IfW_HAWCWind.f90 +++ /dev/null @@ -1,390 +0,0 @@ -!> This module uses full-field binary wind files to determine the wind inflow. -!! This module assumes that the origin, (0,0,0), is located at the tower centerline at ground level, -!! and that all units are specified in the metric system (using meters and seconds). -!! Data is assumed periodic in the X direction (and thus not shifted like FFWind files are). -MODULE IfW_HAWCWind -!! -!! Created 25-June-2010 by B. Jonkman, National Renewable Energy Laboratory -!! using subroutines and modules from AeroDyn v12.58 -!! -!!---------------------------------------------------------------------------------------------------- -!! Updated 8-Aug-2015 for InflowWind v3.0 in the FAST v8 Framework -! -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2015-2016 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** - USE NWTC_Library - USE IfW_HAWCWind_Types - USE IfW_FFWind_Base - - IMPLICIT NONE - PRIVATE - - TYPE(ProgDesc), PARAMETER :: IfW_HAWCWind_Ver = ProgDesc( 'IfW_HAWCWind', '', '' ) - - PUBLIC :: IfW_HAWCWind_Init - PUBLIC :: IfW_HAWCWind_End - PUBLIC :: IfW_HAWCWind_CalcOutput - - INTEGER(IntKi), PARAMETER :: nc = 3 !< number of wind components - -CONTAINS -!==================================================================================================== -!> This routine is used to initialize the parameters for using HAWC wind format files. -SUBROUTINE IfW_HAWCWind_Init(InitInp, p, MiscVars, Interval, InitOut, ErrStat, ErrMsg) - - ! Passed Variables - TYPE(IfW_HAWCWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization data passed to the module - TYPE(IfW_HAWCWind_ParameterType), INTENT( OUT) :: p !< Parameters - TYPE(IfW_HAWCWind_MiscVarType), INTENT( OUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - TYPE(IfW_HAWCWind_InitOutputType), INTENT( OUT) :: InitOut !< Initialization output - - REAL(DbKi), INTENT(IN ) :: Interval !< Time Interval to use (passed through here) - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_Init' - - ! Local Variables: - - - - ErrStat = ErrID_None - ErrMsg = "" - - ! validate init input data: - call ValidateInput(InitInp, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Set some internal module parameters based on input file values - !------------------------------------------------------------------------------------------------- - p%FF%WindFileFormat = 0 - p%FF%Periodic = .true. - p%FF%InterpTower = .true. - - p%FF%NFFComp = 3 - p%FF%NFFSteps = InitInp%nx - p%FF%NYGrids = InitInp%ny - p%FF%NZGrids = InitInp%nz - p%FF%NTGrids = 0 - - p%FF%MeanFFWS = InitInp%FF%URef - p%FF%FFDTime = InitInp%dx / InitInp%FF%URef - p%FF%FFRate = 1.0 / p%FF%FFDTime - p%FF%InvFFYD = 1.0 / InitInp%dy - p%FF%InvFFZD = 1.0 / InitInp%dz - p%FF%InvMFFWS = 1.0 / p%FF%MeanFFWS - - p%FF%TotalTime = InitInp%nx * InitInp%dx / InitInp%FF%URef - p%FF%FFYHWid = 0.5 * InitInp%dy * (InitInp%ny-1) - p%FF%FFZHWid = 0.5 * InitInp%dz * (InitInp%nz-1) - p%FF%GridBase = InitInp%FF%RefHt - p%FF%FFZHWid - p%FF%RefHt = InitInp%FF%RefHt - - p%FF%WindProfileType = InitInp%FF%WindProfileType - p%FF%Z0 = InitInp%FF%Z0 - p%FF%PLExp = InitInp%FF%PLExp - p%FF%VLinShr = 0.0_ReKi - p%FF%HLinShr = 0.0_ReKi - p%FF%RefLength = p%FF%FFYHWid*2.0_ReKi - p%FF%AddMeanAfterInterp = .true. - - - p%FF%InitXPosition = InitInp%FF%XOffset - - IF ( p%FF%GridBase < 0.0_ReKi ) THEN - call SetErrStat( ErrID_Severe, 'WARNING: The bottom of the grid is located at a height of '//& - TRIM( Num2LStr(p%FF%GridBase) )//' meters, which is below the ground.'//& - ' Winds below the ground will be set to 0.', ErrStat,ErrMsg, RoutineName) - END IF - - !------------------------------------------------------------------------------------------------- - ! Read data files: - !------------------------------------------------------------------------------------------------- - call ReadTurbulenceData( p, InitInp, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - !------------------------------------------------------------------------------------------------- - ! scale to requested TI (or use requested scale factors) - !------------------------------------------------------------------------------------------------- - call ScaleTurbulence(InitInp%FF, p%FF%FFData, InitOut%sf, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Add the mean wind speed to the u component. - !------------------------------------------------------------------------------------------------- - if (InitInp%FF%ScaleMethod /= ScaleMethod_None) call SubtractMeanVelocity(p%FF%FFData) - if (.not. p%FF%AddMeanAfterInterp) call AddMeanVelocity(InitInp%FF, p%FF%GridBase, 1.0_ReKi/p%FF%InvFFZD, 1.0_ReKi/p%FF%InvFFYD, p%FF%FFData) - - !------------------------------------------------------------------------------------------------- - ! write info to summary file, if necessary - !------------------------------------------------------------------------------------------------- - - IF ( InitInp%SumFileUnit > 0 ) THEN - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) 'HAWC wind type. Read by InflowWind sub-module '//TRIM(GetNVD(IfW_HAWCWind_Ver)) - - WRITE(InitInp%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Reference height (m): ',InitInp%FF%RefHt - WRITE(InitInp%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Timestep (s): ',p%FF%FFDTime - WRITE(InitInp%SumFileUnit,'(A34,I12)', IOSTAT=TmpErrStat) ' Number of timesteps: ',p%FF%NFFSteps - WRITE(InitInp%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Mean windspeed (m/s): ',p%FF%MeanFFWS - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Time range (s): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr( p%FF%TotalTime ))//' ]' - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' X range (m): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr( p%FF%TotalTime * p%FF%MeanFFWS ))//' ]' - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Y range (m): [ '// & - TRIM(Num2LStr(-p%FF%FFYHWid))//' : '//TRIM(Num2LStr(p%FF%FFYHWid))//' ]' - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Z range (m): [ '// & - TRIM(Num2LStr(p%FF%GridBase))//' : '//TRIM(Num2LStr(p%FF%GridBase + p%FF%FFZHWid*2.0))//' ]' - - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) 'Scaling factors used:' - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' u v w ' - WRITE(InitInp%SumFileUnit,'(A)', IOSTAT=TmpErrStat) '---------- ---------- ----------' - WRITE(InitInp%SumFileUnit,'(F10.3,2x,F10.3,2x,F10.3)',IOSTAT=TmpErrStat) InitOut%sf - ENDIF - - MiscVars%DummyMiscVar = 0 - - RETURN - -END SUBROUTINE IfW_HAWCWind_Init -!==================================================================================================== -!> This routine is used to make sure the initInp data is valid. -SUBROUTINE ValidateInput(InitInp, ErrStat, ErrMsg) - - ! Passed Variables - TYPE(IfW_HAWCWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization input data passed to the module - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - character(*), parameter :: RoutineName = 'ValidateInput' - - - ErrStat = ErrID_None - ErrMsg = "" - - ! validate the inputs for scaling turbulence: - CALL FFWind_ValidateInput(InitInp%FF, nc, ErrStat, ErrMsg) - - IF ( InitInp%nx < 1 ) CALL SetErrStat( ErrID_Fatal, 'Number of grid points in the X direction must be at least 1.', ErrStat, ErrMsg, RoutineName ) - IF ( InitInp%ny < 1 ) CALL SetErrStat( ErrID_Fatal, 'Number of grid points in the Y direction must be at least 1.', ErrStat, ErrMsg, RoutineName ) - IF ( InitInp%nz < 1 ) CALL SetErrStat( ErrID_Fatal, 'Number of grid points in the Z direction must be at least 1.', ErrStat, ErrMsg, RoutineName ) - - IF ( InitInp%dx < 0.0_ReKi .or. EqualRealNos( InitInp%dx, 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal, 'The grid spacing in the X direction must be larger than 0.', ErrStat, ErrMsg, RoutineName ) - IF ( InitInp%dy < 0.0_ReKi .or. EqualRealNos( InitInp%dy, 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal, 'The grid spacing in the Y direction must be larger than 0.', ErrStat, ErrMsg, RoutineName ) - IF ( InitInp%dz < 0.0_ReKi .or. EqualRealNos( InitInp%dz, 0.0_ReKi ) ) CALL SetErrStat( ErrID_Fatal, 'The grid spacing in the Z direction must be larger than 0.', ErrStat, ErrMsg, RoutineName ) - - -END SUBROUTINE ValidateInput -!==================================================================================================== -!> This routine is used read the full-field turbulence data stored in HAWC format. -SUBROUTINE ReadTurbulenceData(p, InitInp, ErrStat, ErrMsg) - - ! Passed Variables - TYPE(IfW_HAWCWind_ParameterType), INTENT(INOUT) :: p !< Parameters - TYPE(IfW_HAWCWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization input data passed to the module - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - ! Local Variables: - INTEGER :: IC ! Loop counter for the number of wind components - INTEGER :: IX ! Loop counter for the number of grid points in the X direction - INTEGER :: IY ! Loop counter for the number of grid points in the Y direction - INTEGER :: unWind ! unit number for reading binary files - - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - CHARACTER(*), PARAMETER :: RoutineName = 'ReadTurbulenceData' - - - ErrStat = ErrID_None - ErrMsg = "" - - - !------------------------------------------------------------------------------------------------- - ! Allocate space for the wind array. - !------------------------------------------------------------------------------------------------- - - CALL AllocAry( p%FF%FFData, p%FF%NZGrids,p%FF%NYGrids,p%FF%NFFComp, p%FF%NFFSteps, 'p%FF%FFData', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - !------------------------------------------------------------------------------------------------- - ! Read the 3 files containg the turbulent wind speeds. - !------------------------------------------------------------------------------------------------- -!bjj: check these indices... they do not seem to be very consistant between the WAsP IEC Turbulence -! simulator and documentation of OC3 file formats... the current implementation is from the -! OC3/Kenneth Thompson documentation. - - - ! this could take a while, so we'll write a message indicating what's going on: - - CALL WrScr( NewLine//' Reading HAWC wind files with grids of '//& - TRIM( Num2LStr(p%FF%NFFSteps) )//' x '//TRIM( Num2LStr(p%FF%NYGrids) )//' x '//TRIM( Num2LStr(p%FF%NZGrids) )//' points'// & - ' ('//TRIM( Num2LStr(p%FF%FFYHWid*2) )//' m wide, '// TRIM( Num2LStr(p%FF%GridBase) )//' m to '// & - TRIM( Num2LStr(p%FF%GridBase+p%FF%FFZHWid*2) )//& - ' m above ground) with a characteristic wind speed of '//TRIM( Num2LStr(p%FF%MeanFFWS) )//' m/s. ' ) - - - CALL GetNewUnit( UnWind, TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - ! The array must be filled so that x(i) < x(i+1), y(i) < y(i+1), and z(i) < z(i+1) - ! Also, note that the time axis is the negative x axis. - - DO IC = 1,NC - - CALL OpenBInpFile ( UnWind, InitInp%WindFileName(IC), TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - ! DO IX = p%FF%NFFSteps,1,-1 ! This order fixes #256 - DO IX = 1,p%FF%NFFSteps ! This order is wrong (has been in dev and hawc2 for a while now) - DO IY = p%FF%NYGrids,1,-1 - !DO IZ = 1,p%FF%NZGrids - - READ( UnWind, IOSTAT=TmpErrStat ) p%FF%FFData(:,iy,ic,ix) ! note that FFData is SiKi (4-byte reals, not default kinds) - - IF (TmpErrStat /= 0) THEN - TmpErrMsg = ' Error reading binary data from "'//TRIM(InitInp%WindFileName(IC))//'". I/O error ' & - //TRIM(Num2LStr(TmpErrStat))//' occurred at IY='//TRIM(Num2LStr(IY))//', IX='//TRIM(Num2LStr(IX))//'.' - CLOSE ( UnWind ) - CALL SetErrStat(ErrID_Fatal, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - RETURN - END IF - - !END DO - END DO - END DO - - CLOSE ( UnWind ) - - END DO - - -END SUBROUTINE ReadTurbulenceData -!==================================================================================================== -!> This routine acts as a wrapper for the GetWindSpeed routine. It steps through the array of input -!! positions and calls the GetWindSpeed routine to calculate the velocities at each point. -!! -!! There are inefficiencies in how this set of routines is coded, but that is a problem for another -!! day. For now, it merely needs to be functional. It can be fixed up and made all pretty later. -!! -!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -SUBROUTINE IfW_HAWCWind_CalcOutput(Time, PositionXYZ, p, Velocity, MiscVars, ErrStat, ErrMsg) - - IMPLICIT NONE - - ! Passed Variables - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - REAL(ReKi), INTENT(IN ) :: PositionXYZ(:,:) !< Array of XYZ coordinates, 3xN - TYPE(IfW_HAWCWind_ParameterType), INTENT(IN ) :: p !< Parameters - REAL(ReKi), INTENT(INOUT) :: Velocity(:,:) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) - TYPE(IfW_HAWCWind_MiscVarType), INTENT(INOUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message - - - ! temporary variables - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CalcOutput' - - - !------------------------------------------------------------------------------------------------- - ! Check that the module has been initialized. - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = '' - - !------------------------------------------------------------------------------------------------- - ! Initialize some things - !------------------------------------------------------------------------------------------------- - - CALL IfW_FFWind_CalcOutput(Time, PositionXYZ, p%FF, Velocity, ErrStat, ErrMsg) - RETURN - -END SUBROUTINE IfW_HAWCWind_CalcOutput -!==================================================================================================== -!> This subroutine cleans up any data that is still allocated. The (possibly) open files are -!! closed in InflowWindMod. -SUBROUTINE IfW_HAWCWind_End( p, MiscVars, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_HAWCWind_End" - - - - ! Passed Variables - TYPE(IfW_HAWCWind_ParameterType), INTENT(INOUT) :: p !< Parameters - TYPE(IfW_HAWCWind_MiscVarType), INTENT( OUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Local Variables - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - !-=- Initialize the routine -=- - - ErrMsg = '' - ErrStat = ErrID_None - - - - - ! Destroy parameter data - - CALL IfW_HAWCWind_DestroyParam( p, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - - - ! Destroy the state data - - CALL IfW_HAWCWind_DestroyMisc( MiscVars, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - - - -END SUBROUTINE IfW_HAWCWind_End - -!==================================================================================================== -END MODULE IfW_HAWCWind diff --git a/modules/inflowwind/src/IfW_HAWCWind.txt b/modules/inflowwind/src/IfW_HAWCWind.txt deleted file mode 100644 index 1d45291817..0000000000 --- a/modules/inflowwind/src/IfW_HAWCWind.txt +++ /dev/null @@ -1,52 +0,0 @@ -################################################################################################################################### -# Registry for IfW_HAWCWind, creates MODULE IfW_HAWCWind_Types -# Module IfW_HAWCWind_Types contains all of the user-defined types needed in IfW_HAWCWind. It also contains copy, destroy, pack, and -# unpack routines associated with each defined data types. -################################################################################################################################### -# Entries are of the form -# keyword -################################################################################################################################### - -include Registry_NWTC_Library.txt -usefrom IfW_FFWind_Base.txt - - -######################### - -# Init Input -typedef IfW_HAWCWind/IfW_HAWCWind InitInputType CHARACTER(1024) WindFileName {3} - - "Name of the wind file to use" - -typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - -typedef ^ ^ IntKi nx - 0 - "Number of grids in the x direction (in the 3 files above)" - -typedef ^ ^ IntKi ny - 0 - "Number of grids in the y direction (in the 3 files above)" - -typedef ^ ^ IntKi nz - 0 - "Number of grids in the z direction (in the 3 files above)" - -typedef ^ ^ ReKi dx - 0 - "size of grids in the x direction (in the 3 files above)" - -typedef ^ ^ ReKi dy - 0 - "size of grids in the y direction (in the 3 files above)" - -typedef ^ ^ ReKi dz - 0 - "size of grids in the z direction (in the 3 files above)" - -typedef ^ ^ IfW_FFWind_InitInputType FF - - - "scaling data" - - - -# Init Output -typedef ^ InitOutputType ProgDesc Ver - - - "Version information of HAWCWind submodule" - -typedef ^ ^ ReKi SF 3 0 - "Turbulence scaling factor for each direction direction" - - - -# ..... States not used by this module ................................................................................................................... -typedef ^ ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - -typedef ^ DiscreteStateType ReKi DummyDiscState - - - "Remove this variable if you have discrete states" - -typedef ^ ConstraintStateType ReKi DummyConstrState - - - "Remove this variable if you have constraint states" - -typedef ^ OtherStateType ReKi DummyOtherState - - - "Remove this variable if you have other states" - - -# ..... Misc/Optimization variables................................................................................................. -# Define any data that are used only for efficiency purposes (these variables are not associated with time): -# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi DummyMiscVar - - - "Remove this variable if you have misc variables" - - -# ..... Parameters ................................................................................................................ -# Define parameters here: -# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType IfW_FFWind_ParameterType FF - - - "Parameters used in all full-field wind types" - - -# ..... Inputs .................................................................................................................... -# Define inputs that are not on this mesh here: -typedef ^ InputType ReKi Position :: - - "Array holding the input positions at a given timestep" meters - diff --git a/modules/inflowwind/src/IfW_HAWCWind_Types.f90 b/modules/inflowwind/src/IfW_HAWCWind_Types.f90 deleted file mode 100644 index 126947f674..0000000000 --- a/modules/inflowwind/src/IfW_HAWCWind_Types.f90 +++ /dev/null @@ -1,1720 +0,0 @@ -!STARTOFREGISTRYGENERATEDFILE 'IfW_HAWCWind_Types.f90' -! -! WARNING This file is generated automatically by the FAST registry. -! Do not edit. Your changes to this file will be lost. -! -! FAST Registry -!********************************************************************************************************************************* -! IfW_HAWCWind_Types -!................................................................................................................................. -! This file is part of IfW_HAWCWind. -! -! Copyright (C) 2012-2016 National Renewable Energy Laboratory -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -! -! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. -! -!********************************************************************************************************************************* -!> This module contains the user-defined types needed in IfW_HAWCWind. It also contains copy, destroy, pack, and -!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE IfW_HAWCWind_Types -!--------------------------------------------------------------------------------------------------------------------------------- -USE IfW_FFWind_Base_Types -USE NWTC_Library -IMPLICIT NONE -! ========= IfW_HAWCWind_InitInputType ======= - TYPE, PUBLIC :: IfW_HAWCWind_InitInputType - CHARACTER(1024) , DIMENSION(1:3) :: WindFileName !< Name of the wind file to use [-] - INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file (-1 for none). Provided by IfW. [-] - INTEGER(IntKi) :: nx = 0 !< Number of grids in the x direction (in the 3 files above) [-] - INTEGER(IntKi) :: ny = 0 !< Number of grids in the y direction (in the 3 files above) [-] - INTEGER(IntKi) :: nz = 0 !< Number of grids in the z direction (in the 3 files above) [-] - REAL(ReKi) :: dx = 0 !< size of grids in the x direction (in the 3 files above) [-] - REAL(ReKi) :: dy = 0 !< size of grids in the y direction (in the 3 files above) [-] - REAL(ReKi) :: dz = 0 !< size of grids in the z direction (in the 3 files above) [-] - TYPE(IfW_FFWind_InitInputType) :: FF !< scaling data [-] - END TYPE IfW_HAWCWind_InitInputType -! ======================= -! ========= IfW_HAWCWind_InitOutputType ======= - TYPE, PUBLIC :: IfW_HAWCWind_InitOutputType - TYPE(ProgDesc) :: Ver !< Version information of HAWCWind submodule [-] - REAL(ReKi) , DIMENSION(1:3) :: SF !< Turbulence scaling factor for each direction direction [-] - END TYPE IfW_HAWCWind_InitOutputType -! ======================= -! ========= IfW_HAWCWind_ContinuousStateType ======= - TYPE, PUBLIC :: IfW_HAWCWind_ContinuousStateType - REAL(ReKi) :: DummyContState !< Remove this variable if you have continuous states [-] - END TYPE IfW_HAWCWind_ContinuousStateType -! ======================= -! ========= IfW_HAWCWind_DiscreteStateType ======= - TYPE, PUBLIC :: IfW_HAWCWind_DiscreteStateType - REAL(ReKi) :: DummyDiscState !< Remove this variable if you have discrete states [-] - END TYPE IfW_HAWCWind_DiscreteStateType -! ======================= -! ========= IfW_HAWCWind_ConstraintStateType ======= - TYPE, PUBLIC :: IfW_HAWCWind_ConstraintStateType - REAL(ReKi) :: DummyConstrState !< Remove this variable if you have constraint states [-] - END TYPE IfW_HAWCWind_ConstraintStateType -! ======================= -! ========= IfW_HAWCWind_OtherStateType ======= - TYPE, PUBLIC :: IfW_HAWCWind_OtherStateType - REAL(ReKi) :: DummyOtherState !< Remove this variable if you have other states [-] - END TYPE IfW_HAWCWind_OtherStateType -! ======================= -! ========= IfW_HAWCWind_MiscVarType ======= - TYPE, PUBLIC :: IfW_HAWCWind_MiscVarType - REAL(ReKi) :: DummyMiscVar !< Remove this variable if you have misc variables [-] - END TYPE IfW_HAWCWind_MiscVarType -! ======================= -! ========= IfW_HAWCWind_ParameterType ======= - TYPE, PUBLIC :: IfW_HAWCWind_ParameterType - TYPE(IfW_FFWind_ParameterType) :: FF !< Parameters used in all full-field wind types [-] - END TYPE IfW_HAWCWind_ParameterType -! ======================= -! ========= IfW_HAWCWind_InputType ======= - TYPE, PUBLIC :: IfW_HAWCWind_InputType - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Position !< Array holding the input positions at a given timestep [meters] - END TYPE IfW_HAWCWind_InputType -! ======================= -CONTAINS - SUBROUTINE IfW_HAWCWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_HAWCWind_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(IfW_HAWCWind_InitInputType), INTENT(INOUT) :: DstInitInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CopyInitInput' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitInputData%WindFileName = SrcInitInputData%WindFileName - DstInitInputData%SumFileUnit = SrcInitInputData%SumFileUnit - DstInitInputData%nx = SrcInitInputData%nx - DstInitInputData%ny = SrcInitInputData%ny - DstInitInputData%nz = SrcInitInputData%nz - DstInitInputData%dx = SrcInitInputData%dx - DstInitInputData%dy = SrcInitInputData%dy - DstInitInputData%dz = SrcInitInputData%dz - CALL IfW_FFWind_CopyInitInput( SrcInitInputData%FF, DstInitInputData%FF, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_HAWCWind_CopyInitInput - - SUBROUTINE IfW_HAWCWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_HAWCWind_InitInputType), INTENT(INOUT) :: InitInputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyInitInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL IfW_FFWind_DestroyInitInput( InitInputData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_HAWCWind_DestroyInitInput - - SUBROUTINE IfW_HAWCWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_InitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_PackInitInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + SIZE(InData%WindFileName)*LEN(InData%WindFileName) ! WindFileName - Int_BufSz = Int_BufSz + 1 ! SumFileUnit - Int_BufSz = Int_BufSz + 1 ! nx - Int_BufSz = Int_BufSz + 1 ! ny - Int_BufSz = Int_BufSz + 1 ! nz - Re_BufSz = Re_BufSz + 1 ! dx - Re_BufSz = Re_BufSz + 1 ! dy - Re_BufSz = Re_BufSz + 1 ! dz - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype - CALL IfW_FFWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! FF - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! FF - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! FF - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO i1 = LBOUND(InData%WindFileName,1), UBOUND(InData%WindFileName,1) - DO I = 1, LEN(InData%WindFileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(i1)(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - IntKiBuf(Int_Xferred) = InData%SumFileUnit - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%nx - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%ny - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%nz - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%dx - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%dy - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%dz - Re_Xferred = Re_Xferred + 1 - CALL IfW_FFWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE IfW_HAWCWind_PackInitInput - - SUBROUTINE IfW_HAWCWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_InitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_UnPackInitInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - i1_l = LBOUND(OutData%WindFileName,1) - i1_u = UBOUND(OutData%WindFileName,1) - DO i1 = LBOUND(OutData%WindFileName,1), UBOUND(OutData%WindFileName,1) - DO I = 1, LEN(OutData%WindFileName) - OutData%WindFileName(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END DO - OutData%SumFileUnit = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%nx = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%ny = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%nz = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%dx = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%dy = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%dz = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_FFWind_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_HAWCWind_UnPackInitInput - - SUBROUTINE IfW_HAWCWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_HAWCWind_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(IfW_HAWCWind_InitOutputType), INTENT(INOUT) :: DstInitOutputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CopyInitOutput' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - DstInitOutputData%SF = SrcInitOutputData%SF - END SUBROUTINE IfW_HAWCWind_CopyInitOutput - - SUBROUTINE IfW_HAWCWind_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_HAWCWind_InitOutputType), INTENT(INOUT) :: InitOutputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyInitOutput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_HAWCWind_DestroyInitOutput - - SUBROUTINE IfW_HAWCWind_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_InitOutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_PackInitOutput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Ver - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Ver - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Ver - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Re_BufSz = Re_BufSz + SIZE(InData%SF) ! SF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - DO i1 = LBOUND(InData%SF,1), UBOUND(InData%SF,1) - ReKiBuf(Re_Xferred) = InData%SF(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END SUBROUTINE IfW_HAWCWind_PackInitOutput - - SUBROUTINE IfW_HAWCWind_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_InitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_UnPackInitOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - i1_l = LBOUND(OutData%SF,1) - i1_u = UBOUND(OutData%SF,1) - DO i1 = LBOUND(OutData%SF,1), UBOUND(OutData%SF,1) - OutData%SF(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END SUBROUTINE IfW_HAWCWind_UnPackInitOutput - - SUBROUTINE IfW_HAWCWind_CopyContState( SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_HAWCWind_ContinuousStateType), INTENT(IN) :: SrcContStateData - TYPE(IfW_HAWCWind_ContinuousStateType), INTENT(INOUT) :: DstContStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CopyContState' -! - ErrStat = ErrID_None - ErrMsg = "" - DstContStateData%DummyContState = SrcContStateData%DummyContState - END SUBROUTINE IfW_HAWCWind_CopyContState - - SUBROUTINE IfW_HAWCWind_DestroyContState( ContStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_HAWCWind_ContinuousStateType), INTENT(INOUT) :: ContStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyContState' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_HAWCWind_DestroyContState - - SUBROUTINE IfW_HAWCWind_PackContState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_ContinuousStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_PackContState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyContState - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyContState - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_PackContState - - SUBROUTINE IfW_HAWCWind_UnPackContState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_ContinuousStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_UnPackContState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyContState = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_UnPackContState - - SUBROUTINE IfW_HAWCWind_CopyDiscState( SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_HAWCWind_DiscreteStateType), INTENT(IN) :: SrcDiscStateData - TYPE(IfW_HAWCWind_DiscreteStateType), INTENT(INOUT) :: DstDiscStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CopyDiscState' -! - ErrStat = ErrID_None - ErrMsg = "" - DstDiscStateData%DummyDiscState = SrcDiscStateData%DummyDiscState - END SUBROUTINE IfW_HAWCWind_CopyDiscState - - SUBROUTINE IfW_HAWCWind_DestroyDiscState( DiscStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_HAWCWind_DiscreteStateType), INTENT(INOUT) :: DiscStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyDiscState' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_HAWCWind_DestroyDiscState - - SUBROUTINE IfW_HAWCWind_PackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_DiscreteStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_PackDiscState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyDiscState - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyDiscState - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_PackDiscState - - SUBROUTINE IfW_HAWCWind_UnPackDiscState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_DiscreteStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_UnPackDiscState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyDiscState = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_UnPackDiscState - - SUBROUTINE IfW_HAWCWind_CopyConstrState( SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_HAWCWind_ConstraintStateType), INTENT(IN) :: SrcConstrStateData - TYPE(IfW_HAWCWind_ConstraintStateType), INTENT(INOUT) :: DstConstrStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CopyConstrState' -! - ErrStat = ErrID_None - ErrMsg = "" - DstConstrStateData%DummyConstrState = SrcConstrStateData%DummyConstrState - END SUBROUTINE IfW_HAWCWind_CopyConstrState - - SUBROUTINE IfW_HAWCWind_DestroyConstrState( ConstrStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_HAWCWind_ConstraintStateType), INTENT(INOUT) :: ConstrStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyConstrState' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_HAWCWind_DestroyConstrState - - SUBROUTINE IfW_HAWCWind_PackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_ConstraintStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_PackConstrState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyConstrState - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyConstrState - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_PackConstrState - - SUBROUTINE IfW_HAWCWind_UnPackConstrState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_ConstraintStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_UnPackConstrState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyConstrState = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_UnPackConstrState - - SUBROUTINE IfW_HAWCWind_CopyOtherState( SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_HAWCWind_OtherStateType), INTENT(IN) :: SrcOtherStateData - TYPE(IfW_HAWCWind_OtherStateType), INTENT(INOUT) :: DstOtherStateData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CopyOtherState' -! - ErrStat = ErrID_None - ErrMsg = "" - DstOtherStateData%DummyOtherState = SrcOtherStateData%DummyOtherState - END SUBROUTINE IfW_HAWCWind_CopyOtherState - - SUBROUTINE IfW_HAWCWind_DestroyOtherState( OtherStateData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_HAWCWind_OtherStateType), INTENT(INOUT) :: OtherStateData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyOtherState' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_HAWCWind_DestroyOtherState - - SUBROUTINE IfW_HAWCWind_PackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_OtherStateType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_PackOtherState' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyOtherState - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyOtherState - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_PackOtherState - - SUBROUTINE IfW_HAWCWind_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_OtherStateType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_UnPackOtherState' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyOtherState = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_UnPackOtherState - - SUBROUTINE IfW_HAWCWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_HAWCWind_MiscVarType), INTENT(IN) :: SrcMiscData - TYPE(IfW_HAWCWind_MiscVarType), INTENT(INOUT) :: DstMiscData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CopyMisc' -! - ErrStat = ErrID_None - ErrMsg = "" - DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar - END SUBROUTINE IfW_HAWCWind_CopyMisc - - SUBROUTINE IfW_HAWCWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_HAWCWind_MiscVarType), INTENT(INOUT) :: MiscData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyMisc' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_HAWCWind_DestroyMisc - - SUBROUTINE IfW_HAWCWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_MiscVarType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_PackMisc' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyMiscVar - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyMiscVar - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_PackMisc - - SUBROUTINE IfW_HAWCWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyMiscVar = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_HAWCWind_UnPackMisc - - SUBROUTINE IfW_HAWCWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_HAWCWind_ParameterType), INTENT(IN) :: SrcParamData - TYPE(IfW_HAWCWind_ParameterType), INTENT(INOUT) :: DstParamData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CopyParam' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL IfW_FFWind_CopyParam( SrcParamData%FF, DstParamData%FF, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_HAWCWind_CopyParam - - SUBROUTINE IfW_HAWCWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_HAWCWind_ParameterType), INTENT(INOUT) :: ParamData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyParam' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL IfW_FFWind_DestroyParam( ParamData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_HAWCWind_DestroyParam - - SUBROUTINE IfW_HAWCWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_ParameterType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_PackParam' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype - CALL IfW_FFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! FF - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! FF - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! FF - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL IfW_FFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE IfW_HAWCWind_PackParam - - SUBROUTINE IfW_HAWCWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_FFWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_HAWCWind_UnPackParam - - SUBROUTINE IfW_HAWCWind_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_HAWCWind_InputType), INTENT(IN) :: SrcInputData - TYPE(IfW_HAWCWind_InputType), INTENT(INOUT) :: DstInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_CopyInput' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcInputData%Position)) THEN - i1_l = LBOUND(SrcInputData%Position,1) - i1_u = UBOUND(SrcInputData%Position,1) - i2_l = LBOUND(SrcInputData%Position,2) - i2_u = UBOUND(SrcInputData%Position,2) - IF (.NOT. ALLOCATED(DstInputData%Position)) THEN - ALLOCATE(DstInputData%Position(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Position.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstInputData%Position = SrcInputData%Position -ENDIF - END SUBROUTINE IfW_HAWCWind_CopyInput - - SUBROUTINE IfW_HAWCWind_DestroyInput( InputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_HAWCWind_InputType), INTENT(INOUT) :: InputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_DestroyInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - -IF (ALLOCATED(InputData%Position)) THEN - DEALLOCATE(InputData%Position) -ENDIF - END SUBROUTINE IfW_HAWCWind_DestroyInput - - SUBROUTINE IfW_HAWCWind_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_InputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_PackInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! Position allocated yes/no - IF ( ALLOCATED(InData%Position) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! Position upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Position) ! Position - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%Position) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Position,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Position,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Position,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Position,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%Position,2), UBOUND(InData%Position,2) - DO i1 = LBOUND(InData%Position,1), UBOUND(InData%Position,1) - ReKiBuf(Re_Xferred) = InData%Position(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - END SUBROUTINE IfW_HAWCWind_PackInput - - SUBROUTINE IfW_HAWCWind_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_HAWCWind_InputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_HAWCWind_UnPackInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Position not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Position)) DEALLOCATE(OutData%Position) - ALLOCATE(OutData%Position(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Position.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%Position,2), UBOUND(OutData%Position,2) - DO i1 = LBOUND(OutData%Position,1), UBOUND(OutData%Position,1) - OutData%Position(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - END SUBROUTINE IfW_HAWCWind_UnPackInput - -END MODULE IfW_HAWCWind_Types -!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/IfW_TSFFWind.f90 b/modules/inflowwind/src/IfW_TSFFWind.f90 deleted file mode 100644 index 77bcf5c4c8..0000000000 --- a/modules/inflowwind/src/IfW_TSFFWind.f90 +++ /dev/null @@ -1,661 +0,0 @@ -!> This module uses full-field binary wind files to determine the wind inflow. -!! This module assumes that the origin, (0,0,0), is located at the tower centerline at ground level, -!! and that all units are specified in the metric system (using meters and seconds). -!! Data is shifted by half the grid width to account for turbine yaw (so that data in the X -!! direction actually starts at -1*ParamData%FF%FFYHWid meters). -MODULE IfW_TSFFWind -!! -!! Created 25-Sep-2009 by B. Jonkman, National Renewable Energy Laboratory -!! using subroutines and modules from AeroDyn v12.58 -!! -!!---------------------------------------------------------------------------------------------------- -!! Feb 2013 v2.00.00 A. Platt -!! -- updated to the new framework -!! -- Modified to use NWTC_Library v. 2.0 -!! -- Note: Jacobians are not included in this version. -!! -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2015-2016 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** - - USE NWTC_Library - USE IfW_TSFFWind_Types - USE IfW_FFWind_Base - - IMPLICIT NONE - PRIVATE - - TYPE(ProgDesc), PARAMETER :: IfW_TSFFWind_Ver = ProgDesc( 'IfW_TSFFWind', '', '' ) - - PUBLIC :: IfW_TSFFWind_Init - PUBLIC :: IfW_TSFFWind_End - PUBLIC :: IfW_TSFFWind_CalcOutput - - - - -CONTAINS -!==================================================================================================== -!> This routine is used read the full-field turbulence data. -!! 09/25/1997 - Created by M. Buhl from GETFILES in ViewWind. -!! 09/23/2009 - modified by B. Jonkman: this subroutine was split into several subroutines (was ReadFF) -!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -SUBROUTINE IfW_TSFFWind_Init(InitData, ParamData, MiscVars, InitOutData, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_TSFFWind_Init" - - - ! Passed Variables - TYPE(IfW_TSFFWind_InitInputType), INTENT(IN ) :: InitData !< Initialization data passed to the module - TYPE(IfW_TSFFWind_ParameterType), INTENT( OUT) :: ParamData !< Parameters - TYPE(IfW_TSFFWind_MiscVarType), INTENT( OUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - TYPE(IfW_TSFFWind_InitOutputType), INTENT( OUT) :: InitOutData !< Initial output - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - ! Local Variables: - - INTEGER(IntKi) :: UnitWind ! Unit number for the InflowWind input file - INTEGER(B2Ki) :: Dum_Int2 - - !------------------------------------------------------------------------------------------------- - ! Initialize temporary variables - !------------------------------------------------------------------------------------------------- - - ErrMsg = '' - ErrStat = ErrID_None - - ParamData%FF%InterpTower = .false. - ParamData%FF%AddMeanAfterInterp = .false. - ParamData%FF%WindProfileType = WindProfileType_None - ParamData%FF%VLinShr = 0.0_ReKi - ParamData%FF%HLinShr = 0.0_ReKi - ParamData%FF%RefLength = 1.0_ReKi - - ! Get a unit number to use - - CALL GetNewUnit(UnitWind, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Copy things from the InitData to the ParamData - !------------------------------------------------------------------------------------------------- - - !---------------------------------------------------------------------------------------------- - ! 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(InitData%WindFileName), TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - ! Read the first binary integer from the file to get info on the type. - ! Cannot use library read routines since this is a 2-byte integer. - READ ( UnitWind, IOSTAT=TmpErrStat ) Dum_Int2 - CLOSE( UnitWind ) - - IF (TmpErrStat /= 0) THEN - CALL SetErrStat(ErrID_Fatal,' Error reading first binary integer from file "'//TRIM(InitData%WindFileName)//'."', & - ErrStat,ErrMsg,RoutineName) - RETURN - ENDIF - - - !---------------------------------------------------------------------------------------------- - ! Read the files to get the required FF data. - !---------------------------------------------------------------------------------------------- - - ! Store the binary format information so the InflowWind code can use it. - ! Also changes to IntKi from INT(2) to compare in the SELECT below - ParamData%FF%WindFileFormat = Dum_Int2 - - SELECT CASE (ParamData%FF%WindFileFormat) - - CASE ( 7, 8 ) ! TurbSim binary format - - CALL Read_TurbSim_FF(UnitWind, TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CLOSE ( UnitWind ) - RETURN - END IF - - - CASE DEFAULT - CALL SetErrStat( ErrID_Fatal, ' Error: This is not a TurbSim binary wind file type (binary format identifier: '// & - TRIM(Num2LStr(ParamData%FF%WindFileFormat))//'. This might be a Bladed style binary wind file.', & - ErrStat, ErrMsg, RoutineName ) - RETURN - - END SELECT - - - IF (ParamData%FF%Periodic) THEN - ParamData%FF%InitXPosition = 0 ! start at the hub - ParamData%FF%TotalTime = ParamData%FF%NFFSteps*ParamData%FF%FFDTime - ELSE - ParamData%FF%InitXPosition = ParamData%FF%FFYHWid ! start half the grid width ahead of the turbine - ParamData%FF%TotalTime = (ParamData%FF%NFFSteps-1)*ParamData%FF%FFDTime - ENDIF - - - !------------------------------------------------------------------------------------------------- - ! Set the InitOutput information - !------------------------------------------------------------------------------------------------- - - InitOutdata%Ver = IfW_TSFFWind_Ver - - - - RETURN - - - CONTAINS - - !==================================================================================================== - !> This subroutine reads the binary TurbSim-format FF file (.bts). It fills the FFData array with - !! velocity data for the grids and fills the FFTower array with velocities at points on the tower - !! (if data exists). - !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 - SUBROUTINE Read_TurbSim_FF(UnitWind, ErrStat, ErrMsg) - !---------------------------------------------------------------------------------------------------- - - CHARACTER(*), PARAMETER :: RoutineName="READ_TurbSim_FF" - - - ! Passed Variables: - - INTEGER(IntKi), INTENT(IN ) :: UnitWind !< unit number for the wind file - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status return value (0=no error; non-zero is error) - CHARACTER(*), INTENT( OUT) :: ErrMsg !< message about the error encountered - - ! Local Variables: - - REAL(SiKi) :: Dum_Real4 ! dummy 4-byte real number - INTEGER(B1Ki) :: Dum_Int1 ! dummy 1-byte integer - INTEGER(B2Ki) :: Dum_Int2 ! dummy 2-byte integer - INTEGER(B4Ki) :: Dum_Int4 ! dummy 4-byte integer - - INTEGER(IntKi) :: IC ! loop counter for wind components - INTEGER(IntKi) :: IT ! loop counter for time - INTEGER(IntKi) :: IY ! loop counter for y - INTEGER(IntKi) :: IZ ! loop counter for z - INTEGER(IntKi) :: NChar ! number of characters in the description string - - REAL(SiKi) :: Vslope(3) ! slope for "un-normalizing" data - REAL(SiKi) :: Voffset(3) ! offset for "un-normalizing" data - - LOGICAL :: FirstWarn ! we don't need to print warning for each character that exceeds the - CHARACTER(1024) :: DescStr ! description string contained in the file - - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - ParamData%FF%NFFComp = 3 ! this file contains 3 wind components - ErrStat = ErrID_None - ErrMsg = "" - - !------------------------------------------------------------------------------------------------- - ! Open the file - !------------------------------------------------------------------------------------------------- - - CALL OpenBInpFile (UnitWind, TRIM(InitData%WindFileName), TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - !------------------------------------------------------------------------------------------------- - ! Read the header information - !------------------------------------------------------------------------------------------------- - ! Read in the 2-byte integer. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! the file identifier, INT(2) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading the file identifier in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%Periodic = Dum_Int2 == INT( 8, B2Ki) ! the number 7 is used for non-periodic wind files; 8 is periodic wind - - - ! Read in the 4-byte integer. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! the number of grid points vertically, INT(4) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading the number of z grid points in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%NZGrids = Dum_Int4 - - - ! Read in the 4-byte integer. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! the number of grid points laterally, INT(4) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading the number of y grid points in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%NYGrids = Dum_Int4 - - - ! Read in the 4-byte integer. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! the number of tower points, INT(4) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading the number of tower points in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%NTGrids = Dum_Int4 - - - ! Read in the 4-byte integer. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! the number of time steps, INT(4) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading the number of time steps in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%NFFSteps = Dum_Int4 - - - ! Read in the 4-byte real. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! grid spacing in vertical direction (dz), REAL(4), in m - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dz in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%InvFFZD = 1.0/Dum_Real4 ! 1/dz - ParamData%FF%FFZHWid = 0.5*(ParamData%FF%NZGrids-1)*Dum_Real4 ! half the grid height - - - ! Read in the 4-byte real. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! grid spacing in lateral direction (dy), REAL(4), in m - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dy in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%InvFFYD = 1.0 / Dum_Real4 ! 1/dy - ParamData%FF%FFYHWid = 0.5*(ParamData%FF%NYGrids-1)*Dum_Real4 ! half grid grid width - - - ! Read in the 4-byte real. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! grid spacing in time (dt), REAL(4), in m/s - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading dt in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%FFDTime = Dum_Real4 - ParamData%FF%FFRate = 1.0/ParamData%FF%FFDTime - - - ! Read in the 4-byte real. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! the mean wind speed at hub height, REAL(4), in m/s - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading mean wind speed in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%MeanFFWS = Dum_Real4 - ParamData%FF%InvMFFWS = 1.0 / ParamData%FF%MeanFFWS - - - ! Read in the 4-byte real. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! height of the hub, REAL(4), in m - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading zHub in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%RefHt = Dum_Real4 - - - ! Read in the 4-byte real. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Real4 ! height of the bottom of the grid, REAL(4), in m - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading GridBase in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ParamData%FF%GridBase = Dum_Real4 - - ! ZGOffset = ParamData%FF%RefHt - ParamData%FF%GridBase - ParamData%FF%FFZHWid - - - !---------------------------------------------------------------------------------------------- - ! Read the binary scaling factors - !---------------------------------------------------------------------------------------------- - - DO IC = 1,ParamData%FF%NFFComp - ! Read in the 4-byte real. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Vslope(IC) ! the IC-component slope for scaling, REAL(4) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading Vslope('//Num2LStr(IC)//') in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - - ! Read in the 4-byte real. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Voffset(IC) ! the IC-component offset for scaling, REAL(4) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading Voffset('//Num2LStr(IC)//') in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - ENDDO !IC - - - !---------------------------------------------------------------------------------------------- - ! Read the description string: "Generated by TurbSim (vx.xx, dd-mmm-yyyy) on dd-mmm-yyyy at hh:mm:ss." - !---------------------------------------------------------------------------------------------- - - ! Read in the 4-byte integer. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int4 ! the number of characters in the description string, max 200, INT(4) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading NCHAR in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - nchar = Dum_Int4 - - DescStr = '' ! Initialize the description string - FirstWarn = .true. - - DO IC=1,nchar - - ! Read in the 1-byte integer. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int1 ! the ASCII integer representation of the character, INT(1) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading description line in the FF binary file "'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - IF ( LEN(DescStr) >= IC ) THEN - DescStr(IC:IC) = ACHAR( Dum_Int1 ) ! converted ASCII characters - ELSEIF ( FirstWarn ) THEN - FirstWarn = .FALSE. - CALL SetErrStat( ErrID_Info, ' Description string was too long for variable.'//TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - ENDIF - - ENDDO !IC - - - !------------------------------------------------------------------------------------------------- - ! Get the grid and tower velocities - !------------------------------------------------------------------------------------------------- - - ! this could take a while, so we'll write a message indicating what's going on: - - CALL WrScr( NewLine//' Reading a '//TRIM( Num2LStr(ParamData%FF%NYGrids) )//'x'//TRIM( Num2LStr(ParamData%FF%NZGrids) )// & - ' grid ('//TRIM( Num2LStr(ParamData%FF%FFYHWid*2) )//' m wide, '// & - TRIM( Num2LStr(ParamData%FF%GridBase) )//' m to '// & - TRIM( Num2LStr(ParamData%FF%GridBase+ParamData%FF%FFZHWid*2) )//& - ' m above ground) with a characteristic wind speed of '// & - TRIM( Num2LStr(ParamData%FF%MeanFFWS) )//' m/s. '//TRIM(DescStr) ) - - - !---------------------------------------------------------------------------------------------- - ! Allocate arrays for the FF grid as well as the tower points, if they exist - !---------------------------------------------------------------------------------------------- - - IF ( .NOT. ALLOCATED( ParamData%FF%FFData ) ) THEN - CALL AllocAry( ParamData%FF%FFData, ParamData%FF%NZGrids, ParamData%FF%NYGrids, ParamData%FF%NFFComp, ParamData%FF%NFFSteps, & - 'Full-field wind data array.', TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - ENDIF - - - IF ( ParamData%FF%NTGrids > 0 ) THEN - - IF ( .NOT. ALLOCATED( ParamData%FF%FFTower ) ) THEN - CALL AllocAry( ParamData%FF%FFTower, ParamData%FF%NFFComp, ParamData%FF%NTGrids, ParamData%FF%NFFSteps, & - 'Tower wind file data array.', TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - ENDIF - - ENDIF - - !------------------------------------------------------------------------------------------------- - ! Read the 16-bit data and scale it to 32-bit reals - !------------------------------------------------------------------------------------------------- - - ! Loop through time. - - DO IT=1,ParamData%FF%NFFSteps - - !........................................................................................... - ! Read grid data at this time step. - !........................................................................................... - - DO IZ=1,ParamData%FF%NZGrids - ! Zgrid(IZ) = Z1 + (IZ-1)*dz ! Vertical location of grid data point, in m relative to ground - - DO IY=1,ParamData%FF%NYGrids - ! Ygrid(IY) = -0.5*(ny-1)*dy + (IY-1)*dy ! Horizontal location of grid data point, in m relative to tower centerline - - DO IC=1,ParamData%FF%NFFComp ! number of wind components (U, V, W) - - ! Read in the 2-byte integer. Can't use library read routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! normalized wind-component, INT(2) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading grid wind components in the FF binary file "'// & - TRIM( InitData%WindFileName )//'."', ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - ParamData%FF%FFData(IZ,IY,IC,IT) = ( Dum_Int2 - Voffset(IC) ) / VSlope(IC) - - ENDDO !IC - - ENDDO !IY - - ENDDO ! IZ - - - !........................................................................................... - ! Read the tower data at this time step. - !........................................................................................... - - DO IZ=1,ParamData%FF%NTGrids ! If NTGrids<1, there are no tower points & FFTower is not allocated - - ! Ytower = 0 ! Lateral location of the tower data point, in m relative to tower centerline - ! Ztower(IZ) = Z1 - (IZ-1)*dz ! Vertical location of tower data point, in m relative to ground - - DO IC=1,ParamData%FF%NFFComp ! number of wind components - - ! Read in a 2-byte integer. Can't use library routines for this. - READ (UnitWind, IOSTAT=TmpErrStat) Dum_Int2 ! normalized wind-component, INT(2) - IF ( TmpErrStat /= 0 ) THEN - CALL SetErrStat( ErrID_Fatal, ' Error reading tower wind components in the FF binary file "'//TRIM(InitData%WindFileName)//'."'& - , ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - ParamData%FF%FFTower(IC,IZ,IT) = ( Dum_Int2 - Voffset(IC) ) / VSlope(IC) ! wind-component scaled to m/s - - ENDDO !IC - - ENDDO ! IZ - - - ENDDO ! IT - - !------------------------------------------------------------------------------------------------- - ! close the file and return - !------------------------------------------------------------------------------------------------- - - CLOSE ( UnitWind ) - - IF ( ParamData%FF%Periodic ) THEN - TmpErrMsg = ' Processed '//TRIM( Num2LStr( ParamData%FF%NFFSteps ) )//' time steps of '// & - TRIM( Num2LStr ( ParamData%FF%FFRate ) )//'-Hz full-field data (period of '// & - TRIM( Num2LStr( ParamData%FF%FFDTime*( ParamData%FF%NFFSteps ) ) )//' seconds).' - ELSE - TmpErrMsg = ' Processed '//TRIM( Num2LStr( ParamData%FF%NFFSteps ) )//' time steps of '// & - TRIM( Num2LStr ( ParamData%FF%FFRate ) )//'-Hz full-field data ('// & - TRIM( Num2LStr( ParamData%FF%FFDTime*( ParamData%FF%NFFSteps - 1 ) ) )//' seconds).' - ENDIF - - CALL WrScr( NewLine//TRIM(TmpErrMsg) ) ! Note: the TmpErrMsg gets used below for the summary file - - - - !------------------------------------------------------------------------------------------------- - ! Write to the summary file - !------------------------------------------------------------------------------------------------- - - IF ( InitData%SumFileUnit > 0 ) THEN - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) 'TurbSim wind type. Read by InflowWind sub-module '//TRIM(IfW_TSFFWind_Ver%Name)// & - ' '//TRIM(IfW_TSFFWind_Ver%Ver) - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) TRIM(TmpErrMsg) - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' FileName: '//TRIM(InitData%WindFileName) - WRITE(InitData%SumFileUnit,'(A34,I3)', IOSTAT=TmpErrStat) ' Binary file format id: ',ParamData%FF%WindFileFormat - WRITE(InitData%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Reference height (m): ',ParamData%FF%RefHt - WRITE(InitData%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Timestep (s): ',ParamData%FF%FFDTime - WRITE(InitData%SumFileUnit,'(A34,I12)', IOSTAT=TmpErrStat) ' Number of timesteps: ',ParamData%FF%NFFSteps - WRITE(InitData%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Mean windspeed (m/s): ',ParamData%FF%MeanFFWS - WRITE(InitData%SumFileUnit,'(A34,L1)', IOSTAT=TmpErrStat) ' Windfile is periodic: ',ParamData%FF%Periodic - WRITE(InitData%SumFileUnit,'(A34,L1)', IOSTAT=TmpErrStat) ' Windfile includes tower: ',ParamData%FF%NTGrids > 0 - - IF ( ParamData%FF%Periodic ) THEN - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Time range (s): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(ParamData%FF%TotalTime))//' ]' - ELSE ! Shift the time range to compensate for the shifting of the wind grid - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Time range (s): [ '// & - TRIM(Num2LStr(-ParamData%FF%InitXPosition*ParamData%FF%InvMFFWS))//' : '// & - TRIM(Num2LStr(ParamData%FF%TotalTime-ParamData%FF%InitXPosition*ParamData%FF%InvMFFWS))//' ]' - ENDIF - - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Y range (m): [ '// & - TRIM(Num2LStr(-ParamData%FF%FFYHWid))//' : '//TRIM(Num2LStr(ParamData%FF%FFYHWid))//' ]' - - IF ( ParamData%FF%NTGrids > 0 ) THEN - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Z range (m): [ '// & - TRIM(Num2LStr(0.0_ReKi))//' : '//TRIM(Num2LStr(ParamData%FF%RefHt + ParamData%FF%FFZHWid))//' ]' - ELSE - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Z range (m): [ '// & - TRIM(Num2LStr(ParamData%FF%RefHt - ParamData%FF%FFZHWid))//' : '//TRIM(Num2LStr(ParamData%FF%RefHt + ParamData%FF%FFZHWid))//' ]' - ENDIF - - - ! We are assuming that if the last line was written ok, then all of them were. - IF (TmpErrStat /= 0_IntKi) THEN - CALL SetErrStat(ErrID_Fatal,'Error writing to summary file.',ErrStat,ErrMsg,RoutineName) - RETURN - ENDIF - ENDIF - - - RETURN - - END SUBROUTINE READ_TurbSim_FF - - END SUBROUTINE IfW_TSFFWind_Init -!==================================================================================================== - - -!==================================================================================================== -!> This routine computes the wind speed at each of the PositionXYZ points. -SUBROUTINE IfW_TSFFWind_CalcOutput(Time, PositionXYZ, p, Velocity, MiscVars, ErrStat, ErrMsg) - - IMPLICIT NONE - - - CHARACTER(*), PARAMETER :: RoutineName="IfW_TSFFWind_CalcOutput" - - - ! Passed Variables - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - REAL(ReKi), INTENT(IN ) :: PositionXYZ(:,:) !< Array of XYZ coordinates, 3xN - TYPE(IfW_TSFFWind_ParameterType), INTENT(IN ) :: p !< Parameters - REAL(ReKi), INTENT(INOUT) :: Velocity(:,:) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) - TYPE(IfW_TSFFWind_MiscVarType), INTENT(INOUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message - - - - CALL IfW_FFWind_CalcOutput(Time, PositionXYZ, p%FF, Velocity, ErrStat, ErrMsg) - - - RETURN - -END SUBROUTINE IfW_TSFFWind_CalcOutput -!==================================================================================================== -!> This subroutine cleans up any data that is still allocated. The (possibly) open files are -!! closed in InflowWindMod. -!! -!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -SUBROUTINE IfW_TSFFWind_End( p, m, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_TSFFWind_End" - - - - ! Passed Variables - TYPE(IfW_TSFFWind_ParameterType), INTENT(INOUT) :: p !< Parameters - TYPE(IfW_TSFFWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Local Variables - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - !-=- Initialize the routine -=- - - ErrMsg = '' - ErrStat = ErrID_None - - - - ! Destroy parameter data - - CALL IfW_TSFFWind_DestroyParam( p, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - - - ! Destroy the misc data - - CALL IfW_TSFFWind_DestroyMisc( m, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - - - -END SUBROUTINE IfW_TSFFWind_End - -!==================================================================================================== -END MODULE IfW_TSFFWind diff --git a/modules/inflowwind/src/IfW_TSFFWind.txt b/modules/inflowwind/src/IfW_TSFFWind.txt deleted file mode 100644 index 71b9e9c753..0000000000 --- a/modules/inflowwind/src/IfW_TSFFWind.txt +++ /dev/null @@ -1,33 +0,0 @@ -################################################################################################################################### -# Registry for IfW_TSFFWind, creates MODULE IfW_TSFFWind_Types -# Module IfW_TSFFWind_Types contains all of the user-defined types needed in IfW_TSFFWind. It also contains copy, destroy, pack, and -# unpack routines associated with each defined data types. -################################################################################################################################### -# Entries are of the form -# keyword -################################################################################################################################### - -include Registry_NWTC_Library.txt -usefrom IfW_FFWind_Base.txt - - -######################### - -typedef IfW_TSFFWind/IfW_TSFFWind InitInputType CHARACTER(1024) WindFileName - - - "Name of the wind file to use" - -typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - - - -# Init Output -typedef ^ InitOutputType ProgDesc Ver - - - "Version information off FFWind submodule" - - - -# ..... Misc/Optimization variables................................................................................................. -# Define any data that are used only for efficiency purposes (these variables are not associated with time): -# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType IntKi dummy - 0 - "An Index into the TData array" - - -# ..... Parameters ................................................................................................................ -# Define parameters here: -# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType IfW_FFWind_ParameterType FF - - - "Parameters used in all full-field wind types" - - diff --git a/modules/inflowwind/src/IfW_TSFFWind_Types.f90 b/modules/inflowwind/src/IfW_TSFFWind_Types.f90 deleted file mode 100644 index 5f52f9c1c9..0000000000 --- a/modules/inflowwind/src/IfW_TSFFWind_Types.f90 +++ /dev/null @@ -1,788 +0,0 @@ -!STARTOFREGISTRYGENERATEDFILE 'IfW_TSFFWind_Types.f90' -! -! WARNING This file is generated automatically by the FAST registry. -! Do not edit. Your changes to this file will be lost. -! -! FAST Registry -!********************************************************************************************************************************* -! IfW_TSFFWind_Types -!................................................................................................................................. -! This file is part of IfW_TSFFWind. -! -! Copyright (C) 2012-2016 National Renewable Energy Laboratory -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -! -! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. -! -!********************************************************************************************************************************* -!> This module contains the user-defined types needed in IfW_TSFFWind. It also contains copy, destroy, pack, and -!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE IfW_TSFFWind_Types -!--------------------------------------------------------------------------------------------------------------------------------- -USE IfW_FFWind_Base_Types -USE NWTC_Library -IMPLICIT NONE -! ========= IfW_TSFFWind_InitInputType ======= - TYPE, PUBLIC :: IfW_TSFFWind_InitInputType - CHARACTER(1024) :: WindFileName !< Name of the wind file to use [-] - INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file (-1 for none). Provided by IfW. [-] - END TYPE IfW_TSFFWind_InitInputType -! ======================= -! ========= IfW_TSFFWind_InitOutputType ======= - TYPE, PUBLIC :: IfW_TSFFWind_InitOutputType - TYPE(ProgDesc) :: Ver !< Version information off FFWind submodule [-] - END TYPE IfW_TSFFWind_InitOutputType -! ======================= -! ========= IfW_TSFFWind_MiscVarType ======= - TYPE, PUBLIC :: IfW_TSFFWind_MiscVarType - INTEGER(IntKi) :: dummy = 0 !< An Index into the TData array [-] - END TYPE IfW_TSFFWind_MiscVarType -! ======================= -! ========= IfW_TSFFWind_ParameterType ======= - TYPE, PUBLIC :: IfW_TSFFWind_ParameterType - TYPE(IfW_FFWind_ParameterType) :: FF !< Parameters used in all full-field wind types [-] - END TYPE IfW_TSFFWind_ParameterType -! ======================= -CONTAINS - SUBROUTINE IfW_TSFFWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_TSFFWind_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(IfW_TSFFWind_InitInputType), INTENT(INOUT) :: DstInitInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_CopyInitInput' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitInputData%WindFileName = SrcInitInputData%WindFileName - DstInitInputData%SumFileUnit = SrcInitInputData%SumFileUnit - END SUBROUTINE IfW_TSFFWind_CopyInitInput - - SUBROUTINE IfW_TSFFWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_TSFFWind_InitInputType), INTENT(INOUT) :: InitInputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_DestroyInitInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_TSFFWind_DestroyInitInput - - SUBROUTINE IfW_TSFFWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_TSFFWind_InitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_PackInitInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName - Int_BufSz = Int_BufSz + 1 ! SumFileUnit - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%WindFileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = InData%SumFileUnit - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_TSFFWind_PackInitInput - - SUBROUTINE IfW_TSFFWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_TSFFWind_InitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_UnPackInitInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%WindFileName) - OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%SumFileUnit = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_TSFFWind_UnPackInitInput - - SUBROUTINE IfW_TSFFWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_TSFFWind_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(IfW_TSFFWind_InitOutputType), INTENT(INOUT) :: DstInitOutputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_CopyInitOutput' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_TSFFWind_CopyInitOutput - - SUBROUTINE IfW_TSFFWind_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_TSFFWind_InitOutputType), INTENT(INOUT) :: InitOutputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_DestroyInitOutput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_TSFFWind_DestroyInitOutput - - SUBROUTINE IfW_TSFFWind_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_TSFFWind_InitOutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_PackInitOutput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Ver - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Ver - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Ver - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE IfW_TSFFWind_PackInitOutput - - SUBROUTINE IfW_TSFFWind_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_TSFFWind_InitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_UnPackInitOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_TSFFWind_UnPackInitOutput - - SUBROUTINE IfW_TSFFWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_TSFFWind_MiscVarType), INTENT(IN) :: SrcMiscData - TYPE(IfW_TSFFWind_MiscVarType), INTENT(INOUT) :: DstMiscData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_CopyMisc' -! - ErrStat = ErrID_None - ErrMsg = "" - DstMiscData%dummy = SrcMiscData%dummy - END SUBROUTINE IfW_TSFFWind_CopyMisc - - SUBROUTINE IfW_TSFFWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_TSFFWind_MiscVarType), INTENT(INOUT) :: MiscData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_DestroyMisc' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_TSFFWind_DestroyMisc - - SUBROUTINE IfW_TSFFWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_TSFFWind_MiscVarType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_PackMisc' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! dummy - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = InData%dummy - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_TSFFWind_PackMisc - - SUBROUTINE IfW_TSFFWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_TSFFWind_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%dummy = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_TSFFWind_UnPackMisc - - SUBROUTINE IfW_TSFFWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_TSFFWind_ParameterType), INTENT(IN) :: SrcParamData - TYPE(IfW_TSFFWind_ParameterType), INTENT(INOUT) :: DstParamData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_CopyParam' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL IfW_FFWind_CopyParam( SrcParamData%FF, DstParamData%FF, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_TSFFWind_CopyParam - - SUBROUTINE IfW_TSFFWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_TSFFWind_ParameterType), INTENT(INOUT) :: ParamData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_DestroyParam' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL IfW_FFWind_DestroyParam( ParamData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_TSFFWind_DestroyParam - - SUBROUTINE IfW_TSFFWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_TSFFWind_ParameterType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_PackParam' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype - CALL IfW_FFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! FF - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! FF - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! FF - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL IfW_FFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE IfW_TSFFWind_PackParam - - SUBROUTINE IfW_TSFFWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_TSFFWind_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_TSFFWind_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_FFWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_TSFFWind_UnPackParam - -END MODULE IfW_TSFFWind_Types -!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/IfW_UniformWind.f90 b/modules/inflowwind/src/IfW_UniformWind.f90 deleted file mode 100644 index 516dc25408..0000000000 --- a/modules/inflowwind/src/IfW_UniformWind.f90 +++ /dev/null @@ -1,1333 +0,0 @@ -!> This module contains all the data and procedures that define uniform wind files (formerly known as -!! hub-height files). This could more accurately be called a point wind file since the wind speed at -!! any point is calculated by shear applied to the point where wind is defined. It is basically uniform -!! wind over the rotor disk. The entire file is read on initialization, then the columns that make up -!! the wind file are interpolated to the time requested, and wind is calculated based on the location -!! in space. -!! -!! the file contains header information (rows that contain "!"), followed by numeric data stored in -!! 9 columns (if only 8 are listed, Upflow is assumed to be 0): -!! |Column | Description | Variable Name | Units| -!! |-------|-----------------------------|---------------|------| -!! | 1 | Time | Time | [s] | -!! | 2 | Horizontal wind speed | V | [m/s]| -!! | 3 | Wind direction | Delta | [deg]| -!! | 4 | Vertical wind speed | VZ | [m/s]| -!! | 5 | Horizontal linear shear | HLinShr | [-] | -!! | 6 | Vertical power-law shear | VShr | [-] | -!! | 7 | Vertical linear shear | VLinShr | [-] | -!! | 8 | Gust (horizontal) velocity | VGust | [m/s]| -!! | 9 | Upflow angle | Upflow | [deg]| -!! -!! The horizontal wind speed at (X, Y, Z) is then calculated using the interpolated columns by \n -!! \f{eqnarray}{ V_h & = & V \, \left( \frac{Z}{Z_{Ref}} \right) ^ {VShr} & \mbox{power-law wind shear} \\ -!! & + & V \, \frac{H_{LinShr}}{RefWid} \, \left( Y \cos(Delta) + X \sin(Delta) \right) & \mbox{horizontal linear shear} \\ -!! & + & V \, \frac{V_{LinShr}}{RefWid} \, \left( Z-Z_{Ref} \right) & \mbox{vertical linear shear} \\ -!! & + & V_{Gust} & \mbox{gust speed} -!! \f} -MODULE IfW_UniformWind -!---------------------------------------------------------------------------------------------------- -!! Feb 2013 v2.00.00 A. Platt -!! -- updated to the new framework -!! -- Note: Jacobians are not included in this version. -!! -!! Feb 2015 v2.01.00 A. Platt -!! -- Further updates to the new framework -!! -- name change from 'hub-height wind files' to 'Uniform wind files'. -!! -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2015-2016 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** - - USE NWTC_Library - USE IfW_UniformWind_Types - - IMPLICIT NONE - PRIVATE - - TYPE(ProgDesc), PARAMETER :: IfW_UniformWind_Ver = ProgDesc( 'IfW_UniformWind', '', '' ) - - PUBLIC :: IfW_UniformWind_Init - PUBLIC :: IfW_UniformWind_End - PUBLIC :: IfW_UniformWind_CalcOutput - PUBLIC :: IfW_UniformWind_JacobianPInput - PUBLIC :: IfW_UniformWind_GetOP - - PUBLIC :: Uniform_to_FFWind - PUBLIC :: FFWind_to_Uniform - PUBLIC :: WrUniformWind - -CONTAINS - -!==================================================================================================== - -!---------------------------------------------------------------------------------------------------- -!> A subroutine to initialize the UniformWind module. It reads the uniform wind file and stores the data in an -!! array to use later. It requires an initial reference height (hub height) and width (rotor diameter), -!! both in meters, which are used to define the volume where wind velocities will be calculated. This -!! information is necessary because of the way the shears are defined. -!! -!! @note This routine does not conform to the framework. The InputType has been replaced with just -!! the PositionXYZ array. -!! @date 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -!---------------------------------------------------------------------------------------------------- -SUBROUTINE IfW_UniformWind_Init(InitData, ParamData, MiscVars, InitOutData, ErrStat, ErrMsg) - - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_UniformWind_Init" - - - ! Passed Variables - TYPE(IfW_UniformWind_InitInputType), INTENT(IN ) :: InitData !< Input data for initialization - TYPE(IfW_UniformWind_ParameterType), INTENT( OUT) :: ParamData !< Parameters - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - TYPE(IfW_UniformWind_InitOutputType), INTENT( OUT) :: InitOutData !< Initial output - - - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< A message about the error - - ! local variables - - INTEGER(IntKi), PARAMETER :: MaxNumCols = 9 ! maximum number of columns in the Uniform file - INTEGER(IntKi) :: NumCols ! Number of columns in the Uniform file - REAL(ReKi) :: TmpData(MaxNumCols) ! Temp variable for reading all columns from a line - INTEGER(IntKi) :: LineNo - REAL(ReKi) :: DelDiff ! Temp variable for storing the direction difference - - INTEGER(IntKi) :: I - INTEGER(IntKi) :: ILine ! Counts the line number in the file - INTEGER(IntKi), PARAMETER :: MaxTries = 100 - TYPE(FileInfoType) :: InFileInfo !< The derived type for holding the full input file for parsing -- we may pass this in the future - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat ! Temp variable for the error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - !------------------------------------------------------------------------------------------------- - ! Set the Error handling variables - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = "" - - !------------------------------------------------------------------------------------------------- - ! Check that it's not already initialized - !------------------------------------------------------------------------------------------------- - - IF ( MiscVars%TimeIndex /= 0 ) THEN - CALL SetErrStat(ErrID_Warn,' UniformWind has already been initialized.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - - !------------------------------------------------------------------------------------------------- - ! Copy things from the InitData to the ParamData - !------------------------------------------------------------------------------------------------- - - ParamData%RefHt = InitData%ReferenceHeight - ParamData%RefLength = InitData%RefLength - - ! Read in the data from a file, or copy from the passed InFileInfo. After this, the InFileInfo - ! should contain only a table -- all comments and empty lines have been stripped out - IF ( InitData%UseInputFile ) THEN - CALL ProcessComFile( InitData%WindFileName, InFileInfo, TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - ELSE - CALL NWTC_Library_CopyFileInfoType( InitData%PassedFileData, InFileInfo, MESH_NEWCOPY, TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - ENDIF - - ! For diagnostic purposes, the following can be used to display the contents - ! of the InFileInfo data structure. - ! call Print_FileInfo_Struct( CU, InFileInfo ) ! CU is the screen -- different number on different systems. - - - !------------------------------------------------------------------------------------------------- - ! Allocate the data arrays - !------------------------------------------------------------------------------------------------- - - ParamData%NumDataLines = InFileInfo%NumLines - CALL Alloc_ParamDataArrays( ParamData, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Store the data arrays - !------------------------------------------------------------------------------------------------- - - ! Check if 9 columns - NumCols = MaxNumCols - LineNo = 1 ! Start at begining - CALL ParseAry( InFileInfo, LineNo, "Wind type 2 line", TmpData(1:NumCols), NumCols, TmpErrStat, TmpErrMsg ) - if (TmpErrStat /= 0) then - ! assume the upflow is 0 and try reading the rest of the files - CALL SetErrStat(ErrID_Info,' Could not read upflow column in uniform wind files. Assuming upflow is 0.', ErrStat, ErrMsg, RoutineName) - NumCols = NumCols - 1 - end if - - - ! Parse the data and store it - LineNo = 1 - DO I=1,ParamData%NumDataLines - CALL ParseAry( InFileInfo, LineNo, "Wind type 2 file line", TmpData(1:NumCols), NumCols, TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - - ParamData%Tdata( I) = TmpData(1) - ParamData%V( I) = TmpData(2) - ParamData%Delta( I) = TmpData(3)*D2R - ParamData%VZ( I) = TmpData(4) - ParamData%HShr( I) = TmpData(5) - ParamData%VShr( I) = TmpData(6) - ParamData%VLinShr(I) = TmpData(7) - ParamData%VGust( I) = TmpData(8) - - if (NumCols > 8) ParamData%Upflow( I) = TmpData(9)*D2R ! otherwise, use default value from initialization in Alloc_ParamDataArrays() - END DO !I - - - - !------------------------------------------------------------------------------------------------- - ! Make sure the wind direction isn't jumping more than 180 degrees between any 2 consecutive - ! input times. (Avoids interpolation errors with modular arithemetic.) - !------------------------------------------------------------------------------------------------- - - DO I=2,ParamData%NumDataLines - - ILine = 1 - - DO WHILE ( ILine < MaxTries ) - - DelDiff = ( ParamData%Delta(I) - ParamData%Delta(I-1) ) - - IF ( ABS( DelDiff ) < Pi ) EXIT ! exit inner loop - - ParamData%Delta(I) = ParamData%Delta(I) - SIGN( TwoPi, DelDiff ) - - ILine = ILine + 1 - - END DO - - IF ( ILine >= MaxTries ) THEN - TmpErrMsg= ' Error calculating wind direction from uniform wind file. ParamData%Delta(' & - // TRIM(Num2LStr(I )) // ') = ' // TRIM(Num2LStr(ParamData%Delta(I))) // '; ParamData%Delta(' & - // TRIM(Num2LStr(I+1)) // ') = ' // TRIM(Num2LStr(ParamData%Delta(I+1))) - CALL SetErrStat(ErrID_Fatal,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - END IF - - - END DO !I - - !------------------------------------------------------------------------------------------------- - ! Find out information on the timesteps and range - !------------------------------------------------------------------------------------------------- - - ! Uniform timesteps - IF ( ParamData%NumDataLines > 3 ) THEN - - InitOutData%WindFileConstantDT = .TRUE. - InitOutData%WindFileDT = ParamData%Tdata(2) - ParamData%Tdata(1) - - DO I=3,ParamData%NumDataLines - - IF ( .NOT. EqualRealNos( (ParamData%Tdata(I ) - ParamData%Tdata(I-1) ), REAL(InitOutData%WindFileDT,ReKi )) ) THEN - InitOutData%WindFileConstantDT = .FALSE. - EXIT - END IF - - END DO !I - - ELSE - - ! There aren't enough points to check, so report that the timesteps are not uniform - InitOutData%WindFileConstantDT = .FALSE. - InitOutData%WindFileDT = 0.0_ReKi - - END IF - - - ! Time range - InitOutData%WindFileTRange(1) = ParamData%Tdata(1) - InitOutData%WindFileTRange(2) = ParamData%Tdata(ParamData%NumDataLines) - - ! Number of timesteps - InitOutData%WindFileNumTSteps = ParamData%NumDataLines - - !------------------------------------------------------------------------------------------------- - ! Print warnings and messages - !------------------------------------------------------------------------------------------------- - ! CALL WrScr( ' Processed '//TRIM( Num2LStr( ParamData%NumDataLines ) )//' records of uniform wind data from '''// & - ! TRIM(ADJUSTL(InitData%WindFileName))//'''') - - - IF ( ParamData%Tdata(1) > 0.0 ) THEN - TmpErrMsg= 'The uniform wind file : "'//TRIM(ADJUSTL(InitData%WindFileName))// & - '" starts at a time '//'greater than zero. Interpolation errors may result.' - CALL SetErrStat(ErrID_Warn,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - ENDIF - - IF ( ParamData%NumDataLines == 1 ) THEN - TmpErrMsg= ' Only 1 line in uniform wind file. Steady, horizontal wind speed at the hub height is '// & - TRIM(Num2LStr(ParamData%V(1)))//' m/s.' - CALL SetErrStat(ErrID_Info,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - END IF - - - - !------------------------------------------------------------------------------------------------- - ! Write to the summary file - !------------------------------------------------------------------------------------------------- - - IF ( InitData%SumFileUnit > 0 ) THEN - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) 'Uniform wind. Module '//TRIM(IfW_UniformWind_Ver%Name)// & - ' '//TRIM(IfW_UniformWind_Ver%Ver) - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' FileName: '//TRIM(InitData%WindFileName) - WRITE(InitData%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Reference height (m): ',ParamData%RefHt - WRITE(InitData%SumFileUnit,'(A34,G12.4)',IOSTAT=TmpErrStat) ' Reference length (m): ',ParamData%RefLength - WRITE(InitData%SumFileUnit,'(A32,I8)', IOSTAT=TmpErrStat) ' Number of data lines: ',ParamData%NumDataLines - WRITE(InitData%SumFileUnit,'(A)', IOSTAT=TmpErrStat) ' Time range (s): [ '// & - TRIM(Num2LStr(InitOutData%WindFileTRange(1)))//' : '//TRIM(Num2LStr(InitOutData%WindFileTRange(2)))//' ]' - - ! We are assuming that if the last line was written ok, then all of them were. - IF (TmpErrStat /= 0_IntKi) THEN - CALL SetErrStat(ErrID_Fatal,'Error writing to summary file.',ErrStat,ErrMsg,RoutineName) - RETURN - ENDIF - ENDIF - - - - !------------------------------------------------------------------------------------------------- - ! Set the initial index into the time array (it indicates that we've initialized the module, too) - ! and initialize the spatial scaling for the wind calculations - !------------------------------------------------------------------------------------------------- - - MiscVars%TimeIndex = 1 - - - !------------------------------------------------------------------------------------------------- - ! Set the InitOutput information - !------------------------------------------------------------------------------------------------- - - InitOutdata%Ver = IfW_UniformWind_Ver - - - RETURN - -END SUBROUTINE IfW_UniformWind_Init - -SUBROUTINE Alloc_ParamDataArrays( ParamData, ErrStat, ErrMsg ) - - IMPLICIT NONE - CHARACTER(*), PARAMETER :: RoutineName="Alloc_ParamDataArrays" - - TYPE(IfW_UniformWind_ParameterType), INTENT(INOUT) :: ParamData !< Parameters - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< A message about the error - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat ! Temp variable for the error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! Temporary error message - - ErrStat = ErrID_None - ErrMsg = "" - - !------------------------------------------------------------------------------------------------- - ! Allocate arrays for the uniform wind data - !------------------------------------------------------------------------------------------------- - ! BJJ note: If the subroutine AllocAry() is called, the CVF compiler with A2AD does not work - ! properly. The arrays are not properly read even though they've been allocated. - ! ADP note: the above note may or may not apply after conversion to the modular framework in 2013 - !------------------------------------------------------------------------------------------------- - - IF (.NOT. ALLOCATED(ParamData%Tdata) ) THEN - CALL AllocAry( ParamData%Tdata, ParamData%NumDataLines, 'Uniform wind time', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - IF (.NOT. ALLOCATED(ParamData%V) ) THEN - CALL AllocAry( ParamData%V, ParamData%NumDataLines, 'Uniform wind horizontal wind speed', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - IF (.NOT. ALLOCATED(ParamData%Delta) ) THEN - CALL AllocAry( ParamData%Delta, ParamData%NumDataLines, 'Uniform wind direction', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - IF (.NOT. ALLOCATED(ParamData%VZ) ) THEN - CALL AllocAry( ParamData%VZ, ParamData%NumDataLines, 'Uniform vertical wind speed', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - IF (.NOT. ALLOCATED(ParamData%HShr) ) THEN - CALL AllocAry( ParamData%HShr, ParamData%NumDataLines, 'Uniform horizontal linear shear', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - IF (.NOT. ALLOCATED(ParamData%VShr) ) THEN - CALL AllocAry( ParamData%VShr, ParamData%NumDataLines, 'Uniform vertical power-law shear exponent', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - IF (.NOT. ALLOCATED(ParamData%VLinShr) ) THEN - CALL AllocAry( ParamData%VLinShr, ParamData%NumDataLines, 'Uniform vertical linear shear', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - IF (.NOT. ALLOCATED(ParamData%VGust) ) THEN - CALL AllocAry( ParamData%VGust, ParamData%NumDataLines, 'Uniform gust velocity', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - - IF (.NOT. ALLOCATED(ParamData%Upflow) ) THEN - CALL AllocAry( ParamData%Upflow, ParamData%NumDataLines, 'Uniform wind upflow', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) RETURN - END IF - ParamData%Upflow = 0.0_ReKi - -END SUBROUTINE Alloc_ParamDataArrays - -!==================================================================================================== - -!------------------------------------------------------------------------------------------------- -!> This routine and its subroutines calculate the wind velocity at a set of points given in -!! PositionXYZ. The UVW velocities are returned in Velocity -!! -!! @note This routine does not satisfy the Modular framework. -!! @date 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -!------------------------------------------------------------------------------------------------- -SUBROUTINE IfW_UniformWind_CalcOutput(Time, PositionXYZ, p, Velocity, m, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_UniformWind_CalcOutput" - - - ! Passed Variables - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - REAL(ReKi), INTENT(IN ) :: PositionXYZ(:,:) !< Array of XYZ coordinates, 3xN - TYPE(IfW_UniformWind_ParameterType), INTENT(IN ) :: p !< Parameters - REAL(ReKi), INTENT(INOUT) :: Velocity(:,:) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message - - - ! local variables - INTEGER(IntKi) :: NumPoints ! Number of points specified by the PositionXYZ array - TYPE(IfW_UniformWind_Intrp) :: op ! interpolated values of InterpParams - INTEGER(IntKi) :: PointNum ! a loop counter for the current point - - ! temporary variables - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - - !------------------------------------------------------------------------------------------------- - ! Initialize some things - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = "" - - ! The array is transposed so that the number of points is the second index, x/y/z is the first. - ! This is just in case we only have a single point, the SIZE command returns the correct number of points. - NumPoints = SIZE(PositionXYZ,DIM=2) - - - !------------------------------------------------------------------------------------------------- - !> 1. Linearly interpolate parameters in time (or use nearest-neighbor to extrapolate) - !! (compare with nwtc_num::interpstpreal) - !------------------------------------------------------------------------------------------------- - CALL InterpParams(Time, p, m, op) - - ! Step through all the positions and get the velocities - !OMP PARALLEL default(shared) if(NumPoints>1000) - !OMP do private(PointNum, TmpErrStat, TmpErrMsg ) schedule(runtime) - DO PointNum = 1, NumPoints - - ! Calculate the velocity for the position - call GetWindSpeed(PositionXYZ(:,PointNum), p, op, Velocity(:,PointNum), TmpErrStat, TmpErrMsg) - - ! Error handling - !CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF (TmpErrStat >= AbortErrLev) THEN - TmpErrMsg= trim(TmpErrMsg)//" Error calculating the wind speed at position ("// & - TRIM(Num2LStr(PositionXYZ(1,PointNum)))//", "// & - TRIM(Num2LStr(PositionXYZ(2,PointNum)))//", "// & - TRIM(Num2LStr(PositionXYZ(3,PointNum)))//") in the wind-file coordinates" - !OMP CRITICAL ! Needed to avoid data race on ErrStat and ErrMsg - ErrStat = ErrID_None - ErrMsg = "" - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - !OMP END CRITICAL - ENDIF - - ENDDO - !OMP END DO - !OMP END PARALLEL - - IF (ErrStat >= AbortErrLev) RETURN ! Return cannot be in parallel loop - - RETURN - -END SUBROUTINE IfW_UniformWind_CalcOutput -!+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- -!> This subroutine linearly interpolates the parameters that are used to compute uniform -!! wind. -SUBROUTINE InterpParams(Time, p, m, op) - - ! Passed Variables - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - TYPE(IfW_UniformWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables (index) - - TYPE(IfW_UniformWind_Intrp) , INTENT( OUT) :: op !< interpolated V values at input TIME - - - ! Local Variables - REAL(ReKi) :: slope ! temporary storage for slope (in time) used in linear interpolation - - - !------------------------------------------------------------------------------------------------- - ! Linearly interpolate in time (or used nearest-neighbor to extrapolate) - ! (compare with NWTC_Num.f90\InterpStpReal) - !------------------------------------------------------------------------------------------------- - - ! Let's check the limits. - IF ( Time <= p%Tdata(1) .OR. p%NumDataLines == 1 ) THEN - - m%TimeIndex = 1 - op%V = p%V (1) - op%Delta = p%Delta (1) - op%Upflow = p%Upflow (1) - op%VZ = p%VZ (1) - op%HShr = p%HShr (1) - op%VShr = p%VShr (1) - op%VLinShr = p%VLinShr(1) - op%VGust = p%VGust (1) - - ELSE IF ( Time >= p%Tdata(p%NumDataLines) ) THEN - - m%TimeIndex = p%NumDataLines - 1 - op%V = p%V (p%NumDataLines) - op%Delta = p%Delta (p%NumDataLines) - op%Upflow = p%Upflow (p%NumDataLines) - op%VZ = p%VZ (p%NumDataLines) - op%HShr = p%HShr (p%NumDataLines) - op%VShr = p%VShr (p%NumDataLines) - op%VLinShr = p%VLinShr(p%NumDataLines) - op%VGust = p%VGust (p%NumDataLines) - - ELSE - - ! Let's interpolate! Linear interpolation. - m%TimeIndex = MAX( MIN( m%TimeIndex, p%NumDataLines-1 ), 1 ) - - DO - - IF ( Time < p%Tdata(m%TimeIndex) ) THEN - - m%TimeIndex = m%TimeIndex - 1 - - ELSE IF ( Time >= p%Tdata(m%TimeIndex+1) ) THEN - - m%TimeIndex = m%TimeIndex + 1 - - ELSE - slope = ( Time - p%Tdata(m%TimeIndex) )/( p%Tdata(m%TimeIndex+1) - p%Tdata(m%TimeIndex) ) - - op%V = ( p%V( m%TimeIndex+1) - p%V( m%TimeIndex) )*slope + p%V( m%TimeIndex) - op%Delta = ( p%Delta( m%TimeIndex+1) - p%Delta( m%TimeIndex) )*slope + p%Delta( m%TimeIndex) - op%Upflow = ( p%Upflow( m%TimeIndex+1) - p%Upflow( m%TimeIndex) )*slope + p%Upflow( m%TimeIndex) - op%VZ = ( p%VZ( m%TimeIndex+1) - p%VZ( m%TimeIndex) )*slope + p%VZ( m%TimeIndex) - op%HShr = ( p%HShr( m%TimeIndex+1) - p%HShr( m%TimeIndex) )*slope + p%HShr( m%TimeIndex) - op%VShr = ( p%VShr( m%TimeIndex+1) - p%VShr( m%TimeIndex) )*slope + p%VShr( m%TimeIndex) - op%VLinShr = ( p%VLinShr(m%TimeIndex+1) - p%VLinShr(m%TimeIndex) )*slope + p%VLinShr(m%TimeIndex) - op%VGust = ( p%VGust( m%TimeIndex+1) - p%VGust( m%TimeIndex) )*slope + p%VGust( m%TimeIndex) - EXIT - - END IF - - END DO - - END IF -END SUBROUTINE InterpParams - -!+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- -!> This subroutine linearly interpolates the columns in the uniform input file to get the values for -!! the requested time, then uses the interpolated values to calclate the wind speed at a point -!! in space represented by InputPosition. -!! -!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -SUBROUTINE GetWindSpeed(InputPosition, p, op, WindSpeed, ErrStat, ErrMsg) - - ! Passed Variables - REAL(ReKi), INTENT(IN ) :: InputPosition(3) !< input information: positions X,Y,Z - TYPE(IfW_UniformWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(IfW_UniformWind_Intrp), INTENT(IN ) :: op !< operating point values; interpolated UniformWind parameters for this time (for glue-code linearization operating point) - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message - - ! Returned variables - REAL(ReKi), INTENT( OUT) :: WindSpeed(3) !< return velocities (U,V,W) - - ! Local Variables - REAL(ReKi) :: CosDelta ! cosine of y%Delta - REAL(ReKi) :: SinDelta ! sine of y%Delta - REAL(ReKi) :: V1 ! temporary storage for horizontal velocity - REAL(ReKi) :: V1_rotate ! temporary storage for rotated horizontal velocity - REAL(ReKi) :: VZ_rotate ! temporary storage for rotated vertical velocity - - REAL(ReKi) :: CosUpflow ! cosine of y%Upflow - REAL(ReKi) :: SinUpflow ! sine of y%Upflow - - ErrStat = ErrID_None - ErrMsg = "" - - - - !------------------------------------------------------------------------------------------------- - !> 2. Calculate the wind speed at this time (if z<0, return an error): - !------------------------------------------------------------------------------------------------- - - if ( InputPosition(3) <= 0.0_ReKi ) then - if (.not. EqualRealNos(InputPosition(3), 0.0_ReKi) ) call SetErrStat(ErrID_Severe,'Height must not be negative.',ErrStat,ErrMsg,'GetWindSpeed') - WindSpeed = 0.0 - return - end if - - !> Let \f{eqnarray}{ V_h & = & V \, \left( \frac{Z}{Z_{ref}} \right) ^ {V_{shr}} & \mbox{power-law wind shear} \\ - !! & + & V \, \frac{H_{LinShr}}{RefWid} \, \left( Y \cos(Delta) + X \sin(Delta) \right) & \mbox{horizontal linear shear} \\ - !! & + & V \, \frac{V_{LinShr}}{RefWid} \, \left( Z - Z_{ref} \right) & \mbox{vertical linear shear} \\ - !! & + & V_{Gust} & \mbox{gust speed} - !! \f} Then the returned wind speed, \f$Vt\f$, is \n - !! \f$Vt_u = V_h \, \cos(Delta) \f$ \n - !! \f$Vt_v = -V_h \, \sin(Delta) \f$ \n - !! \f$Vt_w = V_z \f$ \n using input positions \f$X,Y,Z\f$ and interpolated values for time-dependent input-file parameters - !! \f$V, Delta, V_z, H_{LinShr}, V_{Shr}, V_{LinShr}, V_{Gust}\f$. - - CosDelta = COS( op%Delta ) - SinDelta = SIN( op%Delta ) - V1 = op%V * ( ( InputPosition(3)/p%RefHt ) ** op%VShr & ! power-law wind shear - + ( op%HShr * ( InputPosition(2) * CosDelta + InputPosition(1) * SinDelta ) & ! horizontal linear shear - + op%VLinShr * ( InputPosition(3) - p%RefHt ) )/p%RefLength ) & ! vertical linear shear - + op%VGust ! gust speed - - ! convert global to local: Global wind = R(op%Delta) * R(op%Upflow) * [local wind] = R(op%Delta) * R(op%Upflow) * [V1, 0, op%VZ] - - ! apply upflow angle: - CosUpflow = COS( op%Upflow ) - SinUpflow = SIN( op%Upflow ) - V1_rotate = CosUpflow*V1 - SinUpflow*op%VZ - VZ_rotate = SinUpflow*V1 + CosUpflow*op%VZ - - ! apply wind direction: - WindSpeed(1) = V1_rotate * CosDelta - WindSpeed(2) = -V1_rotate * SinDelta - WindSpeed(3) = VZ_rotate - - - RETURN - -END SUBROUTINE GetWindSpeed - -FUNCTION RotateWindSpeed(Vh, Vz, Delta, Upflow) - REAL(ReKi) :: Vh ! horizontal wind speed - REAL(ReKi) :: Vz ! vertical wind speed - REAL(ReKi) :: Delta ! wind direction - REAL(ReKi) :: Upflow ! upflow angle - - REAL(R8Ki) :: CosDelta ! cosine of y%Delta - REAL(R8Ki) :: SinDelta ! sine of y%Delta - REAL(R8Ki) :: V1_rotate ! temporary storage for rotated horizontal velocity - REAL(R8Ki) :: VZ_rotate ! temporary storage for rotated vertical velocity - - REAL(R8Ki) :: CosUpflow ! cosine of y%Upflow - REAL(R8Ki) :: SinUpflow ! sine of y%Upflow - - - REAL(R8Ki) :: RotateWindSpeed(3) - - - ! apply upflow angle: - CosUpflow = COS( REAL(Upflow,R8Ki) ) - SinUpflow = SIN( REAL(Upflow,R8Ki) ) - - V1_rotate = CosUpflow*Vh - SinUpflow*Vz - Vz_rotate = SinUpflow*Vh + CosUpflow*Vz - - - ! apply wind direction: - CosDelta = COS( REAL(Delta,R8Ki) ) - SinDelta = SIN( REAL(Delta,R8Ki) ) - - RotateWindSpeed(1) = V1_rotate * CosDelta - RotateWindSpeed(2) = -V1_rotate * SinDelta - RotateWindSpeed(3) = Vz_rotate - -END FUNCTION RotateWindSpeed - - -!> This function should be deleted ASAP. Its purpose is to reproduce results of AeroDyn 12.57; -!! when a consensus on the definition of "average velocity" is determined, this function will be -!! removed. -FUNCTION WindInf_ADhack_diskVel( t, p, m,ErrStat, ErrMsg ) - - ! Passed variables - - REAL(DbKi), INTENT(IN ) :: t !< Time - TYPE(IfW_UniformWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: m !< misc/optimization data (storage for efficiency index) - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status from this function - CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message from this function - - ! Function definition - REAL(ReKi) :: WindInf_ADhack_diskVel(3) - - ! Local variables - TYPE(IfW_UniformWind_Intrp) :: op ! interpolated values of InterpParams - - - ErrStat = ErrID_None - ErrMsg = "" - - !------------------------------------------------------------------------------------------------- - ! Linearly interpolate in time (or use nearest-neighbor to extrapolate) - ! (compare with NWTC_Num.f90\InterpStpReal) - !------------------------------------------------------------------------------------------------- - - call InterpParams(t, p, m, op) - - !------------------------------------------------------------------------------------------------- - ! calculate the wind speed at this time (note that it is not the full uniform wind equation!) - !------------------------------------------------------------------------------------------------- - WindInf_ADhack_diskVel = RotateWindSpeed(op%V, op%VZ, op%Delta, op%Upflow) - - RETURN - -END FUNCTION WindInf_ADhack_diskVel - - -!==================================================================================================== -!> This routine closes any open files and clears all data stored in UniformWind derived Types -!! -!! @note This routine does not satisfy the Modular framework. The InputType is not used, rather -!! an array of points is passed in. -!! @date: 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -!---------------------------------------------------------------------------------------------------- -SUBROUTINE IfW_UniformWind_End( ParamData, MiscVars, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_UniformWind_End" - - - ! Passed Variables - TYPE(IfW_UniformWind_ParameterType), INTENT(INOUT) :: ParamData !< Parameters - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Local Variables - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - !-=- Initialize the routine -=- - - ErrMsg = '' - ErrStat = ErrID_None - - - - ! Destroy parameter data - - CALL IfW_UniformWind_DestroyParam( ParamData, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - - ! Destroy the state data - - CALL IfW_UniformWind_DestroyMisc( MiscVars, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - - ! reset time index so we know the module is no longer initialized - - MiscVars%TimeIndex = 0 - -END SUBROUTINE IfW_UniformWind_End -!.................................................................................................................................. -!> Routine to compute the Jacobians of the output (Y) function with respect to the inputs (u). The partial -!! derivative dY/du is returned. This submodule does not follow the modularization framework. -SUBROUTINE IfW_UniformWind_JacobianPInput( t, Position, CosPropDir, SinPropDir, p, m, dYdu ) - - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds - REAL(ReKi), INTENT(IN ) :: Position(3) !< XYZ Position at which to find velocity (operating point) - REAL(ReKi), INTENT(IN ) :: CosPropDir !< cosine of InflowWind propagation direction - REAL(ReKi), INTENT(IN ) :: SinPropDir !< sine of InflowWind propagation direction - TYPE(IfW_UniformWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - REAL(R8Ki), INTENT(INOUT) :: dYdu(3,6) !< Partial derivatives of output functions - !! (Y) with respect to the inputs (u) - - ! local variables: - !INTEGER(IntKi) :: ErrStat2 - !CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary error message - !CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_JacobianPInput' - - ! Local Variables - TYPE(IfW_UniformWind_Intrp) :: op ! interpolated values of InterpParams - REAL(R8Ki) :: CosDelta ! cosine of Delta_tmp - REAL(R8Ki) :: SinDelta ! sine of Delta_tmp - REAL(R8Ki) :: RotatePosition(3) !< rotated position - - REAL(R8Ki) :: dVhdx ! temporary value to hold partial v_h partial X - REAL(R8Ki) :: dVhdy ! temporary value to hold partial v_h partial Y - REAL(R8Ki) :: dVhdz ! temporary value to hold partial v_h partial Z - REAL(R8Ki) :: tmp_du ! temporary value to hold calculations that are part of multiple components - REAL(R8Ki) :: tmp_dv ! temporary value to hold calculations that are part of multiple components - REAL(R8Ki) :: dVhdPD ! temporary value to hold partial v_h partial propagation direction - REAL(R8Ki) :: dVhdV ! temporary value to hold partial v_h partial V - REAL(R8Ki) :: Vh ! temporary value to hold v_h - REAL(R8Ki) :: dVhdVShr ! temporary value to hold partial v_h partial VShr - REAL(R8Ki) :: zr - - - - - if ( Position(3) < 0.0_ReKi .or. EqualRealNos(Position(3), 0.0_ReKi)) then - dYdu = 0.0_R8Ki - RETURN - end if - - !------------------------------------------------------------------------------------------------- - !> 1. Linearly interpolate parameters in time at operating point (or use nearest-neighbor to extrapolate) - !! (compare with nwtc_num::interpstpreal) - !------------------------------------------------------------------------------------------------- - CALL InterpParams(t, p, m, op) - - CosDelta = COS( real(op%Delta,R8Ki) ) - SinDelta = SIN( real(op%Delta,R8Ki) ) - - RotatePosition(1) = Position(1)*cosPropDir - Position(2)*sinPropDir - RotatePosition(2) = Position(1)*sinPropDir + Position(2)*cosPropDir - RotatePosition(3) = Position(3) - - - !------------------------------------------------------------------------------------------------- - !> 2. Calculate \f$ \frac{\partial Y_{Output \, Equations}}{\partial u_{inputs}} = \begin{bmatrix} - !! \frac{\partial Vt_u}{\partial X} & \frac{\partial Vt_u}{\partial Y} & \frac{\partial Vt_u}{\partial Z} \\ - !! \frac{\partial Vt_v}{\partial X} & \frac{\partial Vt_v}{\partial Y} & \frac{\partial Vt_v}{\partial Z} \\ - !! \frac{\partial Vt_w}{\partial X} & \frac{\partial Vt_w}{\partial Y} & \frac{\partial Vt_w}{\partial Z} \\ - !! \end{bmatrix} \f$ - !------------------------------------------------------------------------------------------------- - zr = RotatePosition(3)/p%RefHt - tmp_du = op%V * op%HShr /p%RefLength * CosPropDir - dVhdx = tmp_du * SinDelta - dVhdy = tmp_du * CosDelta - dVhdz = op%V * ( op%VShr / p%RefHt * zr**(op%VShr-1.0_R8Ki) + op%VLinShr/p%RefLength) - - dVhdV = ( ( RotatePosition(3)/p%RefHt ) ** op%VShr & ! power-law wind shear - + ( op%HShr * ( RotatePosition(2) * CosDelta + RotatePosition(1) * SinDelta ) & ! horizontal linear shear - + op%VLinShr * ( RotatePosition(3) - p%RefHt ) )/p%RefLength ) ! vertical linear shear - Vh = op%V * dVhdV + op%Vgust - - dVhdVShr = op%V * zr**op%VShr * log(zr) - dVhdPD = op%V * op%HShr / p%RefLength * ( RotatePosition(1) * CosDelta - RotatePosition(2) * SinDelta ) - - tmp_du = CosPropDir*CosDelta - SinPropDir*SinDelta - tmp_dv = -SinPropDir*CosDelta - CosPropDir*SinDelta - - - !> \f$ \frac{\partial Vt_u}{\partial X} = \left[\cos(PropagationDir)\cos(Delta) - \sin(PropagationDir)\sin(Delta) \right] - !! V \, \frac{H_{LinShr}}{RefWid} \, \sin(Delta) \cos(PropagationDir) \f$ - dYdu(1,1) = tmp_du*dVhdx - - !> \f$ \frac{\partial Vt_v}{\partial X} = \left[-\sin(PropagationDir)\cos(Delta) - \cos(PropagationDir)\sin(Delta) \right] - !! V \, \frac{H_{LinShr}}{RefWid} \, \sin(Delta) \cos(PropagationDir) \f$ - dYdu(2,1) = tmp_dv*dVhdx - - !> \f$ \frac{\partial Vt_w}{\partial X} = 0 \f$ - dYdu(3,1) = 0.0_R8Ki - - - !> \f$ \frac{\partial Vt_u}{\partial Y} = \left[\cos(PropagationDir)\cos(Delta) - \sin(PropagationDir)\sin(Delta) \right] - !! V \, \frac{H_{LinShr}}{RefWid} \, \cos(Delta) \cos(PropagationDir) \f$ - dYdu(1,2) = tmp_du*dVhdy - - !> \f$ \frac{\partial Vt_v}{\partial Y} = \left[-\sin(PropagationDir)\cos(Delta) - \cos(PropagationDir)\sin(Delta) \right] - !! V \, \frac{H_{LinShr}}{RefWid} \, \cos(Delta) \cos(PropagationDir) \f$ - dYdu(2,2) = tmp_dv*dVhdy - - !> \f$ \frac{\partial Vt_w}{\partial Y} = 0 \f$ - dYdu(3,2) = 0.0_R8Ki - - - !> \f$ \frac{\partial Vt_u}{\partial Z} = \left[\cos(PropagationDir)\cos(Delta) - \sin(PropagationDir)\sin(Delta) \right] - !! V \, \left[ \frac{V_{shr}}{Z_{ref}} \left( \frac{Z}{Z_{ref}} \right) ^ {V_{shr}-1} + \frac{V_{LinShr}}{RefWid} \right] \f$ - dYdu(1,3) = tmp_du*dVhdz - - !> \f$ \frac{\partial Vt_v}{\partial Z} = \left[-\sin(PropagationDir)\cos(Delta) - \cos(PropagationDir)\sin(Delta) \right] - !! V \, \left[ \frac{V_{shr}}{Z_{ref}} \left( \frac{Z}{Z_{ref}} \right) ^ {V_{shr}-1} + \frac{V_{LinShr}}{RefWid} \right] \f$ - dYdu(2,3) = tmp_dv*dVhdz - - !> \f$ \frac{\partial Vt_w}{\partial Z} = 0 \f$ - dYdu(3,3) = 0.0_R8Ki - - - - ! \f$ \frac{\partial Vt_u}{\partial V} = \f$ - dYdu(1,4) = tmp_du*dVhdV - ! \f$ \frac{\partial Vt_v}{\partial V} = \f$ - dYdu(2,4) = tmp_dv*dVhdV - !> \f$ \frac{\partial Vt_w}{\partial V} = 0 \f$ - dYdu(3,4) = 0.0_R8Ki - - - ! \f$ \frac{\partial Vt_u}{\partial VShr} = \f$ - dYdu(1,5) = tmp_du*dVhdVShr - ! \f$ \frac{\partial Vt_v}{\partial VShr} = \f$ - dYdu(2,5) = tmp_dv*dVhdVShr - !> \f$ \frac{\partial Vt_w}{\partial VShr} = 0 \f$ - dYdu(3,5) = 0.0_R8Ki - - ! \f$ \frac{\partial Vt_u}{\partial PropDir} = \f$ - dYdu(1,6) = tmp_dv*Vh + tmp_du*dVhdPD - ! \f$ \frac{\partial Vt_v}{\partial PropDir} = \f$ - dYdu(2,6) = -tmp_du*Vh + tmp_dv*dVhdPD - !> \f$ \frac{\partial Vt_w}{\partial PropDir} = 0 \f$ - dYdu(3,6) = 0.0_R8Ki - - RETURN - -END SUBROUTINE IfW_UniformWind_JacobianPInput -!.................................................................................................................................. -!> Routine to compute the Jacobians of the output (Y) function with respect to the inputs (u). The partial -!! derivative dY/du is returned. This submodule does not follow the modularization framework. -SUBROUTINE IfW_UniformWind_GetOP( t, p, m, OP_out ) - - REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds - REAL(ReKi), INTENT( OUT) :: OP_out(2) !< operating point (HWindSpeed and PLexp - TYPE(IfW_UniformWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - - ! Local Variables - TYPE(IfW_UniformWind_Intrp) :: op ! interpolated values of InterpParams - - - !------------------------------------------------------------------------------------------------- - !> 1. Linearly interpolate parameters in time at operating point (or use nearest-neighbor to extrapolate) - !! (compare with nwtc_num::interpstpreal) - !------------------------------------------------------------------------------------------------- - CALL InterpParams(t, p, m, op) - - OP_out(1) = op%V - OP_out(2) = op%VSHR - - RETURN - -END SUBROUTINE IfW_UniformWind_GetOP - - -!==================================================================================================== -SUBROUTINE Uniform_to_FFWind(p, m, p_ff, ErrStat, ErrMsg) - - USE IfW_FFWind_Base - - TYPE(IfW_UniformWind_ParameterType), INTENT(IN ) :: p !< UniformWind Parameters - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - TYPE(IfW_FFWind_ParameterType), INTENT( OUT) :: p_ff !< FF Parameters - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message - - ! local variables - REAL(DbKi) :: Time !< time from the start of the simulation - REAL(ReKi) :: PositionXYZ(3,1) !< Array of XYZ coordinates, 3xN - REAL(ReKi) :: Velocity(3,1) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) - REAL(ReKi) :: n - - INTEGER(ReKi) , parameter :: dz = 5.0 - INTEGER(ReKi) , parameter :: dy = 5.0 - INTEGER(ReKi) :: i - INTEGER(ReKi) :: it - INTEGER(ReKi) :: iy - INTEGER(ReKi) :: iz - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), parameter :: RoutineName = 'Uniform_to_FFWind' - - ErrStat = ErrID_None - ErrMsg = "" - - p_ff%WindFileFormat = -1 ! "Binary file format description number" - - p_ff%NFFComp = 3 ! "Number of wind components" - - p_ff%Periodic = .false. - p_ff%InterpTower = .true. - p_ff%RefHt = p%RefHt - p_ff%NTGrids = 0 - p_ff%InvFFYD = 1.0_ReKi / dy ! "reciprocal of delta y" 1/meters - p_ff%InvFFZD = 1.0_ReKi / dz ! "reciprocal of delta z" 1/meters - - ! add roughly 10% to the width - n = NINT( p%RefLength*1.1_ReKi*0.5_ReKi / dy ) - p_ff%NYGrids = n*2+1 ! "Number of points in the lateral (y) direction of the grids" - - p_ff%FFYHWid = 0.5_ReKi * dy * (p_ff%NYGrids-1) ! "Half the grid width" meters - - n = NINT( p%RefLength*1.1_ReKi*0.5_ReKi / dz ) - p_ff%NZGrids = INT( p_ff%RefHt / dy ) + n + 1 ! "Number of points in the vertical (z) direction of the grids" - - - p_ff%FFZHWid = 0.5_ReKi * dz * (p_ff%NZGrids -1) ! "Half the grid height" meters - p_ff%GridBase = p_ff%RefHt + n*dz - p_ff%FFZHWid*2.0_ReKi ! "the height of the bottom of the grid" meters - - p_ff%InitXPosition = 0.0_ReKi ! "the initial x position of grid (distance in FF is offset)" meters - - - ! time will be the smallest delta t in this Uniform wind file - if (p%NumDataLines < 2) then - p_ff%FFDTime = 600.0_ReKi ! doesn't matter what the time step is - else - p_ff%FFDTime = HUGE(p_ff%FFDTime) ! "Delta time" seconds - do i=2,p%NumDataLines - p_ff%FFDTime = min(p_ff%FFDTime, p%TData(i) - p%TData(i-1)) - end do - - if (p_ff%FFDTime < 0.0001) then - call SetErrStat( ErrID_Fatal, "Smallest time step in uniform wind file is less that 0.0001 seconds. Increase the time step "//& - " to convert to a FF file.", ErrStat, ErrMsg, RoutineName ) - return - end if - - end if - - p_ff%FFRate = 1.0_ReKi / p_ff%FFDTime ! "Data rate (1/FFDTime)" Hertz - - - p_ff%AddMeanAfterInterp = .FALSE. ! "Add the mean wind speed after interpolating at a given height?" - - p_ff%WindProfileType = WindProfileType_PL ! "Wind profile type (0=constant;1=logarithmic;2=power law)" - - p_ff%PLExp = GetAverageVal(p%VSHR) ! "Power law exponent (used for PL wind profile type only)" - - p_ff%Z0 = 0.0_ReKi ! "Surface roughness length (used for LOG wind profile type only)" - - - if (p%NumDataLines < 2) then - p_ff%NFFSteps = 2 ! "Number of time steps in the FF array" - - else - p_ff%NFFSteps = NINT(p%TData(p%NumDataLines) / p_ff%FFDTime) + 1 - end if - - p_ff%TotalTime = (p_ff%NFFSteps-1) * p_ff%FFDTime ! "The total time of the simulation" seconds - - - call AllocAry( p_ff%FFData, p_ff%NZGrids,p_ff%NYGrids,p_ff%NFFComp, p_ff%NFFSteps, 'p%FF%FFData', ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - if (ErrStat >= AbortErrLev) return - - PositionXYZ = 0.0_ReKi - do it = 1,p_ff%NFFSteps - Time = (it-1)*p_ff%FFDTime - - do iy = 1,p_ff%NYGrids - PositionXYZ(2,1) = (iy-1)*dy - p_ff%FFYHWid - - do iz=1,p_ff%NZGrids - PositionXYZ(3,1) = (iz-1)*dz + p_ff%GridBase - - call IfW_UniformWind_CalcOutput(Time, PositionXYZ, p, Velocity, m, ErrStat2, ErrMsg2) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - p_ff%FFData(iz,iy,:,it) = Velocity(:,1) - - end do ! iz - end do ! iy - end do ! it - - ! compute some averages for this simulation - p_ff%MeanFFWS = GetAverageVal(p%V) ! "Mean wind speed (advection speed)" - p_ff%InvMFFWS = 1.0_ReKi / p_ff%MeanFFWS - - RETURN - -CONTAINS -!==================================================================================================== - FUNCTION GetAverageVal(Ary) RESULT(Avg) - REAL(ReKi), intent(in) :: Ary(:) - REAL(ReKi) :: Avg - - if (p%NumDataLines < 2) then - Avg = Ary(1) - else - Avg = p%TData(1) * Ary(1) ! in case tData(1)/=0 - do i=2,p%NumDataLines - Avg = Avg + (p%TData(i)-p%TData(i-1)) * (Ary(i)+Ary(i-1))/2.0_ReKi - end do - Avg = Avg / (p%TData(p%NumDataLines)-p%TData(1)) - end if - - END FUNCTION GetAverageVal - -END SUBROUTINE Uniform_to_FFWind -!==================================================================================================== -SUBROUTINE FFWind_to_Uniform(p, m, p_ff, ErrStat, ErrMsg, SmoothingRadius) - - USE IfW_FFWind_Base - - TYPE(IfW_UniformWind_ParameterType), INTENT( OUT) :: p !< UniformWind Parameters - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p_ff !< FF Parameters - REAL(ReKi), OPTIONAL, INTENT(IN ) :: SmoothingRadius !< length of time used for smoothing data, seconds (if omitted, no smoothing will occur) - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message - - INTEGER(IntKi) :: i - INTEGER(IntKi) :: iy_ref, iz_ref, iz_p1 - INTEGER(IntKi) :: iy, iz, ic - REAL(ReKi) :: meanVel(3) - REAL(ReKi) :: meanWindDir - REAL(ReKi) :: u_p1, z_p1 - REAL(ReKi) :: u_ref, z_ref - REAL(ReKi), parameter :: HubPositionX = 0.0_ReKi -! REAL(ReKi), parameter :: radius = 0.0 !5.0_ReKi !seconds - REAL(ReKi) :: radius ! length of time to use for smoothing uniform wind data, seconds - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), parameter :: RoutineName = 'FFWind_to_Uniform' - - REAL(SiKi), allocatable :: FFData(:,:,:,:) - REAL(ReKi), allocatable :: tmp(:) - REAL(R8Ki) :: transformMat(3,3) - - ErrStat = ErrID_None - ErrMsg = "" - - if (p_ff%RefLength > epsilon(0.0_ReKi)) then - p%RefLength = p_ff%VLinShr - else - p%RefLength = (p_ff%nYGrids - 1) / p_ff%InvFFYD ! width of the FF wind field - end if - p%NumDataLines = p_ff%nffSteps - - - CALL AllocAry( p%Tdata, p%NumDataLines, 'time', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%V, p%NumDataLines, 'horizontal wind speed', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%Delta, p%NumDataLines, 'direction', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%Upflow, p%NumDataLines, 'upflow', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%VZ, p%NumDataLines, 'vertical wind speed', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%HShr, p%NumDataLines, 'horizontal linear shear', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%VShr, p%NumDataLines, 'vertical power-law shear exponent',ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%VLinShr,p%NumDataLines, 'vertical linear shear', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( p%VGust, p%NumDataLines, 'gust velocity', ErrStat2, ErrMsg2); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( FFData, p_FF%NZGrids,p_FF%NYGrids,p_FF%NFFComp, p_FF%NFFSteps, 'FFData', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( tmp, p_FF%NFFSteps, 'tmp', ErrStat2, ErrMsg2 ); CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - IF ( ErrStat >= AbortErrLev .or. p%NumDataLines < 1) then - if (allocated(FFData)) deallocate(FFData) - if (allocated(tmp)) deallocate(tmp) - RETURN - END IF - - ! we'll assume these are 0, for simplicity - p%HShr = p_ff%HLinShr - p%VLinShr = p_ff%VLinShr - p%VGust = 0.0_ReKi - - ! fill time array with time at hub position - do i=1,p%NumDataLines - p%Tdata(i) = (p_ff%InitXPosition - HubPositionX) * p_ff%InvMFFWS + (i-1)*p_ff%FFDTime - end do - - - ! calculate mean velocity at grid point nearest lateral center of grid at reference height: - iy_ref = nint(p_ff%nYGrids / 2.0_ReKi) - iz_ref = nint( ( p_ff%RefHt - p_ff%GridBase )*p_ff%InvFFZD ) + 1 - p%RefHt = p_ff%GridBase + (iz_ref - 1)/p_ff%InvFFZD ! make sure RefHt is on the grid - - - meanVel = 0.0_ReKi - do i=1,p%NumDataLines - meanVel = meanVel + p_ff%FFData( iz_ref, iy_ref, :, i ) - end do - meanVel = meanVel/p%NumDataLines - - ! calculate the average upflow angle - p%Upflow = atan2( meanVel(3), TwoNorm(meanVel(1:2)) ) - meanWindDir = atan2( meanVel(2), meanVel(1) ) - - ! rotate the FF wind to remove the mean upflow and direction - transformMat(1,1) = cos(meanWindDir) * cos(p%Upflow(1)) - transformMat(2,1) = -sin(meanWindDir) - transformMat(3,1) = -cos(meanWindDir) * sin(p%Upflow(1)) - - transformMat(1,2) = sin(meanWindDir) * cos(p%Upflow(1)) - transformMat(2,2) = cos(meanWindDir) - transformMat(3,2) = -sin(meanWindDir) * sin(p%Upflow(1)) - - transformMat(1,3) = sin(p%Upflow(1)) - transformMat(2,3) = 0.0_R8Ki - transformMat(3,3) = cos(p%Upflow(1)) - - do i=1,size(FFData,4) - do iy=1,size(FFData,2) - do iz=1,size(FFData,1) - FFData(iz,iy,:,i) = matmul(transformMat, p_ff%FFData(iz,iy,:,i)) - end do - end do - end do - - ! make sure we have the correct mean, or the direction will also be off here - if (p_ff%AddMeanAfterInterp) then - FFData(iz_ref,iy_ref,1,:) = FFData(iz_ref,iy_ref,1,:) + CalculateMeanVelocity(p_ff,p%RefHt,0.0_ReKi) - end if - - meanVel = 0.0_ReKi - do i=1,p%NumDataLines - meanVel = meanVel + FFData( iz_ref, iy_ref, :, i ) - end do - meanVel = meanVel/p%NumDataLines - - - ! Fill velocity arrays for uniform wind - do i=1,p%NumDataLines - p%V(i) = TwoNorm( FFData(iz_ref,iy_ref,1:2,i) ) - end do - p%VZ = FFData(iz_ref,iy_ref,3,:) - - ! Fill wind direction array - do i=1,p%NumDataLines - p%Delta(i) = -(meanWindDir + atan2( FFData(iz_ref,iy_ref,2,i), FFData(iz_ref,iy_ref,1,i) )) - end do - - ! Now, time average values, if desired: - if (present(SmoothingRadius)) then - radius = SmoothingRadius - else - radius = 0.0_ReKi - end if - tmp = p%V; call kernelSmoothing(p%Tdata, tmp, kernelType_TRIWEIGHT, radius, p%V) - tmp = p%VZ; call kernelSmoothing(p%Tdata, tmp, kernelType_TRIWEIGHT, radius, p%VZ) - tmp = p%Delta; call kernelSmoothing(p%Tdata, tmp, kernelType_TRIWEIGHT, radius, p%Delta) - - ! Calculate averaged power law coefficient: - if (p_ff%WindProfileType == WindProfileType_PL) then - p%VShr = p_ff%PLExp - else - iz_p1 = p_ff%nZGrids ! pick a point to compute the power law exponent (least squares would be better than a single point) - z_p1 = p_ff%GridBase + (iz_p1 - 1)/p_ff%InvFFZD - - if (p_ff%AddMeanAfterInterp) then - u_p1 = CalculateMeanVelocity(p_ff,z_p1,0.0_ReKi) - else - u_p1 = 0.0_ReKi - do i=1,p%NumDataLines - u_p1 = u_p1 + FFData( iz_p1, iy_ref, 1, i ) - end do - u_p1 = u_p1/p%NumDataLines - end if - - if (EqualRealNos(meanVel(1), u_p1) .or. EqualRealNos(u_p1,0.0_ReKi) .or. EqualRealNos(meanVel(1),0.0_ReKi)) then - p%VShr = 0.0_ReKi - else - p%VShr = log( u_p1 / meanVel(1) ) / log( z_p1 / p%RefHt ) - end if - end if - - ! clean up - - if (allocated(FFData)) deallocate(FFData) - if (allocated(tmp)) deallocate(tmp) - - -END SUBROUTINE FFWind_to_Uniform - - -!==================================================================================================== -SUBROUTINE WrUniformWind(FileRootName, p, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - TYPE(IfW_UniformWind_ParameterType), INTENT(IN ) :: p !< Parameters - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - INTEGER(IntKi) :: i - INTEGER(IntKi) :: UnWind - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'WrUniformWind' - - ErrStat = ErrID_None - ErrMsg = "" - - ! Local variables - - CALL GetNewUnit( UnWind, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - CALL OpenFOutFile ( UnWind, trim(FileRootName)//'.UniformWind.dat', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - WRITE( UnWind, "(A)" ) "#" - WRITE( UnWind, "(A)" ) '# Uniform Wind (deterministic) file for ENFAST generated by InflowWind' - WRITE( UnWind, "(A)" ) "#" - WRITE( UnWind, "(A)" ) "! Time Wind Wind Vertical Horiz. Pwr.Law Lin.Vert. Gust Upflow" - WRITE( UnWind, "(A)" ) "! Speed Dir Speed Shear Vert.Shr Shear Speed Angle" - WRITE( UnWind, "(A)" ) "! (sec) (m/s) (Deg) (m/s) (m/s) (deg)" - - DO i=1,p%NumDataLines - WRITE( UnWind, "(F15.5,8(1x,F11.4))" ) p%Tdata(i), p%V(i), p%Delta(i)*R2D, p%VZ(i), p%HShr(i), p%VShr(i), p%VLinShr(i), p%VGust(i), p%Upflow(i)*R2D - END DO - - CLOSE(UnWind) - -END SUBROUTINE WrUniformWind -!==================================================================================================== -END MODULE IfW_UniformWind diff --git a/modules/inflowwind/src/IfW_UniformWind.txt b/modules/inflowwind/src/IfW_UniformWind.txt deleted file mode 100644 index df99ddd79e..0000000000 --- a/modules/inflowwind/src/IfW_UniformWind.txt +++ /dev/null @@ -1,67 +0,0 @@ -################################################################################################################################### -# Registry for IfW_UniformWind, creates MODULE IfW_UniformWind_Types -# Module IfW_UniformWind_Types contains all of the user-defined types needed in IfW_UniformWind. It also contains copy, destroy, pack, and -# unpack routines associated with each defined data types. -################################################################################################################################### -# Entries are of the form -# keyword -################################################################################################################################### - -include Registry_NWTC_Library.txt - - -######################### - -typedef IfW_UniformWind/IfW_UniformWind InitInputType CHARACTER(1024) WindFileName - - - "Name of the wind file to use" - -typedef ^ ^ ReKi ReferenceHeight - - - "Hub height of the turbine" meters -typedef ^ ^ ReKi RefLength - - - "RefLength of the wind field to use" meters -typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - -typedef ^ ^ LOGICAL UseInputFile - .TRUE. - "Flag for toggling file based IO in wind type 2." - -typedef ^ ^ FileInfoType PassedFileData - - - "Optional slot for wind type 2 data if file IO is not used." - - - - -# Init Output -typedef ^ InitOutputType ProgDesc Ver - - - "Version information off HHWind submodule" - -typedef ^ ^ DbKi WindFileDT - - - "TimeStep of the wind file -- zero value for none" seconds -typedef ^ ^ ReKi WindFileTRange {2} - - "Time range of the wind file" seconds -typedef ^ ^ IntKi WindFileNumTSteps - - - "Number of timesteps in the time range of wind file" - -typedef ^ ^ LOGICAL WindFileConstantDT - - - "Timesteps are the same throughout file" - - - -# ..... Misc/Optimization variables................................................................................................. -# Define any data that are used only for efficiency purposes (these variables are not associated with time): -# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType IntKi TimeIndex - 0 - "An Index into the TData array" - - - -# ..... Parameters ................................................................................................................ -# Define parameters here: -# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType ReKi TData : - - "Time array from the HH file" seconds -typedef ^ ^ ReKi DELTA : - - "HH Wind direction (angle)" degrees -typedef ^ ^ ReKi Upflow : - - "HH upflow angle" degrees -typedef ^ ^ ReKi V : - - "HH horizontal wind speed" meters/sec -typedef ^ ^ ReKi VZ : - - "wind, including tower shadow, along the Z axis" meters/sec -typedef ^ ^ ReKi HSHR : - - "HH Horizontal linear shear" - -typedef ^ ^ ReKi VSHR : - - "HH vertical shear exponent" - -typedef ^ ^ ReKi VLINSHR : - - "HH vertical linear shear" - -typedef ^ ^ ReKi VGUST : - - "HH wind gust" - -typedef ^ ^ ReKi RefHt - - - "reference height; was HH (hub height); used to center the wind" meters -typedef ^ ^ ReKi RefLength - - - "reference length used to scale the linear shear" meters -typedef ^ ^ IntKi NumDataLines - - - "" - - -# ..... Input (dummy type for extrap/interp routine) ................................................................................................................ -#typedef ^ InputType SiKi dummy - - - "dummy type because we need extrap/interp routine if we put the below outputs in the InflowWind type" - -# ..... Output (for extended AD inputs in linearization) ................................................................................................................ -typedef ^ IfW_UniformWind_Intrp ReKi DELTA - - - "HH Wind direction (angle)" degrees -typedef ^ ^ ReKi Upflow - - - "HH upflow angle" degrees -typedef ^ ^ ReKi V - - - "HH horizontal wind speed" meters/sec -typedef ^ ^ ReKi VZ - - - "wind, including tower shadow, along the Z axis" meters/sec -typedef ^ ^ ReKi HSHR - - - "HH Horizontal linear shear" - -typedef ^ ^ ReKi VSHR - - - "HH vertical shear exponent" - -typedef ^ ^ ReKi VLINSHR - - - "HH vertical linear shear" - -typedef ^ ^ ReKi VGUST - - - "HH wind gust" - - - diff --git a/modules/inflowwind/src/IfW_UniformWind_Types.f90 b/modules/inflowwind/src/IfW_UniformWind_Types.f90 deleted file mode 100644 index 6007f774e4..0000000000 --- a/modules/inflowwind/src/IfW_UniformWind_Types.f90 +++ /dev/null @@ -1,1546 +0,0 @@ -!STARTOFREGISTRYGENERATEDFILE 'IfW_UniformWind_Types.f90' -! -! WARNING This file is generated automatically by the FAST registry. -! Do not edit. Your changes to this file will be lost. -! -! FAST Registry -!********************************************************************************************************************************* -! IfW_UniformWind_Types -!................................................................................................................................. -! This file is part of IfW_UniformWind. -! -! Copyright (C) 2012-2016 National Renewable Energy Laboratory -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -! -! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. -! -!********************************************************************************************************************************* -!> This module contains the user-defined types needed in IfW_UniformWind. It also contains copy, destroy, pack, and -!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE IfW_UniformWind_Types -!--------------------------------------------------------------------------------------------------------------------------------- -USE NWTC_Library -IMPLICIT NONE -! ========= IfW_UniformWind_InitInputType ======= - TYPE, PUBLIC :: IfW_UniformWind_InitInputType - CHARACTER(1024) :: WindFileName !< Name of the wind file to use [-] - REAL(ReKi) :: ReferenceHeight !< Hub height of the turbine [meters] - REAL(ReKi) :: RefLength !< RefLength of the wind field to use [meters] - INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file (-1 for none). Provided by IfW. [-] - LOGICAL :: UseInputFile = .TRUE. !< Flag for toggling file based IO in wind type 2. [-] - TYPE(FileInfoType) :: PassedFileData !< Optional slot for wind type 2 data if file IO is not used. [-] - END TYPE IfW_UniformWind_InitInputType -! ======================= -! ========= IfW_UniformWind_InitOutputType ======= - TYPE, PUBLIC :: IfW_UniformWind_InitOutputType - TYPE(ProgDesc) :: Ver !< Version information off HHWind submodule [-] - REAL(DbKi) :: WindFileDT !< TimeStep of the wind file -- zero value for none [seconds] - REAL(ReKi) , DIMENSION(1:2) :: WindFileTRange !< Time range of the wind file [seconds] - INTEGER(IntKi) :: WindFileNumTSteps !< Number of timesteps in the time range of wind file [-] - LOGICAL :: WindFileConstantDT !< Timesteps are the same throughout file [-] - END TYPE IfW_UniformWind_InitOutputType -! ======================= -! ========= IfW_UniformWind_MiscVarType ======= - TYPE, PUBLIC :: IfW_UniformWind_MiscVarType - INTEGER(IntKi) :: TimeIndex = 0 !< An Index into the TData array [-] - END TYPE IfW_UniformWind_MiscVarType -! ======================= -! ========= IfW_UniformWind_ParameterType ======= - TYPE, PUBLIC :: IfW_UniformWind_ParameterType - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: TData !< Time array from the HH file [seconds] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: DELTA !< HH Wind direction (angle) [degrees] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Upflow !< HH upflow angle [degrees] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: V !< HH horizontal wind speed [meters/sec] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VZ !< wind, including tower shadow, along the Z axis [meters/sec] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: HSHR !< HH Horizontal linear shear [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VSHR !< HH vertical shear exponent [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VLINSHR !< HH vertical linear shear [-] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: VGUST !< HH wind gust [-] - REAL(ReKi) :: RefHt !< reference height; was HH (hub height); used to center the wind [meters] - REAL(ReKi) :: RefLength !< reference length used to scale the linear shear [meters] - INTEGER(IntKi) :: NumDataLines !< [-] - END TYPE IfW_UniformWind_ParameterType -! ======================= -! ========= IfW_UniformWind_Intrp ======= - TYPE, PUBLIC :: IfW_UniformWind_Intrp - REAL(ReKi) :: DELTA !< HH Wind direction (angle) [degrees] - REAL(ReKi) :: Upflow !< HH upflow angle [degrees] - REAL(ReKi) :: V !< HH horizontal wind speed [meters/sec] - REAL(ReKi) :: VZ !< wind, including tower shadow, along the Z axis [meters/sec] - REAL(ReKi) :: HSHR !< HH Horizontal linear shear [-] - REAL(ReKi) :: VSHR !< HH vertical shear exponent [-] - REAL(ReKi) :: VLINSHR !< HH vertical linear shear [-] - REAL(ReKi) :: VGUST !< HH wind gust [-] - END TYPE IfW_UniformWind_Intrp -! ======================= -CONTAINS - SUBROUTINE IfW_UniformWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_UniformWind_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(IfW_UniformWind_InitInputType), INTENT(INOUT) :: DstInitInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_CopyInitInput' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitInputData%WindFileName = SrcInitInputData%WindFileName - DstInitInputData%ReferenceHeight = SrcInitInputData%ReferenceHeight - DstInitInputData%RefLength = SrcInitInputData%RefLength - DstInitInputData%SumFileUnit = SrcInitInputData%SumFileUnit - DstInitInputData%UseInputFile = SrcInitInputData%UseInputFile - CALL NWTC_Library_Copyfileinfotype( SrcInitInputData%PassedFileData, DstInitInputData%PassedFileData, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_UniformWind_CopyInitInput - - SUBROUTINE IfW_UniformWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_UniformWind_InitInputType), INTENT(INOUT) :: InitInputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyInitInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL NWTC_Library_Destroyfileinfotype( InitInputData%PassedFileData, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_UniformWind_DestroyInitInput - - SUBROUTINE IfW_UniformWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_UniformWind_InitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_PackInitInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName - Re_BufSz = Re_BufSz + 1 ! ReferenceHeight - Re_BufSz = Re_BufSz + 1 ! RefLength - Int_BufSz = Int_BufSz + 1 ! SumFileUnit - Int_BufSz = Int_BufSz + 1 ! UseInputFile - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! PassedFileData: size of buffers for each call to pack subtype - CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedFileData, ErrStat2, ErrMsg2, .TRUE. ) ! PassedFileData - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! PassedFileData - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! PassedFileData - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! PassedFileData - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%WindFileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - ReKiBuf(Re_Xferred) = InData%ReferenceHeight - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefLength - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%SumFileUnit - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%UseInputFile, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedFileData, ErrStat2, ErrMsg2, OnlySize ) ! PassedFileData - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE IfW_UniformWind_PackInitInput - - SUBROUTINE IfW_UniformWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_UniformWind_InitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_UnPackInitInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%WindFileName) - OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%ReferenceHeight = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefLength = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%SumFileUnit = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%UseInputFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseInputFile) - Int_Xferred = Int_Xferred + 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackfileinfotype( Re_Buf, Db_Buf, Int_Buf, OutData%PassedFileData, ErrStat2, ErrMsg2 ) ! PassedFileData - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_UniformWind_UnPackInitInput - - SUBROUTINE IfW_UniformWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_UniformWind_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(IfW_UniformWind_InitOutputType), INTENT(INOUT) :: DstInitOutputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_CopyInitOutput' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - DstInitOutputData%WindFileDT = SrcInitOutputData%WindFileDT - DstInitOutputData%WindFileTRange = SrcInitOutputData%WindFileTRange - DstInitOutputData%WindFileNumTSteps = SrcInitOutputData%WindFileNumTSteps - DstInitOutputData%WindFileConstantDT = SrcInitOutputData%WindFileConstantDT - END SUBROUTINE IfW_UniformWind_CopyInitOutput - - SUBROUTINE IfW_UniformWind_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_UniformWind_InitOutputType), INTENT(INOUT) :: InitOutputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyInitOutput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_UniformWind_DestroyInitOutput - - SUBROUTINE IfW_UniformWind_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_UniformWind_InitOutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_PackInitOutput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Ver - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Ver - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Ver - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Db_BufSz = Db_BufSz + 1 ! WindFileDT - Re_BufSz = Re_BufSz + SIZE(InData%WindFileTRange) ! WindFileTRange - Int_BufSz = Int_BufSz + 1 ! WindFileNumTSteps - Int_BufSz = Int_BufSz + 1 ! WindFileConstantDT - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - DbKiBuf(Db_Xferred) = InData%WindFileDT - Db_Xferred = Db_Xferred + 1 - DO i1 = LBOUND(InData%WindFileTRange,1), UBOUND(InData%WindFileTRange,1) - ReKiBuf(Re_Xferred) = InData%WindFileTRange(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = InData%WindFileNumTSteps - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%WindFileConstantDT, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_UniformWind_PackInitOutput - - SUBROUTINE IfW_UniformWind_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_UniformWind_InitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_UnPackInitOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - OutData%WindFileDT = DbKiBuf(Db_Xferred) - Db_Xferred = Db_Xferred + 1 - i1_l = LBOUND(OutData%WindFileTRange,1) - i1_u = UBOUND(OutData%WindFileTRange,1) - DO i1 = LBOUND(OutData%WindFileTRange,1), UBOUND(OutData%WindFileTRange,1) - OutData%WindFileTRange(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%WindFileNumTSteps = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%WindFileConstantDT = TRANSFER(IntKiBuf(Int_Xferred), OutData%WindFileConstantDT) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_UniformWind_UnPackInitOutput - - SUBROUTINE IfW_UniformWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_UniformWind_MiscVarType), INTENT(IN) :: SrcMiscData - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: DstMiscData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_CopyMisc' -! - ErrStat = ErrID_None - ErrMsg = "" - DstMiscData%TimeIndex = SrcMiscData%TimeIndex - END SUBROUTINE IfW_UniformWind_CopyMisc - - SUBROUTINE IfW_UniformWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: MiscData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyMisc' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_UniformWind_DestroyMisc - - SUBROUTINE IfW_UniformWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_UniformWind_MiscVarType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_PackMisc' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! TimeIndex - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = InData%TimeIndex - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_UniformWind_PackMisc - - SUBROUTINE IfW_UniformWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_UniformWind_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%TimeIndex = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_UniformWind_UnPackMisc - - SUBROUTINE IfW_UniformWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_UniformWind_ParameterType), INTENT(IN) :: SrcParamData - TYPE(IfW_UniformWind_ParameterType), INTENT(INOUT) :: DstParamData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_CopyParam' -! - ErrStat = ErrID_None - ErrMsg = "" -IF (ALLOCATED(SrcParamData%TData)) THEN - i1_l = LBOUND(SrcParamData%TData,1) - i1_u = UBOUND(SrcParamData%TData,1) - IF (.NOT. ALLOCATED(DstParamData%TData)) THEN - ALLOCATE(DstParamData%TData(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%TData.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%TData = SrcParamData%TData -ENDIF -IF (ALLOCATED(SrcParamData%DELTA)) THEN - i1_l = LBOUND(SrcParamData%DELTA,1) - i1_u = UBOUND(SrcParamData%DELTA,1) - IF (.NOT. ALLOCATED(DstParamData%DELTA)) THEN - ALLOCATE(DstParamData%DELTA(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%DELTA.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%DELTA = SrcParamData%DELTA -ENDIF -IF (ALLOCATED(SrcParamData%Upflow)) THEN - i1_l = LBOUND(SrcParamData%Upflow,1) - i1_u = UBOUND(SrcParamData%Upflow,1) - IF (.NOT. ALLOCATED(DstParamData%Upflow)) THEN - ALLOCATE(DstParamData%Upflow(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Upflow.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%Upflow = SrcParamData%Upflow -ENDIF -IF (ALLOCATED(SrcParamData%V)) THEN - i1_l = LBOUND(SrcParamData%V,1) - i1_u = UBOUND(SrcParamData%V,1) - IF (.NOT. ALLOCATED(DstParamData%V)) THEN - ALLOCATE(DstParamData%V(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%V.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%V = SrcParamData%V -ENDIF -IF (ALLOCATED(SrcParamData%VZ)) THEN - i1_l = LBOUND(SrcParamData%VZ,1) - i1_u = UBOUND(SrcParamData%VZ,1) - IF (.NOT. ALLOCATED(DstParamData%VZ)) THEN - ALLOCATE(DstParamData%VZ(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%VZ.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%VZ = SrcParamData%VZ -ENDIF -IF (ALLOCATED(SrcParamData%HSHR)) THEN - i1_l = LBOUND(SrcParamData%HSHR,1) - i1_u = UBOUND(SrcParamData%HSHR,1) - IF (.NOT. ALLOCATED(DstParamData%HSHR)) THEN - ALLOCATE(DstParamData%HSHR(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%HSHR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%HSHR = SrcParamData%HSHR -ENDIF -IF (ALLOCATED(SrcParamData%VSHR)) THEN - i1_l = LBOUND(SrcParamData%VSHR,1) - i1_u = UBOUND(SrcParamData%VSHR,1) - IF (.NOT. ALLOCATED(DstParamData%VSHR)) THEN - ALLOCATE(DstParamData%VSHR(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%VSHR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%VSHR = SrcParamData%VSHR -ENDIF -IF (ALLOCATED(SrcParamData%VLINSHR)) THEN - i1_l = LBOUND(SrcParamData%VLINSHR,1) - i1_u = UBOUND(SrcParamData%VLINSHR,1) - IF (.NOT. ALLOCATED(DstParamData%VLINSHR)) THEN - ALLOCATE(DstParamData%VLINSHR(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%VLINSHR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%VLINSHR = SrcParamData%VLINSHR -ENDIF -IF (ALLOCATED(SrcParamData%VGUST)) THEN - i1_l = LBOUND(SrcParamData%VGUST,1) - i1_u = UBOUND(SrcParamData%VGUST,1) - IF (.NOT. ALLOCATED(DstParamData%VGUST)) THEN - ALLOCATE(DstParamData%VGUST(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%VGUST.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%VGUST = SrcParamData%VGUST -ENDIF - DstParamData%RefHt = SrcParamData%RefHt - DstParamData%RefLength = SrcParamData%RefLength - DstParamData%NumDataLines = SrcParamData%NumDataLines - END SUBROUTINE IfW_UniformWind_CopyParam - - SUBROUTINE IfW_UniformWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_UniformWind_ParameterType), INTENT(INOUT) :: ParamData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyParam' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - -IF (ALLOCATED(ParamData%TData)) THEN - DEALLOCATE(ParamData%TData) -ENDIF -IF (ALLOCATED(ParamData%DELTA)) THEN - DEALLOCATE(ParamData%DELTA) -ENDIF -IF (ALLOCATED(ParamData%Upflow)) THEN - DEALLOCATE(ParamData%Upflow) -ENDIF -IF (ALLOCATED(ParamData%V)) THEN - DEALLOCATE(ParamData%V) -ENDIF -IF (ALLOCATED(ParamData%VZ)) THEN - DEALLOCATE(ParamData%VZ) -ENDIF -IF (ALLOCATED(ParamData%HSHR)) THEN - DEALLOCATE(ParamData%HSHR) -ENDIF -IF (ALLOCATED(ParamData%VSHR)) THEN - DEALLOCATE(ParamData%VSHR) -ENDIF -IF (ALLOCATED(ParamData%VLINSHR)) THEN - DEALLOCATE(ParamData%VLINSHR) -ENDIF -IF (ALLOCATED(ParamData%VGUST)) THEN - DEALLOCATE(ParamData%VGUST) -ENDIF - END SUBROUTINE IfW_UniformWind_DestroyParam - - SUBROUTINE IfW_UniformWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_UniformWind_ParameterType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_PackParam' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! TData allocated yes/no - IF ( ALLOCATED(InData%TData) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! TData upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%TData) ! TData - END IF - Int_BufSz = Int_BufSz + 1 ! DELTA allocated yes/no - IF ( ALLOCATED(InData%DELTA) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! DELTA upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%DELTA) ! DELTA - END IF - Int_BufSz = Int_BufSz + 1 ! Upflow allocated yes/no - IF ( ALLOCATED(InData%Upflow) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! Upflow upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%Upflow) ! Upflow - END IF - Int_BufSz = Int_BufSz + 1 ! V allocated yes/no - IF ( ALLOCATED(InData%V) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! V upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%V) ! V - END IF - Int_BufSz = Int_BufSz + 1 ! VZ allocated yes/no - IF ( ALLOCATED(InData%VZ) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! VZ upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%VZ) ! VZ - END IF - Int_BufSz = Int_BufSz + 1 ! HSHR allocated yes/no - IF ( ALLOCATED(InData%HSHR) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! HSHR upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%HSHR) ! HSHR - END IF - Int_BufSz = Int_BufSz + 1 ! VSHR allocated yes/no - IF ( ALLOCATED(InData%VSHR) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! VSHR upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%VSHR) ! VSHR - END IF - Int_BufSz = Int_BufSz + 1 ! VLINSHR allocated yes/no - IF ( ALLOCATED(InData%VLINSHR) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! VLINSHR upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%VLINSHR) ! VLINSHR - END IF - Int_BufSz = Int_BufSz + 1 ! VGUST allocated yes/no - IF ( ALLOCATED(InData%VGUST) ) THEN - Int_BufSz = Int_BufSz + 2*1 ! VGUST upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%VGUST) ! VGUST - END IF - Re_BufSz = Re_BufSz + 1 ! RefHt - Re_BufSz = Re_BufSz + 1 ! RefLength - Int_BufSz = Int_BufSz + 1 ! NumDataLines - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IF ( .NOT. ALLOCATED(InData%TData) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%TData,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%TData,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%TData,1), UBOUND(InData%TData,1) - ReKiBuf(Re_Xferred) = InData%TData(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%DELTA) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%DELTA,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%DELTA,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%DELTA,1), UBOUND(InData%DELTA,1) - ReKiBuf(Re_Xferred) = InData%DELTA(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%Upflow) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%Upflow,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Upflow,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%Upflow,1), UBOUND(InData%Upflow,1) - ReKiBuf(Re_Xferred) = InData%Upflow(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%V) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%V,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%V,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%V,1), UBOUND(InData%V,1) - ReKiBuf(Re_Xferred) = InData%V(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%VZ) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%VZ,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VZ,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%VZ,1), UBOUND(InData%VZ,1) - ReKiBuf(Re_Xferred) = InData%VZ(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%HSHR) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%HSHR,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%HSHR,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%HSHR,1), UBOUND(InData%HSHR,1) - ReKiBuf(Re_Xferred) = InData%HSHR(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%VSHR) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%VSHR,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VSHR,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%VSHR,1), UBOUND(InData%VSHR,1) - ReKiBuf(Re_Xferred) = InData%VSHR(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%VLINSHR) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%VLINSHR,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VLINSHR,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%VLINSHR,1), UBOUND(InData%VLINSHR,1) - ReKiBuf(Re_Xferred) = InData%VLINSHR(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( .NOT. ALLOCATED(InData%VGUST) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%VGUST,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VGUST,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%VGUST,1), UBOUND(InData%VGUST,1) - ReKiBuf(Re_Xferred) = InData%VGUST(i1) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefLength - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NumDataLines - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_UniformWind_PackParam - - SUBROUTINE IfW_UniformWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_UniformWind_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TData not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%TData)) DEALLOCATE(OutData%TData) - ALLOCATE(OutData%TData(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%TData.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%TData,1), UBOUND(OutData%TData,1) - OutData%TData(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! DELTA not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%DELTA)) DEALLOCATE(OutData%DELTA) - ALLOCATE(OutData%DELTA(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%DELTA.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%DELTA,1), UBOUND(OutData%DELTA,1) - OutData%DELTA(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Upflow not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%Upflow)) DEALLOCATE(OutData%Upflow) - ALLOCATE(OutData%Upflow(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Upflow.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%Upflow,1), UBOUND(OutData%Upflow,1) - OutData%Upflow(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! V not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%V)) DEALLOCATE(OutData%V) - ALLOCATE(OutData%V(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%V.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%V,1), UBOUND(OutData%V,1) - OutData%V(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VZ not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%VZ)) DEALLOCATE(OutData%VZ) - ALLOCATE(OutData%VZ(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VZ.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%VZ,1), UBOUND(OutData%VZ,1) - OutData%VZ(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! HSHR not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%HSHR)) DEALLOCATE(OutData%HSHR) - ALLOCATE(OutData%HSHR(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%HSHR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%HSHR,1), UBOUND(OutData%HSHR,1) - OutData%HSHR(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VSHR not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%VSHR)) DEALLOCATE(OutData%VSHR) - ALLOCATE(OutData%VSHR(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VSHR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%VSHR,1), UBOUND(OutData%VSHR,1) - OutData%VSHR(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VLINSHR not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%VLINSHR)) DEALLOCATE(OutData%VLINSHR) - ALLOCATE(OutData%VLINSHR(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VLINSHR.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%VLINSHR,1), UBOUND(OutData%VLINSHR,1) - OutData%VLINSHR(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VGUST not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%VGUST)) DEALLOCATE(OutData%VGUST) - ALLOCATE(OutData%VGUST(i1_l:i1_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VGUST.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i1 = LBOUND(OutData%VGUST,1), UBOUND(OutData%VGUST,1) - OutData%VGUST(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END IF - OutData%RefHt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefLength = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%NumDataLines = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - END SUBROUTINE IfW_UniformWind_UnPackParam - - SUBROUTINE IfW_UniformWind_CopyIntrp( SrcIntrpData, DstIntrpData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_UniformWind_Intrp), INTENT(IN) :: SrcIntrpData - TYPE(IfW_UniformWind_Intrp), INTENT(INOUT) :: DstIntrpData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_CopyIntrp' -! - ErrStat = ErrID_None - ErrMsg = "" - DstIntrpData%DELTA = SrcIntrpData%DELTA - DstIntrpData%Upflow = SrcIntrpData%Upflow - DstIntrpData%V = SrcIntrpData%V - DstIntrpData%VZ = SrcIntrpData%VZ - DstIntrpData%HSHR = SrcIntrpData%HSHR - DstIntrpData%VSHR = SrcIntrpData%VSHR - DstIntrpData%VLINSHR = SrcIntrpData%VLINSHR - DstIntrpData%VGUST = SrcIntrpData%VGUST - END SUBROUTINE IfW_UniformWind_CopyIntrp - - SUBROUTINE IfW_UniformWind_DestroyIntrp( IntrpData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_UniformWind_Intrp), INTENT(INOUT) :: IntrpData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_DestroyIntrp' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_UniformWind_DestroyIntrp - - SUBROUTINE IfW_UniformWind_PackIntrp( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_UniformWind_Intrp), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_PackIntrp' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DELTA - Re_BufSz = Re_BufSz + 1 ! Upflow - Re_BufSz = Re_BufSz + 1 ! V - Re_BufSz = Re_BufSz + 1 ! VZ - Re_BufSz = Re_BufSz + 1 ! HSHR - Re_BufSz = Re_BufSz + 1 ! VSHR - Re_BufSz = Re_BufSz + 1 ! VLINSHR - Re_BufSz = Re_BufSz + 1 ! VGUST - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DELTA - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%Upflow - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%V - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VZ - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%HSHR - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VSHR - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VLINSHR - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VGUST - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_UniformWind_PackIntrp - - SUBROUTINE IfW_UniformWind_UnPackIntrp( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_UniformWind_Intrp), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UniformWind_UnPackIntrp' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DELTA = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%Upflow = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%V = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VZ = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%HSHR = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VSHR = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VLINSHR = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VGUST = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_UniformWind_UnPackIntrp - -END MODULE IfW_UniformWind_Types -!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/IfW_UserWind.f90 b/modules/inflowwind/src/IfW_UserWind.f90 deleted file mode 100644 index b8a8a1596e..0000000000 --- a/modules/inflowwind/src/IfW_UserWind.f90 +++ /dev/null @@ -1,282 +0,0 @@ -!> This module is a placeholder for any user defined wind types. The end user can use this as a template for their code. -!! @note This module does not need to exactly conform to the FAST Modularization Framework standards. Three routines are required -!! though: -!! -- IfW_UserWind_Init -- Load or create any wind data. Only called at the start of FAST. -!! -- IfW_UserWind_CalcOutput -- This will be called at each timestep with a series of data points to give wind velocities at. -!! -- IfW_UserWind_End -- clear out any stored stuff. Only called at the end of FAST. -MODULE IfW_UserWind -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2015-2016 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** - - USE NWTC_Library - USE IfW_UserWind_Types - - IMPLICIT NONE - PRIVATE - - TYPE(ProgDesc), PARAMETER :: IfW_UserWind_Ver = ProgDesc( 'IfW_UserWind', '', '' ) - - PUBLIC :: IfW_UserWind_Init - PUBLIC :: IfW_UserWind_End - PUBLIC :: IfW_UserWind_CalcOutput - -CONTAINS - -!==================================================================================================== - -!---------------------------------------------------------------------------------------------------- -!> A subroutine to initialize the UserWind module. This routine will initialize the module. -!---------------------------------------------------------------------------------------------------- -SUBROUTINE IfW_UserWind_Init(InitData, ParamData, MiscVars, Interval, InitOutData, ErrStat, ErrMsg) - - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_UserWind_Init" - - - ! Passed Variables - - ! Anything this code needs to be able to generate or read its data in should be passed into here through InitData. - TYPE(IfW_UserWind_InitInputType), INTENT(IN ) :: InitData !< Input data for initialization. - - ! Store all data that does not change during the simulation in here (including the wind data field). This cannot be changed later. - TYPE(IfW_UserWind_ParameterType), INTENT( OUT) :: ParamData !< Parameters. - - ! Store things that change during the simulation (indices to arrays for quicker searching etc). - TYPE(IfW_UserWind_MiscVarType), INTENT( OUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - - ! Anything that should be passed back to the InflowWind or higher modules regarding initialization. - TYPE(IfW_UserWind_InitOutputType), INTENT( OUT) :: InitOutData !< Initial output. - - REAL(DbKi), INTENT(IN ) :: Interval !< Do not change this!! - - - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< A message about the error. See NWTC_Library info for ErrID_* levels. - - ! local variables - ! Put local variables used during initializing your wind here. DO NOT USE GLOBAL VARIABLES EVER! - INTEGER(IntKi) :: UnitWind ! Use this unit number if you need to read in a file. - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat ! Temp variable for the error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - !------------------------------------------------------------------------------------------------- - ! Set the Error handling variables - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = "" - - - ! Get a unit number to use - - CALL GetNewUnit(UnitWind, TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Copy things from the InitData to the ParamData. If you need to store it for later calculations, - ! copy it over now. - !------------------------------------------------------------------------------------------------- - ParamData%dummy = 0 -! ParamData%RefHt = InitData%ReferenceHeight -! ParamData%RefLength = InitData%RefLength - - !------------------------------------------------------------------------------------------------- - ! Open the file for reading. Proceed with file parsing etc. Populate your wind field here. - !------------------------------------------------------------------------------------------------- - -! CALL OpenFInpFile (UnitWind, TRIM(InitData%WindFileName), TmpErrStat, TmpErrMsg) -! CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) -! IF ( ErrStat >= AbortErrLev ) RETURN - - - !------------------------------------------------------------------------------------------------- - ! Set the MiscVars: - !------------------------------------------------------------------------------------------------- - - MiscVars%DummyMiscVar = 0 - - - !------------------------------------------------------------------------------------------------- - ! Set the InitOutput information. Set Any outputs here. - !------------------------------------------------------------------------------------------------- - - InitOutdata%Ver = IfW_UserWind_Ver - - - - ! REMOVE THIS MESSAGE IF YOU WRITE CODE IN THIS MODULE - CALL SetErrStat(ErrID_Fatal,' This module has not been written yet.',ErrStat,ErrMsg,RoutineName) - - RETURN - -END SUBROUTINE IfW_UserWind_Init - -!==================================================================================================== - -!------------------------------------------------------------------------------------------------- -!> This routine and its subroutines calculate the wind velocity at a set of points given in -!! PositionXYZ. The UVW velocities are returned in OutData%Velocity -!! -!! @note This routine may be called multiple times in a single timestep!!! -!! -!! @note The PositionXYZ coordinates have been rotated into the wind coordinate system where the -!! primary wind flow is along the X-axis. The rotations to PropagationDir are taken care of -!! in the InflowWind_CalcOutput subroutine which calls this routine. -!------------------------------------------------------------------------------------------------- -SUBROUTINE IfW_UserWind_CalcOutput(Time, PositionXYZ, ParamData, Velocity, MiscVars, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_UserWind_CalcOutput" - - - ! Passed Variables - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - REAL(ReKi), INTENT(IN ) :: PositionXYZ(:,:) !< Array of XYZ coordinates, 3xN - TYPE(IfW_UserWind_ParameterType), INTENT(IN ) :: ParamData !< Parameters - REAL(ReKi), INTENT(INOUT) :: Velocity(:,:) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) - TYPE(IfW_UserWind_MiscVarType), INTENT(INOUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message - - - ! local counters - INTEGER(IntKi) :: PointNum ! a loop counter for the current point - - ! local variables - INTEGER(IntKi) :: NumPoints ! Number of points passed in - - ! temporary variables - !INTEGER(IntKi) :: TmpErrStat ! temporary error status - !CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - - !------------------------------------------------------------------------------------------------- - ! Initialize some things - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = "" - - - ! The array is transposed so that the number of points is the second index, x/y/z is the first. - ! This is just in case we only have a single point, the SIZE command returns the correct number of points. - NumPoints = SIZE(PositionXYZ,DIM=2) - - - ! Step through all the positions and get the velocities - DO PointNum = 1, NumPoints - -! Place code to retrieve the windspeed at a given point here. - - - ! Some generic error handling if you want it when a calculation fails for some reason: - ! - ! ! Error handling - !CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - !IF (ErrStat >= AbortErrLev) THEN - ! TmpErrMsg= " Error calculating the wind speed at position ("// & - ! TRIM(Num2LStr(PositionXYZ(1,PointNum)))//", "// & - ! TRIM(Num2LStr(PositionXYZ(2,PointNum)))//", "// & - ! TRIM(Num2LStr(PositionXYZ(3,PointNum)))//") in the wind-file coordinates" - ! CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - ! RETURN - !ENDIF - - ENDDO - - ! REMOVE THIS MESSAGE IF YOU WRITE CODE IN THIS MODULE - CALL SetErrStat(ErrID_Fatal,' This module has not been written yet.',ErrStat,ErrMsg,RoutineName) - - - RETURN - -END SUBROUTINE IfW_UserWind_CalcOutput - -!==================================================================================================== - -!---------------------------------------------------------------------------------------------------- -!> This routine closes any open files and clears all data stored in UserWind derived Types -!! -!! @note This routine does not satisfy the Modular framework. The InputType is not used, rather -!! an array of points is passed in. -!! @date: 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -!---------------------------------------------------------------------------------------------------- -SUBROUTINE IfW_UserWind_End( ParamData, MiscVars, ErrStat, ErrMsg) - - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="IfW_UserWind_End" - - - ! Passed Variables - TYPE(IfW_UserWind_ParameterType), INTENT(INOUT) :: ParamData !< Parameters - TYPE(IfW_UserWind_MiscVarType), INTENT(INOUT) :: MiscVars !< Misc variables for optimization (not copied in glue code) - - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - - ! Local Variables - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - !-=- Initialize the routine -=- - - ErrMsg = '' - ErrStat = ErrID_None - - - - ! Destroy parameter data - - CALL IfW_UserWind_DestroyParam( ParamData, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - - ! Destroy the misc data - - CALL IfW_UserWind_DestroyMisc( MiscVars, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - - -END SUBROUTINE IfW_UserWind_End - - -!==================================================================================================== -!==================================================================================================== -!==================================================================================================== -END MODULE IfW_UserWind diff --git a/modules/inflowwind/src/IfW_UserWind.txt b/modules/inflowwind/src/IfW_UserWind.txt deleted file mode 100644 index 62fa3e3b28..0000000000 --- a/modules/inflowwind/src/IfW_UserWind.txt +++ /dev/null @@ -1,36 +0,0 @@ -################################################################################################################################### -# Registry for IfW_UserWind, creates MODULE IfW_UserWind_Types -# Module IfW_UserWind_Types contains all of the user-defined types needed in IfW_UserWind. It also contains copy, destroy, pack, and -# unpack routines associated with each defined data types. -################################################################################################################################### -# Entries are of the form -# keyword -################################################################################################################################### - -include Registry_NWTC_Library.txt - - -######################### - -typedef IfW_UserWind/IfW_UserWind InitInputType CHARACTER(1024) WindFileName - - - "Name of the wind file to use" - - - - -# Init Output -typedef ^ InitOutputType ProgDesc Ver - - - "Version information off HHWind submodule" - - - -# ..... Misc/Optimization variables................................................................................................. -# Define any data that are used only for efficiency purposes (these variables are not associated with time): -# e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType ReKi DummyMiscVar - - - "Remove this variable if you have misc variables" - - - -# ..... Parameters ................................................................................................................ -# Define parameters here: -# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType SiKi dummy - - - "remove if you have parameters" - - - - - diff --git a/modules/inflowwind/src/IfW_UserWind_Types.f90 b/modules/inflowwind/src/IfW_UserWind_Types.f90 deleted file mode 100644 index 6f7c2fe094..0000000000 --- a/modules/inflowwind/src/IfW_UserWind_Types.f90 +++ /dev/null @@ -1,695 +0,0 @@ -!STARTOFREGISTRYGENERATEDFILE 'IfW_UserWind_Types.f90' -! -! WARNING This file is generated automatically by the FAST registry. -! Do not edit. Your changes to this file will be lost. -! -! FAST Registry -!********************************************************************************************************************************* -! IfW_UserWind_Types -!................................................................................................................................. -! This file is part of IfW_UserWind. -! -! Copyright (C) 2012-2016 National Renewable Energy Laboratory -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -! -! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. -! -!********************************************************************************************************************************* -!> This module contains the user-defined types needed in IfW_UserWind. It also contains copy, destroy, pack, and -!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. -MODULE IfW_UserWind_Types -!--------------------------------------------------------------------------------------------------------------------------------- -USE NWTC_Library -IMPLICIT NONE -! ========= IfW_UserWind_InitInputType ======= - TYPE, PUBLIC :: IfW_UserWind_InitInputType - CHARACTER(1024) :: WindFileName !< Name of the wind file to use [-] - END TYPE IfW_UserWind_InitInputType -! ======================= -! ========= IfW_UserWind_InitOutputType ======= - TYPE, PUBLIC :: IfW_UserWind_InitOutputType - TYPE(ProgDesc) :: Ver !< Version information off HHWind submodule [-] - END TYPE IfW_UserWind_InitOutputType -! ======================= -! ========= IfW_UserWind_MiscVarType ======= - TYPE, PUBLIC :: IfW_UserWind_MiscVarType - REAL(ReKi) :: DummyMiscVar !< Remove this variable if you have misc variables [-] - END TYPE IfW_UserWind_MiscVarType -! ======================= -! ========= IfW_UserWind_ParameterType ======= - TYPE, PUBLIC :: IfW_UserWind_ParameterType - REAL(SiKi) :: dummy !< remove if you have parameters [-] - END TYPE IfW_UserWind_ParameterType -! ======================= -CONTAINS - SUBROUTINE IfW_UserWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_UserWind_InitInputType), INTENT(IN) :: SrcInitInputData - TYPE(IfW_UserWind_InitInputType), INTENT(INOUT) :: DstInitInputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_CopyInitInput' -! - ErrStat = ErrID_None - ErrMsg = "" - DstInitInputData%WindFileName = SrcInitInputData%WindFileName - END SUBROUTINE IfW_UserWind_CopyInitInput - - SUBROUTINE IfW_UserWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_UserWind_InitInputType), INTENT(INOUT) :: InitInputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_DestroyInitInput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_UserWind_DestroyInitInput - - SUBROUTINE IfW_UserWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_UserWind_InitInputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_PackInitInput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%WindFileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END SUBROUTINE IfW_UserWind_PackInitInput - - SUBROUTINE IfW_UserWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_UserWind_InitInputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_UnPackInitInput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%WindFileName) - OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - END SUBROUTINE IfW_UserWind_UnPackInitInput - - SUBROUTINE IfW_UserWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_UserWind_InitOutputType), INTENT(IN) :: SrcInitOutputData - TYPE(IfW_UserWind_InitOutputType), INTENT(INOUT) :: DstInitOutputData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_CopyInitOutput' -! - ErrStat = ErrID_None - ErrMsg = "" - CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - END SUBROUTINE IfW_UserWind_CopyInitOutput - - SUBROUTINE IfW_UserWind_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_UserWind_InitOutputType), INTENT(INOUT) :: InitOutputData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_DestroyInitOutput' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE IfW_UserWind_DestroyInitOutput - - SUBROUTINE IfW_UserWind_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_UserWind_InitOutputType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_PackInitOutput' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! Ver: size of buffers for each call to pack subtype - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, .TRUE. ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! Ver - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! Ver - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! Ver - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - CALL NWTC_Library_Packprogdesc( Re_Buf, Db_Buf, Int_Buf, InData%Ver, ErrStat2, ErrMsg2, OnlySize ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END SUBROUTINE IfW_UserWind_PackInitOutput - - SUBROUTINE IfW_UserWind_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_UserWind_InitOutputType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_UnPackInitOutput' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL NWTC_Library_Unpackprogdesc( Re_Buf, Db_Buf, Int_Buf, OutData%Ver, ErrStat2, ErrMsg2 ) ! Ver - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - END SUBROUTINE IfW_UserWind_UnPackInitOutput - - SUBROUTINE IfW_UserWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_UserWind_MiscVarType), INTENT(IN) :: SrcMiscData - TYPE(IfW_UserWind_MiscVarType), INTENT(INOUT) :: DstMiscData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_CopyMisc' -! - ErrStat = ErrID_None - ErrMsg = "" - DstMiscData%DummyMiscVar = SrcMiscData%DummyMiscVar - END SUBROUTINE IfW_UserWind_CopyMisc - - SUBROUTINE IfW_UserWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_UserWind_MiscVarType), INTENT(INOUT) :: MiscData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_DestroyMisc' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_UserWind_DestroyMisc - - SUBROUTINE IfW_UserWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_UserWind_MiscVarType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_PackMisc' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! DummyMiscVar - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%DummyMiscVar - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_UserWind_PackMisc - - SUBROUTINE IfW_UserWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_UserWind_MiscVarType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_UnPackMisc' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%DummyMiscVar = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_UserWind_UnPackMisc - - SUBROUTINE IfW_UserWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg ) - TYPE(IfW_UserWind_ParameterType), INTENT(IN) :: SrcParamData - TYPE(IfW_UserWind_ParameterType), INTENT(INOUT) :: DstParamData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_CopyParam' -! - ErrStat = ErrID_None - ErrMsg = "" - DstParamData%dummy = SrcParamData%dummy - END SUBROUTINE IfW_UserWind_CopyParam - - SUBROUTINE IfW_UserWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(IfW_UserWind_ParameterType), INTENT(INOUT) :: ParamData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_DestroyParam' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE IfW_UserWind_DestroyParam - - SUBROUTINE IfW_UserWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(IfW_UserWind_ParameterType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_PackParam' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Re_BufSz = Re_BufSz + 1 ! dummy - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - ReKiBuf(Re_Xferred) = InData%dummy - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_UserWind_PackParam - - SUBROUTINE IfW_UserWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(IfW_UserWind_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_UserWind_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - OutData%dummy = REAL(ReKiBuf(Re_Xferred), SiKi) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE IfW_UserWind_UnPackParam - -END MODULE IfW_UserWind_Types -!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 675aef5461..25950b03d8 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -41,11 +41,12 @@ MODULE InflowWind - USE InflowWind_Types USE NWTC_Library + USE InflowWind_Types USE InflowWind_Subs - USE FlowField_IO_Types - USE FlowField_IO + USE InflowWind_IO_Types + USE InflowWind_IO + USE IfW_FlowField USE Lidar ! module for obtaining sensor data @@ -64,12 +65,6 @@ MODULE InflowWind PUBLIC :: InflowWind_CalcOutput !< Calculate the wind velocities PUBLIC :: InflowWind_End !< Ending routine (includes clean up) - PUBLIC :: InflowWind_Convert2HAWC !< An extension of the FAST framework, this routine converts an InflowWind data structure to HAWC format wind files - PUBLIC :: InflowWind_Convert2Bladed !< An extension of the FAST framework, this routine converts an InflowWind data structure to Bladed format wind files (with shear already included) - PUBLIC :: InflowWind_Convert2VTK !< An extension of the FAST framework, this routine converts an InflowWind data structure to VTK format wind files - PUBLIC :: InflowWind_Convert2Uniform !< An extension of the FAST framework, this routine converts an InflowWind data structure to Uniform Wind formatted text files - - ! These routines satisfy the framework, but do nothing at present. PUBLIC :: InflowWind_UpdateStates !< Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete states PUBLIC :: InflowWind_CalcConstrStateResidual !< Tight coupling routine for returning the constraint state residual @@ -101,760 +96,489 @@ MODULE InflowWind !! Since this module acts as an interface to other modules, on some things are set before initiating !! calls to the lower modules. !---------------------------------------------------------------------------------------------------- -SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & - y, m, TimeInterval, InitOutData, ErrStat, ErrMsg ) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="InflowWind_Init" - - ! Initialization data and guesses - - TYPE(InflowWind_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization - TYPE(InflowWind_InputType), INTENT( OUT) :: InputGuess !< An initial guess for the input; the input mesh must be defined - TYPE(InflowWind_ParameterType), INTENT( OUT) :: p !< Parameters - TYPE(InflowWind_ContinuousStateType), INTENT( OUT) :: ContStates !< Initial continuous states - TYPE(InflowWind_DiscreteStateType), INTENT( OUT) :: DiscStates !< Initial discrete states - TYPE(InflowWind_ConstraintStateType), INTENT( OUT) :: ConstrStateGuess !< Initial guess of the constraint states - TYPE(InflowWind_OtherStateType), INTENT( OUT) :: OtherStates !< Initial other/optimization states - TYPE(InflowWind_OutputType), INTENT( OUT) :: y !< Initial output (outputs are not calculated; only the output mesh is initialized) - TYPE(InflowWind_MiscVarType), INTENT( OUT) :: m !< Misc variables for optimization (not copied in glue code) - REAL(DbKi), INTENT(IN ) :: TimeInterval !< Coupling time interval in seconds: InflowWind does not change this. - TYPE(InflowWind_InitOutputType), INTENT( OUT) :: InitOutData !< Initial output data -- Names, units, and version info. - - - ! Error Handling - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - - TYPE(InflowWind_InputFile) :: InputFileData !< Data from input file - - TYPE(FlowField_IO_InitInputType) :: FlowField_InitData !< initialization info - TYPE(FlowField_IO_InitOutputType) :: Interp_InitOutData !< initialization output info - - TYPE(IfW_UniformWind_InitInputType) :: Uniform_InitData !< initialization info - TYPE(IfW_UniformWind_InitOutputType) :: Uniform_InitOutData !< initialization output info - - TYPE(IfW_TSFFWind_InitInputType) :: TSFF_InitData !< initialization info - TYPE(IfW_TSFFWind_InitOutputType) :: TSFF_InitOutData !< initialization output info - - TYPE(IfW_HAWCWind_InitInputType) :: HAWC_InitData !< initialization info - TYPE(IfW_HAWCWind_InitOutputType) :: HAWC_InitOutData !< initialization output info - - TYPE(IfW_BladedFFWind_InitInputType) :: BladedFF_InitData !< initialization info - TYPE(IfW_BladedFFWind_InitOutputType) :: BladedFF_InitOutData !< initialization output info - - TYPE(IfW_UserWind_InitInputType) :: User_InitData !< initialization info - TYPE(IfW_UserWind_InitOutputType) :: User_InitOutData !< initialization info - - TYPE(IfW_4Dext_InitOutputType) :: FDext_InitOutData !< initialization info - - TYPE(FileInfoType) :: InFileInfo !< The derived type for holding the full input file for parsing -- we may pass this in the future -!!! TYPE(CTBladed_Backgr) :: BackGrndValues - - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat - CHARACTER(ErrMsgLen) :: TmpErrMsg !< temporary error message - CHARACTER(1024) :: PriPath - - ! Local Variables - INTEGER(IntKi) :: I, j !< Generic counter - INTEGER(IntKi) :: Lin_indx !< Generic counter - INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file - CHARACTER(256) :: SumFileName !< Name of the summary file - CHARACTER(256) :: EchoFileName !< Name of the summary file - CHARACTER(1), PARAMETER :: UVW(3) = (/'U','V','W'/) - CHARACTER(1), PARAMETER :: XYZ(3) = (/'X','Y','Z'/) - - !---------------------------------------------------------------------------------------------- - ! Initialize variables and check to see if this module has been initialized before. - !---------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = "" - SumFileUnit = -1_IntKi ! set at beginning in case of error - - ! Set a few variables. - - p%DT = TimeInterval ! InflowWind does not require a specific time interval, so this is never changed. - CALL NWTC_Init() - CALL DispNVD( IfW_Ver ) - - - - !---------------------------------------------------------------------------------------------- - ! Read the input file - !---------------------------------------------------------------------------------------------- - - - ! Set the names of the files based on the inputfilename - p%RootFileName = InitInp%RootName - IF (LEN_TRIM(p%RootFileName) == 0) CALL GetRoot( InitInp%InputFileName, p%RootFileName ) - EchoFileName = TRIM(p%RootFileName)//".ech" - SumFileName = TRIM(p%RootFileName)//".sum" - - ! these values (and others hard-coded in lidar_init) should be set in the input file, too - InputFileData%SensorType = InitInp%lidar%SensorType - InputFileData%NumPulseGate = InitInp%lidar%NumPulseGate - InputFileData%RotorApexOffsetPos = InitInp%lidar%RotorApexOffsetPos - InputFileData%LidRadialVel = InitInp%lidar%LidRadialVel - - ! Parse all the InflowWind related input files and populate the *_InitDataType derived types - CALL GetPath( InitInp%InputFileName, PriPath ) - - IF ( InitInp%UseInputFile ) THEN - CALL ProcessComFile( InitInp%InputFileName, InFileInfo, TmpErrStat, TmpErrMsg ) - ! For diagnostic purposes, the following can be used to display the contents - ! of the InFileInfo data structure. - ! call Print_FileInfo_Struct( CU, InFileInfo ) ! CU is the screen -- different number on different systems. - - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - ENDIF - - ELSE - CALL NWTC_Library_CopyFileInfoType( InitInp%PassedFileData, InFileInfo, MESH_NEWCOPY, TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - ENDIF - - ENDIF - - CALL InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, InitInp%InputFileName, EchoFileName, InitInp%FixedWindFileRootName, InitInp%TurbineID, TmpErrStat, TmpErrMsg ) +SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & + y, m, TimeInterval, InitOutData, ErrStat, ErrMsg ) + + ! Initialization data and guesses + TYPE(InflowWind_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization + TYPE(InflowWind_InputType), INTENT( OUT) :: InputGuess !< An initial guess for the input; the input mesh must be defined + TYPE(InflowWind_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT( OUT) :: ContStates !< Initial continuous states + TYPE(InflowWind_DiscreteStateType), INTENT( OUT) :: DiscStates !< Initial discrete states + TYPE(InflowWind_ConstraintStateType), INTENT( OUT) :: ConstrStateGuess !< Initial guess of the constraint states + TYPE(InflowWind_OtherStateType), INTENT( OUT) :: OtherStates !< Initial other/optimization states + TYPE(InflowWind_OutputType), INTENT( OUT) :: y !< Initial output (outputs are not calculated; only the output mesh is initialized) + TYPE(InflowWind_MiscVarType), INTENT( OUT) :: m !< Misc variables for optimization (not copied in glue code) + REAL(DbKi), INTENT(IN ) :: TimeInterval !< Coupling time interval in seconds: InflowWind does not change this. + TYPE(InflowWind_InitOutputType), INTENT( OUT) :: InitOutData !< Initial output data -- Names, units, and version info. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables + CHARACTER(*), PARAMETER :: RoutineName="InflowWind_Init" + + TYPE(InflowWind_InputFile) :: InputFileData !< Data from input file + + Type(Steady_InitInputType) :: Steady_InitInput + Type(Uniform_InitInputType) :: Uniform_InitInput + Type(TurbSim_InitInputType) :: TurbSim_InitInput + Type(Bladed_InitInputType) :: Bladed_InitInput + Type(Bladed_InitOutputType) :: Bladed_InitOutput + Type(HAWC_InitInputType) :: HAWC_InitInput + Type(User_InitInputType) :: User_InitInput + Type(Grid4D_InitInputType) :: Grid4D_InitInput + Type(Points_InitInputType) :: Points_InitInput + + Type(WindFileDat) :: FileDat + + ! TYPE(InflowWind_IO_InitInputType) :: FlowField_InitData !< initialization info + ! TYPE(InflowWind_IO_InitOutputType) :: FlowField_InitOutData !< initialization output info + + TYPE(FileInfoType) :: InFileInfo !< The derived type for holding the full input file for parsing -- we may pass this in the future + CHARACTER(1024) :: PriPath + + INTEGER(IntKi) :: I, j !< Generic counter + INTEGER(IntKi) :: Lin_indx !< Generic counter + INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file + CHARACTER(256) :: SumFileName !< Name of the summary file + CHARACTER(256) :: EchoFileName !< Name of the summary file + CHARACTER(1), PARAMETER :: UVW(3) = (/'U','V','W'/) + CHARACTER(1), PARAMETER :: XYZ(3) = (/'X','Y','Z'/) + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg !< temporary error message + + !---------------------------------------------------------------------------------------------- + ! Initialize variables and check to see if this module has been initialized before. + !---------------------------------------------------------------------------------------------- + + ErrStat = ErrID_None + ErrMsg = "" + SumFileUnit = -1_IntKi ! set at beginning in case of error + + ! Set a few variables. + + p%DT = TimeInterval ! InflowWind does not require a specific time interval, so this is never changed. + CALL NWTC_Init() + CALL DispNVD( IfW_Ver ) + + !---------------------------------------------------------------------------------------------- + ! Read the input file + !---------------------------------------------------------------------------------------------- + + ! Set the names of the files based on the inputfilename + p%RootFileName = InitInp%RootName + IF (LEN_TRIM(p%RootFileName) == 0) CALL GetRoot( InitInp%InputFileName, p%RootFileName ) + EchoFileName = TRIM(p%RootFileName)//".ech" + SumFileName = TRIM(p%RootFileName)//".sum" + + ! these values (and others hard-coded in lidar_init) should be set in the input file, too + InputFileData%SensorType = InitInp%lidar%SensorType + InputFileData%NumPulseGate = InitInp%lidar%NumPulseGate + InputFileData%RotorApexOffsetPos = InitInp%lidar%RotorApexOffsetPos + InputFileData%LidRadialVel = InitInp%lidar%LidRadialVel + + ! Parse all the InflowWind related input files and populate the *_InitDataType derived types + CALL GetPath( InitInp%InputFileName, PriPath ) + + IF ( InitInp%UseInputFile ) THEN + CALL ProcessComFile( InitInp%InputFileName, InFileInfo, TmpErrStat, TmpErrMsg ) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() - CALL InflowWind_DestroyInputFile( InputFileData, TmpErrStat, TmpErrMsg ) RETURN - ENDIF - ! let's tell InflowWind if an external module (e.g., FAST.Farm) is going to set the velocity grids. - - IF ( InitInp%Use4Dext) then - InputFileData%WindType = FDext_WindNumber - InputFileData%PropagationDir = 0.0_ReKi ! wind is in XYZ coordinates (already rotated if necessary), so don't rotate it again - END IF - - ! initialize sensor data: - CALL Lidar_Init( InitInp, InputGuess, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & - y, m, TimeInterval, InitOutData, TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - + ENDIF + ELSE + CALL NWTC_Library_CopyFileInfoType( InitInp%PassedFileData, InFileInfo, MESH_NEWCOPY, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + ENDIF - ! Validate the InflowWind input file information. + CALL InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, InitInp%InputFileName, EchoFileName, & + InitInp%FixedWindFileRootName, InitInp%TurbineID, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF - CALL InflowWind_ValidateInput( InitInp, InputFileData, TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - - IF ( ErrStat>= AbortErrLev ) THEN + ! If wind is Grid4D from FAST.Farm, set input file values + IF (InitInp%Use4Dext) then + InputFileData%WindType = FDext_WindNumber + InputFileData%PropagationDir = 0.0_ReKi ! wind is in XYZ coordinates (already rotated if necessary), so don't rotate it again + InputFileData%VFlowAngle = 0.0_ReKi + InputFileData%VelInterpCubic = .false. + END IF + + ! initialize sensor data + CALL Lidar_Init( InitInp, InputGuess, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & + y, m, TimeInterval, InitOutData, TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + + ! Validate the InflowWind input file information + CALL InflowWind_ValidateInput( InitInp, InputFileData, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + + ! If a summary file was requested, open it and write preliminary data. + IF ( InputFileData%SumPrint ) THEN + CALL InflowWind_OpenSumFile( SumFileUnit, SumFileName, IfW_Ver, InputFileData%WindType, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) THEN CALL Cleanup() RETURN ENDIF + ENDIF + ! Allocate the array for passing points + CALL AllocAry( InputGuess%PositionXYZ, 3, InitInp%NumWindPoints, "Array of positions at which to find wind velocities", TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + InputGuess%PositionXYZ = 0.0_ReKi + InputGuess%HubPosition = 0.0_ReKi + CALL Eye(InputGuess%HubOrientation,TmpErrStat,TmpErrMsg) + + ! Allocate the array for passing velocities out + CALL AllocAry( y%VelocityUVW, 3, InitInp%NumWindPoints, "Array of wind velocities returned by InflowWind", TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF (ErrStat>= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF + y%VelocityUVW = 0.0_ReKi - - ! If a summary file was requested, open it. - IF ( InputFileData%SumPrint ) THEN - - ! Open the summary file and write some preliminary info to it - CALL InflowWind_OpenSumFile( SumFileUnit, SumFileName, IfW_Ver, InputFileData%WindType, TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - ENDIF - ELSE - SumFileUnit = -1_IntKi ! So that we don't try to write to something. Used as indicator in submodules. + ! If requested, allocate the array for passing accelerations out + IF ( InitInp%OutputAccel ) THEN + CALL AllocAry( y%AccelUVW, 3, InitInp%NumWindPoints, "Array of wind accelerations returned by InflowWind", TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF (ErrStat>= AbortErrLev) THEN + CALL Cleanup() + RETURN ENDIF + y%AccelUVW = 0.0_ReKi + ENDIF + !---------------------------------------------------------------------------- + ! Set flow field input data based on wind type + !---------------------------------------------------------------------------- - ! Allocate the arrays for passing points in and velocities out - CALL AllocAry( InputGuess%PositionXYZ, 3, InitInp%NumWindPoints, "Array of positions at which to find wind velocities", TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - InputGuess%PositionXYZ = 0.0_ReKi - InputGuess%HubPosition = 0.0_ReKi - CALL Eye(InputGuess%HubOrientation,TmpErrStat,TmpErrMsg) + InitOutData%WindFileInfo%MWS = HUGE(InitOutData%WindFileInfo%MWS) - CALL AllocAry( y%VelocityUVW, 3, InitInp%NumWindPoints, "Array of wind velocities returned by InflowWind", TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat>= AbortErrLev ) THEN - CALL Cleanup() - RETURN - ENDIF - y%VelocityUVW = 0.0_ReKi - - IF ( InitInp%OutputAccel ) THEN - CALL AllocAry( y%AccelUVW, 3, InitInp%NumWindPoints, "Array of wind accelerations returned by InflowWind", TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat>= AbortErrLev ) THEN - CALL Cleanup() - RETURN - ENDIF - y%AccelUVW = 0.0_ReKi - ENDIF + select case(InputFileData%WindType) + case (Steady_WindNumber) - !----------------------------------------------------------------- - ! Initialize the submodules based on the WindType - !----------------------------------------------------------------- + Steady_InitInput%HWindSpeed = InputFileData%Steady_HWindSpeed + Steady_InitInput%RefHt = InputFileData%Steady_RefHt + Steady_InitInput%PLExp = InputFileData%Steady_PLexp - - InitOutData%WindFileInfo%MWS = HUGE(InitOutData%WindFileInfo%MWS) - - ! General - FlowField_InitData%WindType = InputFileData%WindType - FlowField_InitData%SumFileUnit = SumFileUnit - FlowField_InitData%PropagationDir = InputFileData%PropagationDir - FlowField_InitData%VFlowAngle = InputFileData%VFlowAngle - FlowField_InitData%VelInterpCubic = InputFileData%VelInterpCubic - FlowField_InitData%OutputAccel = InitInp%OutputAccel - - select case(FlowField_InitData%WindType) - - case (Steady_WindNumber) - FlowField_InitData%Steady%HWindSpeed = InputFileData%Steady_HWindSpeed - FlowField_InitData%Steady%RefHt = InputFileData%Steady_RefHt - FlowField_InitData%Steady%PLExp = InputFileData%Steady_PLexp - - case (Uniform_WindNumber) - FlowField_InitData%Uniform%WindFileName = InputFileData%Uniform_FileName - FlowField_InitData%Uniform%RefHt = InputFileData%Uniform_RefHt - FlowField_InitData%Uniform%RefLength = InputFileData%Uniform_RefLength - FlowField_InitData%Uniform%PropagationDir = InputFileData%PropagationDir - FlowField_InitData%Uniform%UseInputFile = InitInp%WindType2UseInputFile - FlowField_InitData%Uniform%PassedFileData = InitInp%WindType2Data - - case (TSFF_WindNumber) - FlowField_InitData%TurbSim%WindFileName = InputFileData%TSFF_FileName - - case (BladedFF_WindNumber) - FlowField_InitData%Bladed%TurbineID = InitInp%TurbineID - IF ( InitInp%FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data - IF ( InitInp%TurbineID == 0 ) THEN ! .TRUE. for the FAST.Farm low-resolution domain - InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'Low' - ELSE ! FAST.Farm high-resolution domain(s) - InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) - ENDIF - ENDIF - FlowField_InitData%Bladed%WindFileName = TRIM(InputFileData%BladedFF_FileName)//'.wnd' - FlowField_InitData%Bladed%TowerFileExist = InputFileData%BladedFF_TowerFile - FlowField_InitData%Bladed%NativeBladedFmt = .false. - - case (BladedFF_Shr_WindNumber) - FlowField_InitData%Bladed%TurbineID = InitInp%TurbineID - FlowField_InitData%Bladed%WindFileName = InputFileData%BladedFF_FileName - FlowField_InitData%Bladed%TowerFileExist = .false. - FlowField_InitData%Bladed%NativeBladedFmt = .true. - - case (HAWC_WindNumber) - FlowField_InitData%HAWC%WindFileName(1) = InputFileData%HAWC_FileName_u - FlowField_InitData%HAWC%WindFileName(2) = InputFileData%HAWC_FileName_v - FlowField_InitData%HAWC%WindFileName(3) = InputFileData%HAWC_FileName_w - FlowField_InitData%HAWC%nx = InputFileData%HAWC_nx - FlowField_InitData%HAWC%ny = InputFileData%HAWC_ny - FlowField_InitData%HAWC%nz = InputFileData%HAWC_nz - FlowField_InitData%HAWC%dx = InputFileData%HAWC_dx - FlowField_InitData%HAWC%dy = InputFileData%HAWC_dy - FlowField_InitData%HAWC%dz = InputFileData%HAWC_dz - FlowField_InitData%HAWC%G3D%RefHt = InputFileData%FF%RefHt - FlowField_InitData%HAWC%G3D%ScaleMethod = InputFileData%FF%ScaleMethod - FlowField_InitData%HAWC%G3D%SF = InputFileData%FF%SF - FlowField_InitData%HAWC%G3D%SigmaF = InputFileData%FF%SigmaF - FlowField_InitData%HAWC%G3D%URef = InputFileData%FF%URef - FlowField_InitData%HAWC%G3D%WindProfileType = InputFileData%FF%WindProfileType - FlowField_InitData%HAWC%G3D%PLExp = InputFileData%FF%PLExp - FlowField_InitData%HAWC%G3D%Z0 = InputFileData%FF%Z0 - FlowField_InitData%HAWC%G3D%XOffset = InputFileData%FF%XOffset - - case (User_WindNumber) - ! Add user wind initialization data here - - case default - call SetErrStat(ErrID_Fatal, ' Undefined wind type.', ErrStat, ErrMsg, RoutineName) + p%FlowField%FieldType = Uniform_FieldType + call IfW_SteadyWind_Init(Steady_InitInput, SumFileUnit, p%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup() return - end select - - call FlowField_IO_Init(FlowField_InitData, p%FlowField, Interp_InitOutData, TmpErrStat, TmpErrMsg) - - - SELECT CASE ( InputFileData%WindType ) - - - CASE ( Steady_WindNumber ) - - ! This is a simplified case of the Uniform wind. For this, we set the OtherStates data manually and don't - ! call UniformWind_Init. We do however call it for the calculations. - - - ! Set InitInp information -- It isn't necessary to do this since that information is only used in the Uniform_Init routine, which is not called. - - ! Set the Otherstates information - p%UniformWind%NumDataLines = 1_IntKi + endif + + case (Uniform_WindNumber) + + Uniform_InitInput%WindFileName = InputFileData%Uniform_FileName + Uniform_InitInput%RefHt = InputFileData%Uniform_RefHt + Uniform_InitInput%RefLength = InputFileData%Uniform_RefLength + Uniform_InitInput%PropagationDir = InputFileData%PropagationDir + Uniform_InitInput%UseInputFile = InitInp%WindType2UseInputFile + Uniform_InitInput%PassedFileData = InitInp%WindType2Data + + p%FlowField%FieldType = Uniform_FieldType + call IfW_UniformWind_Init(Uniform_InitInput, SumFileUnit, p%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + endif - CALL AllocAry( p%UniformWind%Tdata, p%UniformWind%NumDataLines, 'Uniform wind time', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( p%UniformWind%V, p%UniformWind%NumDataLines, 'Uniform wind horizontal wind speed', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( p%UniformWind%Delta, p%UniformWind%NumDataLines, 'Uniform wind direction', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( p%UniformWind%Upflow, p%UniformWind%NumDataLines, 'Uniform wind upflow angle', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( p%UniformWind%VZ, p%UniformWind%NumDataLines, 'Uniform vertical wind speed', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( p%UniformWind%HShr, p%UniformWind%NumDataLines, 'Uniform horizontal linear shear', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( p%UniformWind%VShr, p%UniformWind%NumDataLines, 'Uniform vertical power-law shear exponent', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( p%UniformWind%VLinShr, p%UniformWind%NumDataLines, 'Uniform vertical linear shear', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - - CALL AllocAry( p%UniformWind%VGust, p%UniformWind%NumDataLines, 'Uniform gust velocity', TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - ENDIF - - ! Set the array information - - p%UniformWind%Tdata( :) = 0.0_ReKi - p%UniformWind%V( :) = InputFileData%Steady_HWindSpeed - p%UniformWind%Delta( :) = 0.0_ReKi - p%UniformWind%Upflow( :) = 0.0_ReKi - p%UniformWind%VZ( :) = 0.0_ReKi - p%UniformWind%HShr( :) = 0.0_ReKi - p%UniformWind%VShr( :) = InputFileData%Steady_PLexp - p%UniformWind%VLinShr(:) = 0.0_ReKi - p%UniformWind%VGust( :) = 0.0_ReKi - - - ! Now we have in effect initialized the IfW_UniformWind module, so set the parameters - p%UniformWind%RefLength = max(1.0_ReKi, InputFileData%Uniform_RefLength) ! This is not used since no shear gusts are used. Set to 1.0 so calculations don't bomb. - p%UniformWind%RefHt = InputFileData%Steady_RefHt - m%UniformWind%TimeIndex = 1_IntKi - - p%ReferenceHeight = p%UniformWind%RefHt - - ! Store wind file metadata - InitOutData%WindFileInfo%FileName = "" - InitOutData%WindFileInfo%WindType = Steady_WindNumber - InitOutData%WindFileInfo%RefHt = InputFileData%Steady_RefHt - InitOutData%WindFileInfo%RefHt_Set = .FALSE. ! The wind file does not set this - InitOutData%WindFileInfo%DT = 0.0_ReKi - InitOutData%WindFileInfo%NumTSteps = 1_IntKi - InitOutData%WindFileInfo%ConstantDT = .FALSE. - InitOutData%WindFileInfo%TRange = (/ 0.0_ReKi, 0.0_ReKi /) - InitOutData%WindFileInfo%TRange_Limited = .FALSE. ! This is constant - InitOutData%WindFileInfo%YRange = (/ 0.0_ReKi, 0.0_ReKi /) - InitOutData%WindFileInfo%YRange_Limited = .FALSE. ! Hard boundaries not enforced in y-direction - InitOutData%WindFileInfo%ZRange = (/ 0.0_ReKi, 0.0_ReKi /) - InitOutData%WindFileInfo%ZRange_Limited = .FALSE. ! Hard boundaries not enforced in z-direction - InitOutData%WindFileInfo%BinaryFormat = 0_IntKi - InitOutData%WindFileInfo%IsBinary = .FALSE. - InitOutData%WindFileInfo%TI = 0.0_ReKi - InitOutData%WindFileInfo%TI_listed = .FALSE. - InitOutData%WindFileInfo%MWS = InputFileData%Steady_HWindSpeed - - ! Write summary file information - IF ( SumFileUnit > 0 ) THEN - WRITE(SumFileUnit,'(A)',IOSTAT=TmpErrStat) - WRITE(SumFileUnit,'(A80)',IOSTAT=TmpErrStat) 'Steady wind -- Constant wind profile for entire simulation. No windfile read in.' - WRITE(SumFileUnit,'(A40,G12.4)',IOSTAT=TmpErrStat) ' Reference height: ',p%UniformWind%RefHt - WRITE(SumFileUnit,'(A40,G12.4)',IOSTAT=TmpErrStat) ' Horizontal velocity: ',p%UniformWind%V - WRITE(SumFileUnit,'(A40,G12.4)',IOSTAT=TmpErrStat) ' Vertical sheer power law exponent: ',p%UniformWind%VShr - - ! We are assuming that if the last line was written ok, then all of them were. - IF (TmpErrStat /= 0_IntKi) THEN - CALL SetErrStat(ErrID_Fatal,'Error writing to summary file.',ErrStat,ErrMsg,RoutineName) - CALL Cleanup - RETURN - ENDIF - ENDIF - - - CASE ( Uniform_WindNumber ) - - ! Set InitInp information - Uniform_InitData%ReferenceHeight = InputFileData%Uniform_RefHt - Uniform_InitData%RefLength = InputFileData%Uniform_RefLength - Uniform_InitData%WindFileName = InputFileData%Uniform_FileName - Uniform_InitData%SumFileUnit = SumFileUnit - - Uniform_InitData%UseInputFile = InitInp%WindType2UseInputFile - Uniform_InitData%PassedFileData = InitInp%WindType2Data - - ! Initialize the UniformWind module - CALL IfW_UniformWind_Init(Uniform_InitData, p%UniformWind, & - m%UniformWind, Uniform_InitOutData, TmpErrStat, TmpErrMsg) - - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, ' IfW_Init' ) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - ENDIF - - if (InitInp%Linearize) then - ! we'd have to redo the math to get this correct, so for now we are disabling upflow for linearization: - if (any(p%UniformWind%upflow /= 0.0_ReKi) ) then - call SetErrStat(ErrID_Fatal, 'Upflow in uniform wind files must be 0 for linearization analysis in InflowWind.', ErrStat, ErrMsg, RoutineName) - CALL Cleanup() - return - end if - end if + case (TSFF_WindNumber) + TurbSim_InitInput%WindFileName = InputFileData%TSFF_FileName - p%ReferenceHeight = p%UniformWind%RefHt - - ! Store wind file metadata - InitOutData%WindFileInfo%FileName = InputFileData%Uniform_FileName - InitOutData%WindFileInfo%WindType = Uniform_WindNumber - InitOutData%WindFileInfo%RefHt = p%UniformWind%RefHt - InitOutData%WindFileInfo%RefHt_Set = .FALSE. ! The wind file does not set this - InitOutData%WindFileInfo%DT = Uniform_InitOutData%WindFileDT - InitOutData%WindFileInfo%NumTSteps = Uniform_InitOutData%WindFileNumTSteps - InitOutData%WindFileInfo%ConstantDT = Uniform_InitOutData%WindFileConstantDT - InitOutData%WindFileInfo%TRange = Uniform_InitOutData%WindFileTRange - InitOutData%WindFileInfo%TRange_Limited = .FALSE. ! UniformWind sets to limit of file if outside time bounds - InitOutData%WindFileInfo%YRange = (/ 0.0_ReKi, 0.0_ReKi /) - InitOutData%WindFileInfo%YRange_Limited = .FALSE. ! Hard boundaries not enforced in y-direction - InitOutData%WindFileInfo%ZRange = (/ 0.0_ReKi, 0.0_ReKi /) - InitOutData%WindFileInfo%ZRange_Limited = .FALSE. ! Hard boundaries not enforced in z-direction - InitOutData%WindFileInfo%BinaryFormat = 0_IntKi - InitOutData%WindFileInfo%IsBinary = .FALSE. - InitOutData%WindFileInfo%TI = 0.0_ReKi - InitOutData%WindFileInfo%TI_listed = .FALSE. - - if (p%UniformWind%NumDataLines == 1) then - InitOutData%WindFileInfo%MWS = p%UniformWind%V(1) - else - InitOutData%WindFileInfo%MWS = 0.0_ReKi - do i=2,p%UniformWind%NumDataLines - InitOutData%WindFileInfo%MWS = InitOutData%WindFileInfo%MWS + & - 0.5_ReKi*(p%UniformWind%V(i)+p%UniformWind%V(i-1))*& - (p%UniformWind%Tdata(i)-p%UniformWind%Tdata(i-1)) - end do - InitOutData%WindFileInfo%MWS = InitOutData%WindFileInfo%MWS / & - ( p%UniformWind%Tdata(p%UniformWind%NumDataLines) - p%UniformWind%Tdata(1) ) - end if - - - ! Check if the fist data point from the file is not along the X-axis while applying the windfield rotation - IF ( ( .NOT. EqualRealNos (p%UniformWind%Delta(1), 0.0_ReKi) ) .AND. & - ( .NOT. EqualRealNos (p%PropagationDir, 0.0_ReKi) ) ) THEN - CALL SetErrStat( ErrID_Warn,' Possible double rotation of wind field! Uniform wind file starts with a wind direction of '// & - TRIM(Num2LStr(p%UniformWind%Delta(1)*R2D))// & - ' degrees and the InflowWind input file specifies a PropagationDir of '// & - TRIM(Num2LStr(p%PropagationDir*R2D))//' degrees.', & - ErrStat,ErrMsg,RoutineName ) - ENDIF - - - - CASE ( TSFF_WindNumber ) - - ! Set InitInp information - TSFF_InitData%WindFileName = InputFileData%TSFF_FileName - TSFF_InitData%SumFileUnit = SumFileUnit - - ! Initialize the TSFFWind module - CALL IfW_TSFFWind_Init(TSFF_InitData, p%TSFFWind, & - m%TSFFWind, TSFF_InitOutData, TmpErrStat, TmpErrMsg) - CALL SetErrSTat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - ENDIF - - ! Store wind file metadata - InitOutData%WindFileInfo%FileName = InputFileData%TSFF_FileName - - CALL SetFFInitOutData(p%TSFFWind%FF) - p%ReferenceHeight = InitOutData%WindFileInfo%RefHt + p%FlowField%FieldType = Grid3D_FieldType + call IfW_TurbSim_Init(TurbSim_InitInput, SumFileUnit, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + endif + case (BladedFF_WindNumber) - CASE ( BladedFF_WindNumber, BladedFF_Shr_WindNumber ) + Bladed_InitInput%TurbineID = InitInp%TurbineID + IF ( InitInp%FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data + IF ( InitInp%TurbineID == 0 ) THEN ! .TRUE. for the FAST.Farm low-resolution domain + InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'Low' + ELSE ! FAST.Farm high-resolution domain(s) + InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) + ENDIF + ENDIF + Bladed_InitInput%WindType = BladedFF_WindNumber + Bladed_InitInput%WindFileName = TRIM(InputFileData%BladedFF_FileName)//'.wnd' + Bladed_InitInput%TowerFileExist = InputFileData%BladedFF_TowerFile + Bladed_InitInput%NativeBladedFmt = .false. + + p%FlowField%FieldType = Grid3D_FieldType + call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + endif + + case (BladedFF_Shr_WindNumber) + + Bladed_InitInput%WindType = BladedFF_Shr_WindNumber + Bladed_InitInput%TurbineID = InitInp%TurbineID + Bladed_InitInput%WindFileName = InputFileData%BladedFF_FileName + Bladed_InitInput%TowerFileExist = .false. + Bladed_InitInput%NativeBladedFmt = .true. + + p%FlowField%FieldType = Grid3D_FieldType + call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + endif + + ! Overwrite the values of PropagationDir and VFlowAngle with values from the native Bladed file + InputFileData%PropagationDir = Bladed_InitOutput%PropagationDir + InputFileData%VFlowAngle = Bladed_InitOutput%VFlowAngle + + case (HAWC_WindNumber) + + HAWC_InitInput%WindFileName(1) = InputFileData%HAWC_FileName_u + HAWC_InitInput%WindFileName(2) = InputFileData%HAWC_FileName_v + HAWC_InitInput%WindFileName(3) = InputFileData%HAWC_FileName_w + HAWC_InitInput%nx = InputFileData%HAWC_nx + HAWC_InitInput%ny = InputFileData%HAWC_ny + HAWC_InitInput%nz = InputFileData%HAWC_nz + HAWC_InitInput%dx = InputFileData%HAWC_dx + HAWC_InitInput%dy = InputFileData%HAWC_dy + HAWC_InitInput%dz = InputFileData%HAWC_dz + HAWC_InitInput%G3D%RefHt = InputFileData%FF%RefHt + HAWC_InitInput%G3D%ScaleMethod = InputFileData%FF%ScaleMethod + HAWC_InitInput%G3D%SF = InputFileData%FF%SF + HAWC_InitInput%G3D%SigmaF = InputFileData%FF%SigmaF + HAWC_InitInput%G3D%URef = InputFileData%FF%URef + HAWC_InitInput%G3D%WindProfileType = InputFileData%FF%WindProfileType + HAWC_InitInput%G3D%PLExp = InputFileData%FF%PLExp + HAWC_InitInput%G3D%Z0 = InputFileData%FF%Z0 + HAWC_InitInput%G3D%XOffset = InputFileData%FF%XOffset + + p%FlowField%FieldType = Grid3D_FieldType + call IfW_HAWC_Init(HAWC_InitInput, SumFileUnit, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + endif - ! Set InitInp information - BladedFF_InitData%SumFileUnit = SumFileUnit - BladedFF_InitData%FixedWindFileRootName = InitInp%FixedWindFileRootName - BladedFF_InitData%TurbineID = InitInp%TurbineID - - if (InputFileData%WindType /= BladedFF_Shr_WindNumber) then - IF ( InitInp%FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data - IF ( InitInp%TurbineID == 0 ) THEN ! .TRUE. for the FAST.Farm low-resolution domain - InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'Low' - ELSE ! FAST.Farm high-resolution domain(s) - InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) - ENDIF - ENDIF - - BladedFF_InitData%WindFileName = TRIM(InputFileData%BladedFF_FileName)//'.wnd' - BladedFF_InitData%TowerFileExist = InputFileData%BladedFF_TowerFile - BladedFF_InitData%NativeBladedFmt = .false. - else - BladedFF_InitData%WindFileName = InputFileData%BladedFF_FileName - BladedFF_InitData%TowerFileExist = .false. - BladedFF_InitData%NativeBladedFmt = .true. - !call IfW_FFWind_CopyInitInput( InputFileData%FF, BladedFF_InitData%FF, MESH_NEWCOPY, TmpErrStat, TmpErrMsg) - end if - - ! Initialize the BladedFFWind module - CALL IfW_BladedFFWind_Init(BladedFF_InitData, p%BladedFFWind, m%BladedFFWind, & - BladedFF_InitOutData, TmpErrStat, TmpErrMsg) - CALL SetErrSTat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - ENDIF - - ! Store wind file metadata - InitOutData%WindFileInfo%FileName = InputFileData%BladedFF_FileName - - CALL SetFFInitOutData(p%BladedFFWind%FF) + case (User_WindNumber) - InitOutData%WindFileInfo%TI = BladedFF_InitOutData%TI - InitOutData%WindFileInfo%TI_listed = .TRUE. ! This must be listed in the file someplace - - if (InputFileData%WindType == BladedFF_Shr_WindNumber) then - InputFileData%WindType = BladedFF_WindNumber - ! this overwrites the values of PropagationDir and VFlowAngle with values from the native Bladed file - InputFileData%PropagationDir = BladedFF_InitOutData%PropagationDir - InputFileData%VFlowAngle = BladedFF_InitOutData%VFlowAngle - end if - p%ReferenceHeight = InitOutData%WindFileInfo%RefHt + p%FlowField%FieldType = User_FieldType + call IfW_User_Init(User_InitInput, SumFileUnit, p%FlowField%User, FileDat, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + endif - - CASE ( HAWC_WindNumber ) - - ! Set InitInp information - HAWC_InitData%WindFileName(1) = InputFileData%HAWC_FileName_u - HAWC_InitData%WindFileName(2) = InputFileData%HAWC_FileName_v - HAWC_InitData%WindFileName(3) = InputFileData%HAWC_FileName_w - HAWC_InitData%SumFileUnit = SumFileUnit - HAWC_InitData%nx = InputFileData%HAWC_nx - HAWC_InitData%ny = InputFileData%HAWC_ny - HAWC_InitData%nz = InputFileData%HAWC_nz - - HAWC_InitData%dx = InputFileData%HAWC_dx - HAWC_InitData%dy = InputFileData%HAWC_dy - HAWC_InitData%dz = InputFileData%HAWC_dz - - call IfW_FFWind_CopyInitInput( InputFileData%FF, HAWC_InitData%FF, MESH_NEWCOPY, TmpErrStat, TmpErrMsg) - - - ! Initialize the HAWCWind module - CALL IfW_HAWCWind_Init(HAWC_InitData, p%HAWCWind, m%HAWCWind, & - TimeInterval, HAWC_InitOutData, TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - ENDIF + case (FDext_WindNumber) + p%FlowField%FieldType = Grid4D_FieldType + call IfW_Grid4D_Init(InitInp%FDext, p%FlowField%Grid4D, FileDat, TmpErrStat, TmpErrMsg) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + endif - ! Store wind file metadata - CALL SetFFInitOutData(p%HAWCWind%FF) - InitOutData%WindFileInfo%FileName = InputFileData%HAWC_FileName_u - p%ReferenceHeight = InitOutData%WindFileInfo%RefHt + ! case (Point_WindNumber) - - CASE (User_WindNumber) - - ! Initialize the UserWind module - CALL IfW_UserWind_Init(User_InitData, p%UserWind, m%UserWind, & - TimeInterval, User_InitOutData, TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - ENDIF - - p%ReferenceHeight = InputFileData%Steady_RefHt ! FIXME!!!! - - CASE ( FDext_WindNumber ) - - ! Initialize the UserWind module - CALL IfW_4Dext_Init(InitInp%FDext, p%FDext, m%FDext, TimeInterval, FDext_InitOutData, TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - ENDIF - p%ReferenceHeight = p%FDext%pZero(3) + (p%FDext%n(3)/2) * p%FDext%delta(3) ! should be middle of grid, right???? FIXME - - CASE DEFAULT ! keep this check to make sure that all new wind types have been accounted for - CALL SetErrStat(ErrID_Fatal,' Undefined wind type.',ErrStat,ErrMsg,'InflowWind_Init()') + ! p%FlowField%FieldType = Point_FieldType + case default + call SetErrStat(ErrID_Fatal, ' Undefined wind type.', ErrStat, ErrMsg, RoutineName) + return + end select + !---------------------------------------------------------------------------- + ! Initialization by Field Type + !---------------------------------------------------------------------------- + ! Reset flag indicating that acceleration field is valid + p%FlowField%AccFieldValid = .false. - END SELECT - + ! Copy flag for enabling cubic velocity interpolation + p%FlowField%VelInterpCubic = InputFileData%VelInterpCubic - !IF ( InputFileData%CTTS_Flag ) THEN - ! ! Initialize the CTTS_Wind module - !ENDIF + ! If cubic velocity interpolation requested and linearization is performed, + ! display message that cubic interpolation is incompatible with linearization + ! and will be disabled + if (p%FlowField%VelInterpCubic .and. InitInp%Linearize) then + call WrScr("InflowWind: Cubic interpolation of wind velocity is disabled for linearization") + p%FlowField%VelInterpCubic = .false. + end if + ! Select based on field type + select case (p%FlowField%FieldType) + case (Uniform_FieldType) - !............................................ - ! Set the p and OtherStates for InflowWind using the input file information. - ! (set this after initializing modules so that we can use propagationDir and VFlowAng from native-Bladed files - !............................................ + if (InitInp%OutputAccel .or. p%FlowField%VelInterpCubic) then + call IfW_UniformField_CalcAccel(p%FlowField%Uniform, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + p%FlowField%AccFieldValid = .true. + end if - CALL InflowWind_SetParameters( InitInp, InputFileData, p, m, TmpErrStat, TmpErrMsg ) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat>= AbortErrLev ) THEN - CALL Cleanup() - RETURN - ENDIF + case (Grid3D_FieldType) - + if (InitInp%OutputAccel .or. p%FlowField%VelInterpCubic) then + call IfW_Grid3DField_CalcAccel(p%FlowField%Grid3D, TmpErrStat, TmpErrMsg) + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + p%FlowField%AccFieldValid = .true. + end if -!!! !---------------------------------------------------------------------------------------------- -!!! ! Check for coherent turbulence file (KH superimposed on a background wind file) -!!! ! Initialize the CTWind module and initialize the module of the other wind type. -!!! !---------------------------------------------------------------------------------------------- -!!! -!!! IF ( p%WindType == CTP_WindNumber ) THEN -!!! -!!!!FIXME: remove this error message when we add CTP_Wind in -!!! CALL SetErrStat( ErrID_Fatal, ' InflowWind cannot currently handle the CTP_Wind type.', ErrStat, ErrMsg, ' IfW_Init' ) -!!! RETURN -!!! -!!! CALL CTTS_Init(UnWind, p%WindFileName, BackGrndValues, ErrStat, ErrMsg) -!!! IF (ErrStat /= 0) THEN -!!! p%WindType = Undef_Wind -!!! ErrStat = ErrID_Fatal -!!! RETURN -!!! END IF -!!! -!!! !FIXME: check this -!!! p%WindFileName = BackGrndValues%WindFile -!!! p%WindType = BackGrndValues%WindType -!!! ! CTTS_Flag = BackGrndValues%CoherentStr -!!! p%CTTS_Flag = BackGrndValues%CoherentStr ! This might be wrong -!!! -!!! ELSE -!!! -!!! p%CTTS_Flag = .FALSE. -!!! -!!! END IF -!!! + case default + if (InitInp%OutputAccel) then + call SetErrStat(ErrID_Fatal, "Acceleration not implemented for field type "// & + num2LStr(p%FlowField%FieldType), ErrStat, ErrMsg, RoutineName) + return + end if + if (p%FlowField%VelInterpCubic) then + call WrScr(' Cubic velocity interpolation not implemented for WindType '// & + num2LStr(InputFileData%WindType)) + p%FlowField%VelInterpCubic = .false. + end if + end select + + !---------------------------------------------------------------------------- + ! Set the p and OtherStates for InflowWind using the input file information. + ! (set this after initializing modules so that we can use PropagationDir + ! and VFlowAng from native-Bladed files + !---------------------------------------------------------------------------- + + CALL InflowWind_SetParameters( InitInp, InputFileData, p, m, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + + ! Allocate arrays for the WriteOutput + CALL AllocAry( y%WriteOutput, p%NumOuts, 'WriteOutput', TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + y%WriteOutput = 0.0_ReKi + + CALL AllocAry( InitOutData%WriteOutputHdr, p%NumOuts, 'WriteOutputHdr', TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + CALL AllocAry( InitOutData%WriteOutputUnt, p%NumOuts, 'WriteOutputUnt', TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + InitOutData%WriteOutputHdr = p%OutParam(1:p%NumOuts)%Name + InitOutData%WriteOutputUnt = p%OutParam(1:p%NumOuts)%Units + !---------------------------------------------------------------------------- + ! Linearization + !---------------------------------------------------------------------------- - ! Allocate arrays for the WriteOutput + ! allocate and fill variables for linearization + if (InitInp%Linearize) then + + ! If field is uniform and there is any nonzero upflow, return error + ! Math needs work before this can be implemented + if (p%FlowField%FieldType == Uniform_FieldType) then + if (any(p%FlowField%Uniform%AngleV /= 0.0_ReKi)) then + call SetErrStat(ErrID_Fatal, 'Upflow in uniform wind files must be 0 for linearization analysis in InflowWind.', ErrStat, ErrMsg, RoutineName) + call Cleanup() + return + end if + end if - CALL AllocAry( y%WriteOutput, p%NumOuts, 'WriteOutput', TmpErrStat, TmpErrMsg ) + ! also need to add InputGuess%HubOrientation to the u%Linear items + CALL AllocAry(InitOutData%LinNames_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'LinNames_u', TmpErrStat, TmpErrMsg) ! add hub position, orientation(3) + extended inputs CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat>= AbortErrLev ) THEN - CALL Cleanup() - RETURN - ENDIF - y%WriteOutput = 0.0_ReKi - - CALL AllocAry( InitOutData%WriteOutputHdr, p%NumOuts, 'WriteOutputHdr', TmpErrStat, TmpErrMsg ) + CALL AllocAry(InitOutData%RotFrame_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'RotFrame_u', TmpErrStat, TmpErrMsg) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - CALL AllocAry( InitOutData%WriteOutputUnt, p%NumOuts, 'WriteOutputUnt', TmpErrStat, TmpErrMsg ) + CALL AllocAry(InitOutData%IsLoad_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'IsLoad_u', TmpErrStat, TmpErrMsg) CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF ( ErrStat>= AbortErrLev ) THEN - CALL Cleanup() - RETURN - ENDIF - - InitOutData%WriteOutputHdr = p%OutParam(1:p%NumOuts)%Name - InitOutData%WriteOutputUnt = p%OutParam(1:p%NumOuts)%Units - - - ! allocate and fill variables for linearization: - if (InitInp%Linearize) then - ! also need to add InputGuess%HubOrientation to the u%Linear items - CALL AllocAry(InitOutData%LinNames_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'LinNames_u', TmpErrStat, TmpErrMsg) ! add hub position, orientation(3) + extended inputs - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - CALL AllocAry(InitOutData%RotFrame_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'RotFrame_u', TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - CALL AllocAry(InitOutData%IsLoad_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'IsLoad_u', TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - CALL AllocAry(InitOutData%LinNames_y, InitInp%NumWindPoints*3 + size(y%DiskVel) + p%NumOuts, 'LinNames_y', TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - CALL AllocAry(InitOutData%RotFrame_y, InitInp%NumWindPoints*3 + size(y%DiskVel) + p%NumOuts, 'RotFrame_y', TmpErrStat, TmpErrMsg) - CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - IF (ErrStat >= AbortErrLev) THEN - CALL Cleanup() - RETURN - ENDIF - - do i=1,InitInp%NumWindPoints - do j=1,3 - InitOutData%LinNames_y((i-1)*3+j) = UVW(j)//'-component inflow velocity at node '//trim(num2lstr(i))//', m/s' - InitOutData%LinNames_u((i-1)*3+j) = XYZ(j)//'-component position of node '//trim(num2lstr(i))//', m' - end do - end do - - ! hub position - Lin_Indx = InitInp%NumWindPoints*3 - do j=1,3 - InitOutData%LinNames_y(Lin_Indx+j) = 'average '//UVW(j)//'-component rotor-disk velocity, m/s' - InitOutData%LinNames_u(Lin_Indx+j) = XYZ(j)//'-component position of moving hub, m' - end do - Lin_Indx = Lin_Indx + 3 - - ! hub orientation angles + CALL AllocAry(InitOutData%LinNames_y, InitInp%NumWindPoints*3 + size(y%DiskVel) + p%NumOuts, 'LinNames_y', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOutData%RotFrame_y, InitInp%NumWindPoints*3 + size(y%DiskVel) + p%NumOuts, 'RotFrame_y', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF + + do i=1,InitInp%NumWindPoints do j=1,3 - InitOutData%LinNames_u(Lin_Indx+j) = XYZ(j)//' orientation of moving hub, rad' - end do - Lin_Indx = Lin_Indx + 3 - - - InitOutData%LinNames_u(Lin_Indx + 1) = 'Extended input: horizontal wind speed (steady/uniform wind), m/s' - InitOutData%LinNames_u(Lin_Indx + 2) = 'Extended input: vertical power-law shear exponent, -' - InitOutData%LinNames_u(Lin_Indx + 3) = 'Extended input: propagation direction, rad' - - do i=1,p%NumOuts - InitOutData%LinNames_y(i+3*InitInp%NumWindPoints+size(y%DiskVel)) = trim(p%OutParam(i)%Name)//', '//p%OutParam(i)%Units + InitOutData%LinNames_y((i-1)*3+j) = UVW(j)//'-component inflow velocity at node '//trim(num2lstr(i))//', m/s' + InitOutData%LinNames_u((i-1)*3+j) = XYZ(j)//'-component position of node '//trim(num2lstr(i))//', m' end do + end do - ! IfW inputs and outputs are in the global, not rotating frame - InitOutData%RotFrame_u = .false. - InitOutData%RotFrame_y = .false. - - InitOutData%IsLoad_u = .false. ! IfW inputs for linearization are not loads - - !InitOutData%PropagationDir = -p%PropagationDir - !InitOutData%RefHt = p%UniformWind%RefHt - !InitOutData%RefLength = p%UniformWind%RefLength - - end if - - - ! Set the version information in InitOutData - InitOutData%Ver = IfW_Ver - - - CALL CleanUp() + ! hub position + Lin_Indx = InitInp%NumWindPoints*3 + do j=1,3 + InitOutData%LinNames_y(Lin_Indx+j) = 'average '//UVW(j)//'-component rotor-disk velocity, m/s' + InitOutData%LinNames_u(Lin_Indx+j) = XYZ(j)//'-component position of moving hub, m' + end do + Lin_Indx = Lin_Indx + 3 + + ! hub orientation angles + do j=1,3 + InitOutData%LinNames_u(Lin_Indx+j) = XYZ(j)//' orientation of moving hub, rad' + end do + Lin_Indx = Lin_Indx + 3 + + InitOutData%LinNames_u(Lin_Indx + 1) = 'Extended input: horizontal wind speed (steady/uniform wind), m/s' + InitOutData%LinNames_u(Lin_Indx + 2) = 'Extended input: vertical power-law shear exponent, -' + InitOutData%LinNames_u(Lin_Indx + 3) = 'Extended input: propagation direction, rad' + + do i=1,p%NumOuts + InitOutData%LinNames_y(i+3*InitInp%NumWindPoints+size(y%DiskVel)) = trim(p%OutParam(i)%Name)//', '//p%OutParam(i)%Units + end do + ! IfW inputs and outputs are in the global, not rotating frame + InitOutData%RotFrame_u = .false. + InitOutData%RotFrame_y = .false. - RETURN + InitOutData%IsLoad_u = .false. ! IfW inputs for linearization are not loads + + end if + + ! Set the version information in InitOutData + InitOutData%Ver = IfW_Ver + CALL CleanUp() - !---------------------------------------------------------------------------------------------------- CONTAINS SUBROUTINE CleanUp() @@ -865,6 +589,7 @@ SUBROUTINE CleanUp() ! Ignore error messages from InFileInfo destruction call NWTC_Library_DestroyFileInfoType( InFileInfo, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) ! Close the summary file if we were writing one IF ( SumFileUnit > 0 ) THEN @@ -872,45 +597,7 @@ SUBROUTINE CleanUp() CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) ENDIF - END SUBROUTINE CleanUp - - - SUBROUTINE SetFFInitOutData(FFp) - - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: FFp !< Parameters - - - InitOutData%WindFileInfo%WindType = p%WindType - InitOutData%WindFileInfo%RefHt = FFp%RefHt - InitOutData%WindFileInfo%RefHt_Set = .TRUE. - InitOutData%WindFileInfo%DT = FFp%FFDTime - InitOutData%WindFileInfo%NumTSteps = FFp%NFFSteps - InitOutData%WindFileInfo%ConstantDT = .TRUE. - IF ( FFp%Periodic ) THEN - InitOutData%WindFileInfo%TRange = (/ 0.0_ReKi, FFp%TotalTime /) - InitOutData%WindFileInfo%TRange_Limited = .FALSE. - ELSE ! Shift the time range to compensate for the shifting of the wind grid - InitOutData%WindFileInfo%TRange = (/ 0.0_ReKi, FFp%TotalTime /) - FFp%InitXPosition*FFp%InvMFFWS - InitOutData%WindFileInfo%TRange_Limited = .TRUE. - ENDIF - InitOutData%WindFileInfo%YRange = (/ -FFp%FFYHWid, FFp%FFYHWid /) - InitOutData%WindFileInfo%YRange_Limited = .TRUE. ! Hard boundaries enforced in y-direction - IF ( p%TSFFWind%FF%NTGrids > 0 ) THEN ! have tower data - InitOutData%WindFileInfo%ZRange = (/ 0.0_Reki, FFp%RefHt + FFp%FFZHWid /) - ELSE - InitOutData%WindFileInfo%ZRange = (/ FFp%GridBase, & - FFp%GridBase + FFp%FFZHWid*2.0 /) - ENDIF - InitOutData%WindFileInfo%ZRange_Limited = .TRUE. - InitOutData%WindFileInfo%BinaryFormat = FFp%WindFileFormat - InitOutData%WindFileInfo%IsBinary = .TRUE. - InitOutData%WindFileInfo%MWS = FFp%MeanFFWS - - InitOutData%WindFileInfo%TI = 0.0_ReKi - InitOutData%WindFileInfo%TI_listed = .FALSE. - - END SUBROUTINE SetFFInitOutData END SUBROUTINE InflowWind_Init @@ -934,14 +621,8 @@ SUBROUTINE InflowWind_CalcOutput( Time, InputData, p, & ContStates, DiscStates, ConstrStates, & ! Framework required states -- empty in this case. OtherStates, OutputData, m, ErrStat, ErrMsg ) - - IMPLICIT NONE - CHARACTER(*), PARAMETER :: RoutineName="InflowWind_CalcOutput" - - ! Inputs / Outputs - REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds TYPE(InflowWind_InputType), INTENT(IN ) :: InputData !< Inputs at Time TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters @@ -951,24 +632,18 @@ SUBROUTINE InflowWind_CalcOutput( Time, InputData, p, & TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherStates !< Other/optimization states at Time TYPE(InflowWind_OutputType), INTENT(INOUT) :: OutputData !< Outputs computed at Time (IN for mesh reasons and data allocation) TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! Local variables INTEGER(IntKi) :: i ! Temporary variables for error handling INTEGER(IntKi) :: TmpErrStat CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = "" - ! Allocate the velocity array to get out IF ( .NOT. ALLOCATED(OutputData%VelocityUVW) ) THEN CALL AllocAry( OutputData%VelocityUVW, 3, SIZE(InputData%PositionXYZ,DIM=2), & @@ -1036,81 +711,36 @@ END SUBROUTINE InflowWind_CalcOutput !> Clean up the allocated variables and close all open files. Reset the initialization flag so !! that we have to reinitialize before calling the routines again. SUBROUTINE InflowWind_End( InputData, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & - y, m, ErrStat, ErrMsg ) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="InflowWind_End" - - ! Initialization data and guesses + y, m, ErrStat, ErrMsg ) TYPE(InflowWind_InputType), INTENT(INOUT) :: InputData !< Input data for initialization - TYPE(InflowWind_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(InflowWind_ParameterType), INTENT(INOUT) :: p !< Parameters TYPE(InflowWind_ContinuousStateType), INTENT(INOUT) :: ContStates !< Continuous states TYPE(InflowWind_DiscreteStateType), INTENT(INOUT) :: DiscStates !< Discrete states TYPE(InflowWind_ConstraintStateType), INTENT(INOUT) :: ConstrStateGuess !< Guess of the constraint states TYPE(InflowWind_OtherStateType), INTENT(INOUT) :: OtherStates !< Other/optimization states - TYPE(InflowWind_OutputType), INTENT(INOUT) :: y !< Output data - TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - - - ! Error Handling - + TYPE(InflowWind_OutputType), INTENT(INOUT) :: y !< Output data + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) INTEGER( IntKi ), INTENT( OUT) :: ErrStat !< error status CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message + CHARACTER(*), PARAMETER :: RoutineName="InflowWind_End" ErrStat = ErrID_None ErrMsg = "" - ! End the sub-modules (deallocates their arrays and closes their files): - - SELECT CASE ( p%WindType ) - - CASE (Steady_WindNumber, Uniform_WindNumber) ! The Steady wind is a simple wrapper for the UniformWind module. - CALL IfW_UniformWind_End( p%UniformWind, m%UniformWind, ErrStat, ErrMsg ) - - CASE (TSFF_WindNumber) - CALL IfW_TSFFWind_End( p%TSFFWind, m%TSFFWind, ErrStat, ErrMsg ) - - CASE (BladedFF_WindNumber) - CALL IfW_BladedFFWind_End( p%BladedFFWind, m%BladedFFWind, ErrStat, ErrMsg ) - - CASE (HAWC_WindNumber) - CALL IfW_HAWCWind_End( p%HAWCWind, m%HAWCWind, ErrStat, ErrMsg ) - - CASE (User_WindNumber) - CALL IfW_UserWind_End( p%UserWind, m%UserWind, ErrStat, ErrMsg ) - - CASE (FDext_WindNumber) - CALL IfW_4Dext_End( p%FDext, m%FDext, ErrStat, ErrMsg ) - - CASE ( Undef_WindNumber ) - ! Do nothing - - CASE DEFAULT ! keep this check to make sure that all new wind types have been accounted for - CALL SetErrStat(ErrID_Fatal,' Undefined wind type.',ErrStat,ErrMsg,RoutineName) - - END SELECT - -!!! ! IF (CTTS_Flag) CALL CTTS_Terminate( ErrStat ) !FIXME: should it be this line or the next? -!!! CALL CTTS_Terminate( ErrStat, ErrMsg ) - + ! Reset the wind type so that the initialization routine must be called + p%WindType = Undef_WindNumber + ! Destroy all inflow wind derived types CALL InflowWind_DestroyInput( InputData, ErrStat, ErrMsg ) - CALL InflowWind_DestroyParam( p, ErrStat, ErrMsg ) + CALL InflowWind_DestroyParam( p, ErrStat, ErrMsg, DeallocatePointers=.true. ) CALL InflowWind_DestroyContState( ContStates, ErrStat, ErrMsg ) CALL InflowWind_DestroyDiscState( DiscStates, ErrStat, ErrMsg ) CALL InflowWind_DestroyConstrState( ConstrStateGuess, ErrStat, ErrMsg ) CALL InflowWind_DestroyOtherState( OtherStates, ErrStat, ErrMsg ) CALL InflowWind_DestroyOutput( y, ErrStat, ErrMsg ) CALL InflowWind_DestroyMisc( m, ErrStat, ErrMsg ) - - - ! Reset the wind type so that the initialization routine must be called - p%WindType = Undef_WindNumber - p%CTTS_Flag = .FALSE. - END SUBROUTINE InflowWind_End @@ -1326,10 +956,10 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt n = SIZE(u%PositionXYZ,2) ! these are the positions used in the module coupling do i=1,n - ! note that p%RotToWind(1,1) = cos(p%PropagationDir) and p%RotToWind(2,1) = sin(p%PropagationDir), which are the + ! note that p%FlowField%RotToWind(1,1) = cos(p%PropagationDir) and p%FlowField%RotToWind(2,1) = sin(p%PropagationDir), which are the ! values we need to compute the jacobian. !!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput( t, u%PositionXYZ(:,i), p%RotToWind(1,1), p%RotToWind(2,1), p%UniformWind, m%UniformWind, local_dYdu ) + call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, u%PositionXYZ(:,i), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) i_end = 3*i i_start= i_end - 2 @@ -1352,7 +982,7 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt do i=1,IfW_NumPtsAvg m%u_Avg%PositionXYZ(:,i) = matmul(u%HubOrientation,p%PositionAvg(:,i)) + u%HubPosition !!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput( t, m%u_Avg%PositionXYZ(:,i), p%RotToWind(1,1), p%RotToWind(2,1), p%UniformWind, m%UniformWind, local_dYdu ) + call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, m%u_Avg%PositionXYZ(:,i), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) ! y%DiskAvg has the same index as u%HubPosition ! Also note that partial_(m%u_Avg%PositionXYZ) / partial_(u%HubPosition) is identity, so we can skip that part of the chain rule for these derivatives: @@ -1374,7 +1004,7 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt if (node > 0) then !!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput( t, p%WindViXYZ(:,node), p%RotToWind(1,1), p%RotToWind(2,1), p%UniformWind, m%UniformWind, local_dYdu ) + call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, p%WindViXYZ(:,node), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) else local_dYdu = 0.0_R8Ki comp = 1 @@ -1403,6 +1033,121 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt END SUBROUTINE InflowWind_JacobianPInput +!.................................................................................................................................. +!> Routine to compute the Jacobians of the output (Y) function with respect to the inputs (u). The partial +!! derivative dY/du is returned. This submodule does not follow the modularization framework. +SUBROUTINE IfW_UniformWind_JacobianPInput(UF, t, Position, CosPropDir, SinPropDir, dYdu) + USE IfW_FlowField, only : UniformField_InterpLinear, UniformField_InterpCubic + + TYPE(UniformFieldType), INTENT(IN ) :: UF !< Uniform field derived type + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + REAL(ReKi), INTENT(IN ) :: Position(3) !< XYZ Position at which to find velocity (operating point) + REAL(ReKi), INTENT(IN ) :: CosPropDir !< cosine of InflowWind propagation direction + REAL(ReKi), INTENT(IN ) :: SinPropDir !< sine of InflowWind propagation direction + REAL(R8Ki), INTENT(INOUT) :: dYdu(3,6) !< Partial derivatives of output functions (Y) with respect to the inputs (u) + + TYPE(UniformField_Interp) :: op ! interpolated values of InterpParams + REAL(R8Ki) :: RotatePosition(3) !< rotated position + REAL(R8Ki) :: dVhdx ! temporary value to hold partial v_h partial X + REAL(R8Ki) :: dVhdy ! temporary value to hold partial v_h partial Y + REAL(R8Ki) :: dVhdz ! temporary value to hold partial v_h partial Z + REAL(R8Ki) :: tmp_du ! temporary value to hold calculations that are part of multiple components + REAL(R8Ki) :: tmp_dv ! temporary value to hold calculations that are part of multiple components + REAL(R8Ki) :: dVhdPD ! temporary value to hold partial v_h partial propagation direction + REAL(R8Ki) :: dVhdV ! temporary value to hold partial v_h partial V + REAL(R8Ki) :: Vh ! temporary value to hold v_h + REAL(R8Ki) :: dVhdVShr ! temporary value to hold partial v_h partial VShr + REAL(R8Ki) :: zr + + if ( Position(3) < 0.0_ReKi .or. EqualRealNos(Position(3), 0.0_ReKi)) then + dYdu = 0.0_R8Ki + return + end if + + !------------------------------------------------------------------------------------------------- + !> 1. Interpolate uniform field to get values at operating point + !------------------------------------------------------------------------------------------------- + + op = UniformField_InterpLinear(UF, t) + + RotatePosition(1) = Position(1)*cosPropDir - Position(2)*sinPropDir + RotatePosition(2) = Position(1)*sinPropDir + Position(2)*cosPropDir + RotatePosition(3) = Position(3) + + !------------------------------------------------------------------------------------------------- + !> 2. Calculate \f$ \frac{\partial Y_{Output \, Equations}}{\partial u_{inputs}} = \begin{bmatrix} + !! \frac{\partial Vt_u}{\partial X} & \frac{\partial Vt_u}{\partial Y} & \frac{\partial Vt_u}{\partial Z} \\ + !! \frac{\partial Vt_v}{\partial X} & \frac{\partial Vt_v}{\partial Y} & \frac{\partial Vt_v}{\partial Z} \\ + !! \frac{\partial Vt_w}{\partial X} & \frac{\partial Vt_w}{\partial Y} & \frac{\partial Vt_w}{\partial Z} \\ + !! \end{bmatrix} \f$ + !------------------------------------------------------------------------------------------------- + + zr = RotatePosition(3)/UF%RefHeight + tmp_du = op%VelH * op%ShrH / UF%RefLength * CosPropDir + dVhdx = tmp_du * op%SinAngleH + dVhdy = tmp_du * op%CosAngleH + dVhdz = op%VelH * ( op%ShrV / UF%RefHeight * zr**(op%ShrV-1.0_R8Ki) + op%LinShrV/UF%RefLength) + + dVhdV = ( ( RotatePosition(3)/UF%RefHeight ) ** op%ShrV & ! power-law wind shear + + ( op%ShrH * ( RotatePosition(2) * op%CosAngleH + RotatePosition(1) * op%SinAngleH ) & ! horizontal linear shear + + op%LinShrV * ( RotatePosition(3) - UF%RefHeight ) )/UF%RefLength ) ! vertical linear shear + Vh = op%VelH * dVhdV + op%VelGust + + dVhdVShr = op%VelH * zr**op%ShrV * log(zr) + dVhdPD = op%VelH * op%ShrH / UF%RefLength * ( RotatePosition(1) * op%CosAngleH - RotatePosition(2) * op%SinAngleH ) + + tmp_du = CosPropDir*op%CosAngleH - SinPropDir*op%SinAngleH + tmp_dv = -SinPropDir*op%CosAngleH - CosPropDir*op%SinAngleH + + !> \f$ \frac{\partial Vt_u}{\partial X} = \left[\cos(PropagationDir)\cos(Delta) - \sin(PropagationDir)\sin(Delta) \right] + !! V \, \frac{H_{LinShr}}{RefWid} \, \sin(Delta) \cos(PropagationDir) \f$ + dYdu(1,1) = tmp_du*dVhdx + !> \f$ \frac{\partial Vt_v}{\partial X} = \left[-\sin(PropagationDir)\cos(Delta) - \cos(PropagationDir)\sin(Delta) \right] + !! V \, \frac{H_{LinShr}}{RefWid} \, \sin(Delta) \cos(PropagationDir) \f$ + dYdu(2,1) = tmp_dv*dVhdx + !> \f$ \frac{\partial Vt_w}{\partial X} = 0 \f$ + dYdu(3,1) = 0.0_R8Ki + + !> \f$ \frac{\partial Vt_u}{\partial Y} = \left[\cos(PropagationDir)\cos(Delta) - \sin(PropagationDir)\sin(Delta) \right] + !! V \, \frac{H_{LinShr}}{RefWid} \, \cos(Delta) \cos(PropagationDir) \f$ + dYdu(1,2) = tmp_du*dVhdy + !> \f$ \frac{\partial Vt_v}{\partial Y} = \left[-\sin(PropagationDir)\cos(Delta) - \cos(PropagationDir)\sin(Delta) \right] + !! V \, \frac{H_{LinShr}}{RefWid} \, \cos(Delta) \cos(PropagationDir) \f$ + dYdu(2,2) = tmp_dv*dVhdy + !> \f$ \frac{\partial Vt_w}{\partial Y} = 0 \f$ + dYdu(3,2) = 0.0_R8Ki + + !> \f$ \frac{\partial Vt_u}{\partial Z} = \left[\cos(PropagationDir)\cos(Delta) - \sin(PropagationDir)\sin(Delta) \right] + !! V \, \left[ \frac{V_{shr}}{Z_{ref}} \left( \frac{Z}{Z_{ref}} \right) ^ {V_{shr}-1} + \frac{V_{LinShr}}{RefWid} \right] \f$ + dYdu(1,3) = tmp_du*dVhdz + !> \f$ \frac{\partial Vt_v}{\partial Z} = \left[-\sin(PropagationDir)\cos(Delta) - \cos(PropagationDir)\sin(Delta) \right] + !! V \, \left[ \frac{V_{shr}}{Z_{ref}} \left( \frac{Z}{Z_{ref}} \right) ^ {V_{shr}-1} + \frac{V_{LinShr}}{RefWid} \right] \f$ + dYdu(2,3) = tmp_dv*dVhdz + !> \f$ \frac{\partial Vt_w}{\partial Z} = 0 \f$ + dYdu(3,3) = 0.0_R8Ki + + ! \f$ \frac{\partial Vt_u}{\partial V} = \f$ + dYdu(1,4) = tmp_du*dVhdV + ! \f$ \frac{\partial Vt_v}{\partial V} = \f$ + dYdu(2,4) = tmp_dv*dVhdV + !> \f$ \frac{\partial Vt_w}{\partial V} = 0 \f$ + dYdu(3,4) = 0.0_R8Ki + + ! \f$ \frac{\partial Vt_u}{\partial VShr} = \f$ + dYdu(1,5) = tmp_du*dVhdVShr + ! \f$ \frac{\partial Vt_v}{\partial VShr} = \f$ + dYdu(2,5) = tmp_dv*dVhdVShr + !> \f$ \frac{\partial Vt_w}{\partial VShr} = 0 \f$ + dYdu(3,5) = 0.0_R8Ki + + ! \f$ \frac{\partial Vt_u}{\partial PropDir} = \f$ + dYdu(1,6) = tmp_dv*Vh + tmp_du*dVhdPD + ! \f$ \frac{\partial Vt_v}{\partial PropDir} = \f$ + dYdu(2,6) = -tmp_du*Vh + tmp_dv*dVhdPD + !> \f$ \frac{\partial Vt_w}{\partial PropDir} = 0 \f$ + dYdu(3,6) = 0.0_R8Ki + +END SUBROUTINE IfW_UniformWind_JacobianPInput !---------------------------------------------------------------------------------------------------------------------------------- !> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions !! with respect to the continuous states (x). The partial derivatives dY/dx, dX/dx, dXd/dx, and dZ/dx are returned. @@ -1684,8 +1429,8 @@ SUBROUTINE InflowWind_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMs u_op((index+1):(index+3)) = EulerExtract(u%HubOrientation) index = index + 3 - call IfW_UniformWind_GetOP( t, p%UniformWind, m%UniformWind, u_op(index+1:index+2) ) - u_op(index + 3) = p%PropagationDir + call IfW_UniformWind_GetOP( p%FlowField%Uniform, t, p%FlowField%VelInterpCubic, u_op(index+1:index+2) ) + u_op(index + 3) = p%FlowField%PropagationDir END IF @@ -1732,252 +1477,5 @@ SUBROUTINE InflowWind_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMs END IF END SUBROUTINE InflowWind_GetOP -!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - -!==================================================================================================== -SUBROUTINE InflowWind_Convert2HAWC( FileRootName, p, m, ErrStat, ErrMsg ) - - USE IfW_FFWind_Base - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="InflowWind_Convert2HAWC" - - ! Subroutine arguments - - TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - TYPE(IfW_FFWind_ParameterType) :: p_ff !< FF Parameters - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - - - ! Compute the wind velocities by stepping through all the data points and calling the appropriate GetWindSpeed routine - SELECT CASE ( p%WindType ) - - CASE (Steady_WindNumber, Uniform_WindNumber) - - CALL Uniform_to_FFWind(p%UniformWind, m%UniformWind, p_ff, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - IF (ErrStat < AbortErrLev) THEN - CALL ConvertFFWind_to_HAWC2(FileRootName, p_ff, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - END IF - - CALL IfW_FFWind_DestroyParam(p_ff,ErrStat2,ErrMsg2) - - CASE (TSFF_WindNumber) - - CALL ConvertFFWind_to_HAWC2(FileRootName, p%TSFFWind%FF, ErrStat, ErrMsg) - - CASE (BladedFF_WindNumber) - - CALL ConvertFFWind_to_HAWC2(FileRootName, p%BladedFFWind%FF, ErrStat, ErrMsg) - - CASE ( HAWC_WindNumber ) - - CALL ConvertFFWind_to_HAWC2(FileRootName, p%HAWCWind%FF, ErrStat, ErrMsg) - - CASE DEFAULT ! User_WindNumber - - ErrStat = ErrID_Warn - ErrMsg = 'Wind type '//TRIM(Num2LStr(p%WindType))//' cannot be converted to HAWC format.' - - END SELECT - -END SUBROUTINE InflowWind_Convert2HAWC - -!==================================================================================================== -SUBROUTINE InflowWind_Convert2Bladed( FileRootName, p, m, ErrStat, ErrMsg ) - - USE IfW_FFWind_Base - IMPLICIT NONE - CHARACTER(*), PARAMETER :: RoutineName="InflowWind_Convert2Bladed" - - ! Subroutine arguments - - TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - ! Local variables - TYPE(IfW_FFWind_ParameterType) :: p_ff !< FF Parameters - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - - ErrStat = ErrID_None - ErrMsg = "" - - ! Local variables - - ! Compute the wind velocities by stepping through all the data points and calling the appropriate GetWindSpeed routine - SELECT CASE ( p%WindType ) - - CASE (Steady_WindNumber, Uniform_WindNumber) - - CALL Uniform_to_FFWind(p%UniformWind, m%UniformWind, p_ff, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - IF (ErrStat < AbortErrLev) THEN - CALL ConvertFFWind_to_Bladed(FileRootName, p_ff, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - END IF - - CALL IfW_FFWind_DestroyParam(p_ff,ErrStat2,ErrMsg2) - - CASE (TSFF_WindNumber) - - CALL ConvertFFWind_to_Bladed(FileRootName, p%TSFFWind%FF, ErrStat, ErrMsg) - - CASE (BladedFF_WindNumber) - - CALL ConvertFFWind_to_Bladed(FileRootName, p%BladedFFWind%FF, ErrStat, ErrMsg) - - CASE ( HAWC_WindNumber ) - - CALL ConvertFFWind_to_Bladed(FileRootName, p%HAWCWind%FF, ErrStat, ErrMsg) - - CASE DEFAULT ! User_WindNumber - - ErrStat = ErrID_Warn - ErrMsg = 'Wind type '//TRIM(Num2LStr(p%WindType))//' cannot be converted to Bladed format.' - - END SELECT - -END SUBROUTINE InflowWind_Convert2Bladed - -!==================================================================================================== -SUBROUTINE InflowWind_Convert2Uniform( FileRootName, p, m, ErrStat, ErrMsg ) - - USE IfW_FFWind_Base - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="InflowWind_Convert2Uniform" - - ! Subroutine arguments - - TYPE(InflowWind_ParameterType), INTENT(INOUT) :: p !< Parameters - TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - - ErrStat = ErrID_None - ErrMsg = "" - - - ! Compute the wind velocities by stepping through all the data points and calling the appropriate GetWindSpeed routine - SELECT CASE ( p%WindType ) - - CASE (Steady_WindNumber, Uniform_WindNumber) - ! no need to convert anything here - - CASE (TSFF_WindNumber) - CALL FFWind_to_Uniform(p%UniformWind, m%UniformWind, p%TSFFWind%FF, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - CASE (BladedFF_WindNumber) - CALL FFWind_to_Uniform(p%UniformWind, m%UniformWind, p%BladedFFWind%FF, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - CASE ( HAWC_WindNumber ) - - CALL FFWind_to_Uniform(p%UniformWind, m%UniformWind, p%HAWCWind%FF, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - CASE DEFAULT ! User_WindNumber - - ErrStat = ErrID_Warn - ErrMsg = RoutineName//': Wind type '//TRIM(Num2LStr(p%WindType))//' cannot be converted to UniformWind format.' - RETURN - - END SELECT - IF (ErrStat >= AbortErrLev) RETURN - - CALL WrUniformWind(FileRootName, p%UniformWind, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - -END SUBROUTINE InflowWind_Convert2Uniform - -!==================================================================================================== -SUBROUTINE InflowWind_Convert2VTK( FileRootName, p, m, ErrStat, ErrMsg ) - - USE IfW_FFWind_Base - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="InflowWind_Convert2VTK" - - ! Subroutine arguments - - TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc/optimization variables - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - ! Local variables - TYPE(IfW_FFWind_ParameterType) :: p_ff !< FF Parameters - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - - ErrStat = ErrID_None - ErrMsg = "" - - ! Local variables - - ! Compute the wind velocities by stepping through all the data points and calling the appropriate GetWindSpeed routine - SELECT CASE ( p%WindType ) - - CASE (Steady_WindNumber, Uniform_WindNumber) - - CALL Uniform_to_FFWind(p%UniformWind, m%UniformWind, p_ff, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - - IF (ErrStat < AbortErrLev) THEN - CALL ConvertFFWind_toVTK(FileRootName, p_ff, ErrStat2, ErrMsg2) - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - END IF - - CALL IfW_FFWind_DestroyParam(p_ff,ErrStat2,ErrMsg2) - - CASE (TSFF_WindNumber) - - CALL ConvertFFWind_toVTK(FileRootName, p%TSFFWind%FF, ErrStat, ErrMsg) - - CASE (BladedFF_WindNumber) - - CALL ConvertFFWind_toVTK(FileRootName, p%BladedFFWind%FF, ErrStat, ErrMsg) - - CASE ( HAWC_WindNumber ) - - CALL ConvertFFWind_toVTK(FileRootName, p%HAWCWind%FF, ErrStat, ErrMsg) - - CASE DEFAULT ! User_WindNumber - - ErrStat = ErrID_Warn - ErrMsg = 'Wind type '//TRIM(Num2LStr(p%WindType))//' cannot be converted to VTK format.' - - END SELECT - -END SUBROUTINE InflowWind_Convert2VTK -!==================================================================================================== END MODULE InflowWind diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 3f0b89c1af..b176cb8488 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -8,13 +8,7 @@ ################################################################################################################################### usefrom IfW_FlowField.txt -usefrom IfW_UniformWind.txt -usefrom IfW_TSFFWind.txt -usefrom IfW_FFWind_Base.txt -usefrom IfW_BladedFFWind.txt -usefrom IfW_HAWCWind.txt -usefrom IfW_UserWind.txt -usefrom IfW_4Dext.txt +usefrom InflowWind_IO.txt usefrom Lidar.txt include Registry_NWTC_Library.txt @@ -29,34 +23,11 @@ param ^ - IntKi HAWC_WindNu param ^ - IntKi User_WindNumber - 6 - "User defined wind." - param ^ - IntKi BladedFF_Shr_WindNumber - 7 - "Native Bladed binary full-field file." - param ^ - IntKi FDext_WindNumber - 8 - "4D wind from external souce (i.e., FAST.Farm)." - -param ^ - IntKi Highest_WindNumber - 8 - "Highest wind number supported." - +param ^ - IntKi Point_WindNumber - 9 - "4D wind from external souce (i.e., FAST.Farm)." - +param ^ - IntKi Highest_WindNumber - 9 - "Highest wind number supported." - param ^ - IntKi IfW_NumPtsAvg - 144 - "Number of points averaged for rotor-average wind speed" - -######################### -# ..... WindFile metadata ........................................................................................................ -# This is metadata about the windfile that is retrieved when InflowWind is initialized -# ................................................................................................................................ -typedef InflowWind/InflowWind WindFileMetaData CHARACTER(1024) FileName - - - "Name of the windfile retrieved" - -typedef ^ ^ IntKi WindType - 0 - "Type of the windfile" - -typedef ^ ^ ReKi RefHt - - - "Reference height given in file" meters -typedef ^ ^ Logical RefHt_Set - - - "Reference height was given in file" - -typedef ^ ^ DbKi DT - - - "TimeStep of the wind file -- zero value for none" seconds -typedef ^ ^ IntKi NumTSteps - - - "Number of timesteps in the time range of wind file" - -typedef ^ ^ Logical ConstantDT - - - "Timesteps are the same throughout file" - -typedef ^ ^ ReKi TRange {2} - - "Time range of the wind file" seconds -typedef ^ ^ Logical TRange_Limited - - - "TRange limits strictly enforced" - -typedef ^ ^ ReKi YRange {2} - - "Range in y direction" meters -typedef ^ ^ Logical YRange_Limited - - - "YRange limits strictly enforced" - -typedef ^ ^ ReKi ZRange {2} - - "Range in z direction" meters -typedef ^ ^ Logical ZRange_Limited - - - "ZRange limits strictly enforced" - -typedef ^ ^ IntKi BinaryFormat - - - "Binary format identifier" - -typedef ^ ^ Logical IsBinary - - - "Windfile is a binary file" - -typedef ^ ^ ReKi TI {3} - - "Turbulence intensity (U,V,W)" - -typedef ^ ^ Logical TI_listed - - - "Turbulence intesity given in file" - -typedef ^ ^ ReKi MWS - - - "Approximate mean wind speed" - - - ######################### # ..... Input file data ........................................................................................................... # This is data defined in the Input File for this module (or could otherwise be passed in) @@ -98,7 +69,7 @@ typedef ^ ^ IntKi SensorType typedef ^ ^ IntKi NumPulseGate - - - "the number of range gates to return wind speeds at" - typedef ^ ^ ReKi RotorApexOffsetPos 3 - - "position of the lidar unit relative to the rotor apex of rotation" m typedef ^ ^ LOGICAL LidRadialVel - - - "TRUE => return radial component, FALSE => return 'x' direction estimate" - -typedef ^ ^ IfW_FFWind_InitInputType FF - - - "scaling data" - +typedef ^ ^ Grid3D_InitInputType FF - - - "scaling data" - @@ -114,8 +85,8 @@ typedef ^ ^ FileInfoType PassedFileD typedef ^ ^ LOGICAL WindType2UseInputFile - .TRUE. - "Flag for toggling file based IO in wind type 2." - typedef ^ ^ FileInfoType WindType2Data - - - "Optional slot for wind type 2 data if file IO is not used." - typedef ^ ^ LOGICAL OutputAccel - .FALSE. - "Flag to output wind acceleration" - -typedef ^ ^ Lidar_InitInputType lidar - - - "InitInput for lidar data" - -typedef ^ ^ IfW_4Dext_InitInputType FDext - - - "InitInput for 4D external wind data" - +typedef ^ ^ Lidar_InitInputType lidar - - - "InitInput for lidar data" - +typedef ^ ^ Grid4D_InitInputType FDext - - - "InitInput for 4D external wind data" - typedef ^ ^ ReKi RadAvg - - - "Radius (from hub) used for averaging wind speed" - @@ -123,7 +94,7 @@ typedef ^ ^ ReKi RadAvg typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr : - - "Names of output-to-file channels" - typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt : - - "Units of output-to-file channels" - typedef ^ ^ ProgDesc Ver - - - "Version information of InflowWind module" - -typedef ^ ^ WindFileMetaData WindFileInfo - - - "Meta data from the wind file" - +typedef ^ ^ WindFileDat WindFileInfo - - - "Meta data from the wind file" - typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - typedef ^ InitOutputType CHARACTER(LinChanLen) LinNames_u {:} - - "Names of the inputs used in linearization" - typedef ^ InitOutputType LOGICAL RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - @@ -135,35 +106,21 @@ typedef ^ InitOutputType LOGICAL IsLoad # ..... Parameters ................................................................................................................ # Define parameters here: # Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType CHARACTER(1024) RootFileName - - - "Root of the InflowWind input filename" - -typedef ^ ^ LOGICAL CTTS_Flag - .FALSE. - "determines if coherent turbulence is used" - -typedef ^ ^ LOGICAL RotateWindBox - .FALSE. - "determines if wind will be rotated" - +typedef ^ ParameterType FlowFieldType FlowField - - - "Parameters from Full-Field" - +typedef ^ ^ CHARACTER(1024) RootFileName - - - "Root of the InflowWind input filename" - +typedef ^ ^ IntKi WindType - 0 - "Type of wind -- set to Undef_Wind initially" - typedef ^ ^ DbKi DT - - - "Time step for cont. state integration & disc. state update" seconds -typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians -typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" radians - -typedef ^ ^ ReKi RotToWind {3}{3} - - "Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X')" - -typedef ^ ^ ReKi RotFromWind {3}{3} - - "Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind)" - typedef ^ ^ ReKi WindViXYZprime :: - - "List of XYZ coordinates for velocity measurements, translated to the wind coordinate system (prime coordinates). This equals MATMUL( RotToWind, ParamData%WindViXYZ )" meters +typedef ^ ^ ReKi WindViXYZ :: - - "List of XYZ coordinates for wind velocity measurements, 3xNWindVel" meters -typedef ^ ^ IntKi WindType - 0 - "Type of wind -- set to Undef_Wind initially" - +typedef ^ ^ ReKi PositionAvg :: - - "(non-rotated) positions of points used for averaging wind speed" meters typedef ^ ^ ReKi ReferenceHeight - - - "Height of the wind turbine" meters typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters typedef ^ ^ IntKi NWindVel - - - "Number of points in the wind velocity list" - -typedef ^ ^ ReKi WindViXYZ :: - - "List of XYZ coordinates for wind velocity measurements, 3xNWindVel" meters -typedef ^ ^ FlowFieldType FlowField - - - "Parameters from Full-Field" - -typedef ^ ^ IfW_UniformWind_ParameterType UniformWind - - - "Parameters from UniformWind" - -typedef ^ ^ IfW_TSFFWind_ParameterType TSFFWind - - - "Parameters from TSFFWind -- TurbSim full-field format" - -typedef ^ ^ IfW_BladedFFWind_ParameterType BladedFFWind - - - "Parameters from BladedFFWind -- Bladed-style full-field format" - -typedef ^ ^ IfW_HAWCWind_ParameterType HAWCWind - - - "Parameters from HAWCWind" - -typedef ^ ^ IfW_UserWind_ParameterType UserWind - - - "Parameters from UserWind" - -typedef ^ ^ IfW_4Dext_ParameterType FDext - - - "Parameters from FDext" - -#typedef ^ ^ IfW_CTWind_ParameterType CTWind - - - "Parameters from CTWind" - typedef ^ ^ IntKi NumOuts - 0 - "Number of parameters in the output list (number of outputs requested)" - typedef ^ ^ OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - typedef ^ ^ IntKi OutParamLinIndx {:}{:} - - "Index into WriteOutput for WindViXYZ in linearization analysis" - -typedef ^ ^ lidar_ParameterType lidar - - - "Lidar parameter data" - -typedef ^ ^ ReKi PositionAvg :: - - "(non-rotated) positions of points used for averaging wind speed" meters +typedef ^ ^ lidar_ParameterType lidar - - - "Lidar parameter data" - # ..... Inputs .................................................................................................................... @@ -182,7 +139,6 @@ typedef ^ OutputType ReKi WriteOutput typedef ^ ^ ReKi DiskVel {3} - - "Vector holding the U,V,W average velocity of the disk" meters/sec typedef ^ ^ ReKi HubVel {3} - - "Vector holding the U,V,W velocity at the hub" meters/sec typedef ^ ^ lidar_OutputType lidar - - - "Lidar data" - -#typedef ^ ^ IfW_UniformWind_OutputType UniformWind - - - "uniform/steady wind operating point" # ..... States not used by this module ................................................................................................................... typedef ^ ContinuousStateType ReKi DummyContState - - - "Remove this variable if you have continuous states" - @@ -194,14 +150,7 @@ typedef ^ OtherStateType ReKi DummyOtherS # ..... Misc/Optimization variables................................................................................................. # Define any data that are used only for efficiency purposes (these variables are not associated with time): # e.g. indices for searching in an array, large arrays that are local variables in any routine called multiple times, etc. -typedef ^ MiscVarType IntKi TimeIndex - 0 - "An Index into the TData array" - -typedef ^ ^ IfW_UniformWind_MiscVarType UniformWind - - - "MiscVars from UniformWind" - -typedef ^ ^ IfW_TSFFWind_MiscVarType TSFFWind - - - "MiscVars from TSFFWind" - -typedef ^ ^ IfW_HAWCWind_MiscVarType HAWCWind - - - "MiscVars from HAWCWind" - -typedef ^ ^ IfW_BladedFFWind_MiscVarType BladedFFWind - - - "MiscVars from BladedFFWind" - -typedef ^ ^ IfW_UserWind_MiscVarType UserWind - - - "MiscVars from UserWind" - -typedef ^ ^ IfW_4Dext_MiscVarType FDext - - - "MiscVars from FDext" - -typedef ^ ^ ReKi AllOuts : - - "An array holding the value of all of the calculated (not only selected) output channels" "see OutListParameters.xlsx spreadsheet" +typedef ^ MiscVarType ReKi AllOuts : - - "An array holding the value of all of the calculated (not only selected) output channels" "see OutListParameters.xlsx spreadsheet" typedef ^ ^ ReKi WindViUVW :: - - "List of UVW velocities for wind velocity measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ" meters/second typedef ^ ^ ReKi WindAiUVW :: - - "List of UVW accelerations for wind acceleration measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ" m/s^2 typedef ^ MiscVarType InflowWind_InputType u_Avg - - - "inputs for computing rotor-averaged values" - diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index 33725b839c..0e8109dc77 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -271,7 +271,7 @@ PROGRAM InflowWind_Driver ! Create velocity output file name from points input file name ! Display that file will be created, output message if it will be overwritten CALL GetRoot( Settings%PointsFileName, Settings%PointsVelOutput%Name ) - Settings%PointsVelOutput%Name = TRIM(Settings%PointsVelOutput%Name)//'.dat' + Settings%PointsVelOutput%Name = TRIM(Settings%PointsVelOutput%Name)//'.Velocity.dat' CALL WrScr(NewLine//"Results output to '"//TRIM(Settings%PointsVelOutput%Name)//"'.") INQUIRE( file=TRIM(Settings%PointsVelOutput%Name), exist=TempFileExist ) IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsVelOutput%Name)) @@ -279,18 +279,12 @@ PROGRAM InflowWind_Driver ! If wind accelerations were requested, create/open file, print overwrite warning of applicable IF (SettingsFlags%OutputAccel) then CALL GetRoot( Settings%PointsFileName, Settings%PointsAccOutput%Name ) - Settings%PointsAccOutput%Name = TRIM(Settings%PointsAccOutput%Name)//'.Acc.dat' + Settings%PointsAccOutput%Name = TRIM(Settings%PointsAccOutput%Name)//'.Acceleration.dat' CALL WrScr(NewLine//"Results output to '"//TRIM(Settings%PointsAccOutput%Name)//"'.") INQUIRE( file=TRIM(Settings%PointsAccOutput%Name), exist=TempFileExist ) IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsAccOutput%Name)) END IF - CALL GetRoot( Settings%PointsFileName, Settings%PointsRefOutput%Name ) - Settings%PointsRefOutput%Name = TRIM(Settings%PointsRefOutput%Name)//'.Ref.dat' - CALL WrScr(NewLine//"Results output to '"//TRIM(Settings%PointsRefOutput%Name)//"'.") - INQUIRE( file=TRIM(Settings%PointsRefOutput%Name), exist=TempFileExist ) - IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsRefOutput%Name)) - ENDIF @@ -453,28 +447,24 @@ PROGRAM InflowWind_Driver ! Convert InflowWind file to HAWC format IF (SettingsFlags%WrHAWC) THEN - - CALL InflowWind_Convert2HAWC( InflowWind_InitInp%RootName, InflowWind_p, InflowWind_MiscVars, ErrStat, ErrMsg ) - + CALL IfW_WriteHAWC( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN CALL DriverCleanup() CALL ProgAbort( ErrMsg ) ELSEIF ( IfWDriver_Verbose >= 7_IntKi ) THEN - CALL WrScr(NewLine//' InflowWind_Convert2HAWC returned: ErrStat: '//TRIM(Num2LStr(ErrStat))) + CALL WrScr(NewLine//' IfW_WriteHAWC returned: ErrStat: '//TRIM(Num2LStr(ErrStat))) END IF - ELSE - IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'InflowWind_Convert2HAWC CALL returned without errors.'//NewLine) + ELSE IF ( IfWDriver_Verbose >= 5_IntKi ) THEN + CALL WrScr(NewLine//'IfW_WriteHAWC CALL returned without errors.'//NewLine) END IF - - END IF ! Write HAWC2 files + END IF ! Convert InflowWind file to Native Bladed format IF (SettingsFlags%WrBladed) THEN - CALL InflowWind_Convert2Bladed( InflowWind_InitInp%RootName, InflowWind_p, InflowWind_MiscVars, ErrStat, ErrMsg ) - + CALL IfW_WriteBladed( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN @@ -483,42 +473,40 @@ PROGRAM InflowWind_Driver ELSEIF ( IfWDriver_Verbose >= 7_IntKi ) THEN CALL WrScr(NewLine//' InflowWind_Convert2Bladed returned: ErrStat: '//TRIM(Num2LStr(ErrStat))) END IF - ELSE - IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'InflowWind_Convert2Bladed CALL returned without errors.'//NewLine) + ELSE IF ( IfWDriver_Verbose >= 5_IntKi ) THEN + CALL WrScr(NewLine//'InflowWind_Convert2Bladed CALL returned without errors.'//NewLine) END IF END IF IF (SettingsFlags%WrVTK) THEN - CALL InflowWind_Convert2VTK( InflowWind_InitInp%RootName, InflowWind_p, InflowWind_MiscVars, ErrStat, ErrMsg ) - + CALL IfW_WriteVTK( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN CALL DriverCleanup() CALL ProgAbort( ErrMsg ) ELSEIF ( IfWDriver_Verbose >= 7_IntKi ) THEN - CALL WrScr(NewLine//' InflowWind_Convert2VTK returned: ErrStat: '//TRIM(Num2LStr(ErrStat))) + CALL WrScr(NewLine//' IfW_WriteVTK returned: ErrStat: '//TRIM(Num2LStr(ErrStat))) END IF - ELSE - IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'InflowWind_Convert2VTK CALL returned without errors.'//NewLine) + ELSE IF ( IfWDriver_Verbose >= 5_IntKi ) THEN + CALL WrScr(NewLine//'IfW_WriteVTK CALL returned without errors.'//NewLine) END IF END IF IF (SettingsFlags%WrUniform) THEN - CALL InflowWind_Convert2Uniform( InflowWind_InitInp%RootName, InflowWind_p, InflowWind_MiscVars, ErrStat, ErrMsg ) - + CALL IfW_WriteUniform( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN CALL DriverCleanup() CALL ProgAbort( ErrMsg ) ELSEIF ( IfWDriver_Verbose >= 7_IntKi ) THEN - CALL WrScr(NewLine//' InflowWind_Convert2Uniform returned: ErrStat: '//TRIM(Num2LStr(ErrStat))) + CALL WrScr(NewLine//' IfW_WriteUniform returned: ErrStat: '//TRIM(Num2LStr(ErrStat))) END IF - ELSE - IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'InflowWind_Convert2Uniform CALL returned without errors.'//NewLine) + ELSE IF ( IfWDriver_Verbose >= 5_IntKi ) THEN + CALL WrScr(NewLine//'IfW_WriteUniform CALL returned without errors.'//NewLine) END IF END IF @@ -676,14 +664,6 @@ PROGRAM InflowWind_Driver ENDIF END IF - ! Now create the reference velocity output file. Write header information - CALL PointData_OutputWrite( Settings%PointsRefOutput, Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%VelocityUVW, TimeNow, .true., ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) THEN - CALL DriverCleanup() - CALL ProgAbort( 'Error creating point data velocity output file: '//trim(Settings%PointsRefOutput%Name) ) - ENDIF - ENDIF ! FFT setup @@ -729,7 +709,7 @@ PROGRAM InflowWind_Driver ! Report the rotation of the coordinates. IF ( IfWDriver_Verbose >= 10_IntKi .and. InflowWind_p%NumOuts > 0 ) THEN CALL WrScr(NewLine//NewLine//' Rotation of coordinates to prime (wind file) coordinates by rotating '// & - TRIM(Num2LStr(R2D*InflowWind_p%PropagationDir))// & + TRIM(Num2LStr(R2D*InflowWind_p%FlowField%PropagationDir))// & ' degrees (meteorological wind direction change) ...'//NewLine) if (InflowWind_p%NWindVel > 0_IntKi) then CALL WrScr(' ------ WindViXYZ --------- ----- WindViXYZprime -----') @@ -799,7 +779,6 @@ PROGRAM InflowWind_Driver IF ( SettingsFlags%PointsFile ) THEN ! Calculate velocity/acceleration at points - InflowWind_p%FlowField%Enabled = .true. CALL InflowWind_CalcOutput( TimeNow, InflowWind_u2, InflowWind_p, & InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & InflowWind_y2, InflowWind_MiscVars, ErrStat, ErrMsg) @@ -829,18 +808,6 @@ PROGRAM InflowWind_Driver CALL ProgAbort( ErrMsg ) END IF END IF - - ! Calculate reference velocity and output - InflowWind_p%FlowField%Enabled = .false. - CALL InflowWind_CalcOutput( TimeNow, InflowWind_u2, InflowWind_p, & - InflowWind_x, InflowWind_xd, InflowWind_z, InflowWind_OtherState, & - InflowWind_y2, InflowWind_MiscVars, ErrStat, ErrMsg) - CALL PointData_OutputWrite( Settings%PointsRefOutput, Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%VelocityUVW, TimeNow, .true., ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL DriverCleanup() - CALL ProgAbort( ErrMsg ) - END IF END IF @@ -991,7 +958,6 @@ SUBROUTINE DriverCleanup() if (Settings%WindGridOutput%Unit > -1_IntKi ) CLOSE( Settings%WindGridOutput%Unit ) if (Settings%PointsVelOutput%Unit > -1_IntKi ) CLOSE( Settings%PointsVelOutput%Unit ) if (Settings%PointsAccOutput%Unit > -1_IntKi ) CLOSE( Settings%PointsAccOutput%Unit ) - if (Settings%PointsRefOutput%Unit > -1_IntKi ) CLOSE( Settings%PointsRefOutput%Unit ) if (Settings%FFTOutput%Unit > -1_IntKi ) CLOSE( Settings%FFTOutput%Unit ) ! Find out how long this actually took diff --git a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 index 34b6639794..926c0cac9f 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 @@ -27,6 +27,8 @@ MODULE InflowWind_Driver_Subs USE NWTC_Library USE InflowWind_Driver_Types + USE InflowWind_IO + USE IfW_FlowField IMPLICIT NONE @@ -2417,6 +2419,191 @@ SUBROUTINE PointData_OutputWrite (OutFile, Settings, GridXYZ, GridDat, TIME, IsV END SUBROUTINE PointData_OutputWrite +subroutine IfW_WriteUniform(FF, FileRootName, ErrStat, ErrMsg) + + type(FlowFieldType), intent(in) :: FF !< Parameters + character(*), intent(in) :: FileRootName !< RootName for output files + integer(IntKi), intent(out) :: ErrStat !< Error status of the operation + character(*), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + character(*), parameter :: RoutineName = "IfW_WriteUniform" + type(UniformFieldType) :: UF + integer(IntKi) :: unit + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + ! Get new unit for writing file + call GetNewUnit(unit, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Switch based on field type + select case (FF%FieldType) + + case (Uniform_FieldType) + + call Uniform_WriteHH(FF%Uniform, FileRootName, unit, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + + case (Grid3D_FieldType) + + call Grid3D_to_Uniform(FF%Grid3D, UF, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat < AbortErrLev) then + call Uniform_WriteHH(UF, FileRootName, unit, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + case default + + ErrStat = ErrID_Warn + ErrMsg = RoutineName//': Field type '//TRIM(Num2LStr(FF%FieldType))// & + ' cannot be converted to UniformWind format.' + end select + +end subroutine IfW_WriteUniform + +subroutine IfW_WriteHAWC(FF, FileRootName, ErrStat, ErrMsg) + + type(FlowFieldType), intent(in) :: FF !< Parameters + character(*), intent(in) :: FileRootName !< RootName for output files + integer(IntKi), intent(out) :: ErrStat !< Error status of the operation + character(*), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + character(*), parameter :: RoutineName = "IfW_Convert2HAWC" + type(Grid3DFieldType) :: G3D + integer(IntKi) :: unit + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ! Get new unit for writing file + call GetNewUnit(unit, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Switch based on field type + select case (FF%FieldType) + + case (Uniform_FieldType) + + call Uniform_to_Grid3D(FF%Uniform, FF%VelInterpCubic, G3D, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat < AbortErrLev) then + call Grid3D_WriteHAWC(G3D, FileRootName, unit, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + case (Grid3D_FieldType) + + call Grid3D_WriteHAWC(FF%Grid3D, FileRootName, unit, ErrStat, ErrMsg) + + case default + + ErrStat = ErrID_Warn + ErrMsg = RoutineName//': Field Type '//TRIM(Num2LStr(FF%FieldType))// & + ' cannot be converted to HAWC format.' + + end select + +end subroutine + +subroutine IfW_WriteBladed(FF, FileRootName, ErrStat, ErrMsg) + + type(FlowFieldType), intent(in) :: FF !< Parameters + character(*), intent(in) :: FileRootName !< RootName for output files + integer(IntKi), intent(out) :: ErrStat !< Error status of the operation + character(*), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + character(*), parameter :: RoutineName = "IfW_WriteBladed" + type(Grid3DFieldType) :: G3D + integer(IntKi) :: unit + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + ! Get new unit for writing file + call GetNewUnit(unit, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Switch based on field type + select case (FF%FieldType) + + case (Uniform_FieldType) + + call Uniform_to_Grid3D(FF%Uniform, FF%VelInterpCubic, G3D, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat < AbortErrLev) then + call Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + case (Grid3D_FieldType) + + call Grid3D_WriteBladed(FF%Grid3D, FileRootName, unit, ErrStat, ErrMsg) + + case default + + ErrStat = ErrID_Warn + ErrMsg = RoutineName//': Field type '//TRIM(Num2LStr(FF%FieldType))// & + ' cannot be converted to Bladed format.' + + end select + +end subroutine + + +subroutine IfW_WriteVTK(FF, FileRootName, ErrStat, ErrMsg) + + type(FlowFieldType), intent(in) :: FF !< Parameters + character(*), intent(in) :: FileRootName !< RootName for output files + integer(IntKi), intent(out) :: ErrStat !< Error status of the operation + character(*), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + character(*), parameter :: RoutineName = "IfW_WriteVTK" + type(Grid3DFieldType) :: G3D + integer(IntKi) :: unit + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + ! Get new unit for writing file + call GetNewUnit(unit, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Switch based on field type + select case (FF%FieldType) + + case (Uniform_FieldType) + + call Uniform_to_Grid3D(FF%Uniform, FF%VelInterpCubic, G3D, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat < AbortErrLev) then + call Grid3D_WriteVTK(G3D, FileRootName, unit, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end if + + case (Grid3D_FieldType) + + call Grid3D_WriteVTK(FF%Grid3D, FileRootName, unit, ErrStat, ErrMsg) + + case default + + ErrStat = ErrID_Warn + ErrMsg = RoutineName//': Field type '//TRIM(Num2LStr(FF%FieldType))// & + ' cannot be converted to VTK format.' + + end select + +end subroutine IfW_WriteVTK !> This routine exists only to support the development of the module. It will not be needed after the module is complete. diff --git a/modules/inflowwind/src/InflowWind_Driver_Types.f90 b/modules/inflowwind/src/InflowWind_Driver_Types.f90 index cd1128c9a6..82e8c840f0 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Types.f90 @@ -104,7 +104,6 @@ MODULE InflowWind_Driver_Types TYPE(OutputFile) :: FFTOutput TYPE(OutputFile) :: PointsVelOutput TYPE(OutputFile) :: PointsAccOutput - TYPE(OutputFile) :: PointsRefOutput END TYPE IfWDriver_Settings diff --git a/modules/inflowwind/src/FlowField_IO.f90 b/modules/inflowwind/src/InflowWind_IO.f90 similarity index 81% rename from modules/inflowwind/src/FlowField_IO.f90 rename to modules/inflowwind/src/InflowWind_IO.f90 index 27e42f3587..b6889630a9 100644 --- a/modules/inflowwind/src/FlowField_IO.f90 +++ b/modules/inflowwind/src/InflowWind_IO.f90 @@ -2,7 +2,7 @@ !! This module assumes that the origin, (0,0,0), is located at the tower centerline at ground level, !! and that all units are specified in the metric system (using meters and seconds). !! Data is shifted by half the grid width to account for turbine yaw (so that data in the X -!! direction actually starts at -1*p%FFYHWid meters). +!! direction actually starts at -1*p%YHWid meters). !********************************************************************************************************************************** ! LICENSING ! Copyright (C) 2022 National Renewable Energy Laboratory @@ -23,17 +23,19 @@ ! !********************************************************************************************************************************** -module FlowField_IO +module InflowWind_IO use NWTC_Library -use FlowField_IO_Types +use InflowWind_IO_Types use IfW_FlowField implicit none private -public :: FlowField_IO_Init +public :: IfW_SteadyWind_Init, IfW_UniformWind_Init, IfW_TurbSim_Init, IfW_Bladed_Init, & + IfW_HAWC_Init, IfW_User_Init, IfW_Grid4D_Init +public :: Uniform_WriteHH, Grid3D_WriteBladed, Grid3D_WriteHAWC, Grid3D_WriteVTK -type(ProgDesc), parameter :: FlowField_IO_Ver = ProgDesc('FlowField_IO', '', '') +type(ProgDesc), parameter :: InflowWind_IO_Ver = ProgDesc('InflowWind_IO', '', '') integer(IntKi), parameter :: ScaleMethod_None = 0, & !< no scaling ScaleMethod_Direct = 1, & !< direct scaling factors @@ -52,167 +54,8 @@ module FlowField_IO contains -!---------------------------------------------------------------------------------------------------- -!> A subroutine to initialize the UserWind module. This routine will initialize the module. -!---------------------------------------------------------------------------------------------------- -subroutine FlowField_IO_Init(InitInp, FF, InitOut, ErrStat, ErrMsg) - - type(FlowField_IO_InitInputType), intent(in) :: InitInp !< Input data for initialization - type(FlowFieldType), intent(out) :: FF !< Flow field - type(FlowField_IO_InitOutputType), intent(out) :: InitOut !< Misc variables for optimization (not copied in glue code) - integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered - character(*), intent(out) :: ErrMsg !< A message about the error. See NWTC_Library info for ErrID_* levels. - - character(*), parameter :: RoutineName = 'FlowField_IO_Init' - integer(IntKi) :: TmpErrStat ! Temp variable for the error status - character(ErrMsgLen) :: TmpErrMsg ! temporary error message - - ErrStat = ErrID_None - ErrMsg = "" - - !---------------------------------------------------------------------------- - ! Parameter initialization - !---------------------------------------------------------------------------- - - FF%PropagationDir = InitInp%PropagationDir*D2R - FF%VFlowAngle = InitInp%VFlowAngle*D2R - - ! Shift propagation direction so it is between -pi and pi - call MPi2Pi(FF%PropagationDir) - - !---------------------------------------------------------------------------- - ! Wind Type Initialization - !---------------------------------------------------------------------------- - - select case (InitInp%WindType) - case (1) ! Steady - FF%FieldType = Uniform_FieldType - call SteadyWind_ReadFile(InitInp%Steady, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) - - case (2) ! Uniform - FF%FieldType = Uniform_FieldType - call UniformWind_ReadFile(InitInp%Uniform, InitInp%SumFileUnit, FF%Uniform, InitOut%FileDat, TmpErrStat, TmpErrMsg) - - case (3) ! Binary TurbSim FF - FF%FieldType = Grid3D_FieldType - call TurbSim_Init(InitInp%TurbSim, InitInp%SumFileUnit, FF%Grid3D, InitOut%FileDat, TmpErrStat, TmpErrMsg) - - case (4) ! Binary Bladed-Style FF - FF%FieldType = Grid3D_FieldType - call Bladed_ReadFile(InitInp%Bladed, InitInp%SumFileUnit, InitOut%Bladed, FF%Grid3D, InitOut%FileDat, TmpErrStat, TmpErrMsg) - - case (5) ! HAWC - FF%FieldType = Grid3D_FieldType - call HAWC_Init(InitInp%HAWC, InitInp%SumFileUnit, FF%Grid3D, InitOut%FileDat, TmpErrStat, TmpErrMsg) - - case (6) ! User Defined - FF%FieldType = Grid3D_FieldType - TmpErrStat = ErrID_Fatal - TmpErrMsg = "User Wind is not implemented" - - case (7) ! Native Bladed FF - FF%FieldType = Grid3D_FieldType - call Bladed_ReadFile(InitInp%Bladed, InitInp%SumFileUnit, InitOut%Bladed, FF%Grid3D, InitOut%FileDat, TmpErrStat, TmpErrMsg) - - case (8) ! Grid - FF%FieldType = Grid4D_FieldType - TmpErrStat = ErrID_Fatal - TmpErrMsg = "Grid4D Wind is not implemented" - - case (9) ! External Point - FF%FieldType = Point_FieldType - TmpErrStat = ErrID_Fatal - TmpErrMsg = "Points Wind is not implemented" - - case default ! Others - TmpErrStat = ErrID_Fatal - TmpErrMsg = "Unknown wind type" - - end select - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return - - !---------------------------------------------------------------------------- - ! Field Type Initialization - !---------------------------------------------------------------------------- - - ! Reset flag indicating that acceleration field is valid - FF%AccFieldValid = .false. - - select case (FF%FieldType) - case (Uniform_FieldType) - - if (InitInp%OutputAccel .or. (InitInp%VelInterpCubic)) then - call UniformField_CalcAccel(FF%Uniform, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return - FF%AccFieldValid = .true. - end if - FF%VelInterpCubic = InitInp%VelInterpCubic - - case (Grid3D_FieldType) - if (InitInp%OutputAccel .or. (InitInp%VelInterpCubic)) then - call Grid3DField_CalcAccel(FF%Grid3D, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return - FF%AccFieldValid = .true. - end if - FF%VelInterpCubic = InitInp%VelInterpCubic - - case default - if (InitInp%OutputAccel) then - call SetErrStat(ErrID_Fatal, "Acceleration not implemented for field type", & - ErrStat, ErrMsg, RoutineName) - return - end if - if (InitInp%VelInterpCubic) then - call WrScr(' Cubic velocity interpolation not implemented for WindType '// & - num2LStr(InitInp%WindType)//', using linear interpolation') - FF%VelInterpCubic = .false. - end if - end select - - !---------------------------------------------------------------------------- - ! Setup the coordinate transforms for rotating the wind field. - !---------------------------------------------------------------------------- - - ! Create the rotation matrices - ! rotate from XYZ to X'Y'Z' (wind aligned along X) coordinates - ! Includes the wind upflow (inclination) angle (rotation about Y axis) - FF%RotToWind(1, :) = [cos(-FF%VFlowAngle)*cos(-FF%PropagationDir), & - cos(-FF%VFlowAngle)*sin(-FF%PropagationDir), & - -sin(-FF%VFlowAngle)] - FF%RotToWind(2, :) = [-sin(-FF%PropagationDir), & - cos(-FF%PropagationDir), & - 0.0_ReKi] - FF%RotToWind(3, :) = [sin(-FF%VFlowAngle)*cos(-FF%PropagationDir), & - sin(-FF%VFlowAngle)*sin(-FF%PropagationDir), & - cos(-FF%VFlowAngle)] - - ! Create the rotation matrices -- rotate from X'Y'Z' (wind aligned along X) - ! to global XYZ coordinates: this is the same as a rotation about the - ! (positive) upflow angle multiplied by a rotation about the (positive) wind direction: - ! Global wind = R(p%PropagationDir) * R(p%VFlowAngle) * [local wind] - ! local wind = R( -p%VFlowAngle) * R (-p%PropagationDir) [global wind] - ! = R^T(p%VFlowAngle) * R^T(p%PropagationDir) [global wind] - ! = (R(p%PropagationDir) * R(p%VFlowAngle))^T [global wind] - FF%RotFromWind = transpose(FF%RotToWind) - - FF%RotateWindBox = .not. (EqualRealNos(FF%PropagationDir, 0.0_ReKi) .and. & - EqualRealNos(FF%VFlowAngle, 0.0_ReKi)) - - FF%RefPosition = [0.0_ReKi, 0.0_ReKi, InitOut%FileDat%RefHt] - - !---------------------------------------------------------------------------- - ! Initialization Output - !---------------------------------------------------------------------------- - - InitOut%Ver = FlowField_IO_Ver - -end subroutine - -subroutine SteadyWind_ReadFile(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) - type(SteadyInitInputType), intent(in) :: InitInp +subroutine IfW_SteadyWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) + type(Steady_InitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(UniformFieldType), intent(out) :: UF type(WindFileDat), intent(out) :: FileDat @@ -291,8 +134,8 @@ subroutine SteadyWind_ReadFile(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMs end subroutine -subroutine UniformWind_ReadFile(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) - type(UniformInitInputType), intent(in) :: InitInp +subroutine IfW_UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) + type(Uniform_InitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(UniformFieldType), intent(out) :: UF type(WindFileDat), intent(out) :: FileDat @@ -449,7 +292,8 @@ subroutine UniformWind_ReadFile(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrM FileDat%MWS = FileDat%MWS/(UF%Time(UF%DataSize) - UF%Time(1)) end if - ! Check if the fist data point from the file is not along the X-axis while applying the windfield rotation + ! Check if the fist data point from the file is not along the X-axis while + ! applying the windfield rotation if ((.not. EqualRealNos(UF%AngleH(1), 0.0_ReKi)) .and. & (.not. EqualRealNos(InitInp%PropagationDir, 0.0_ReKi))) then call SetErrStat(ErrID_Warn, ' Possible double rotation of wind field! Uniform wind file starts with a wind direction of '// & @@ -481,7 +325,7 @@ subroutine UniformWind_ReadFile(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrM if (SumFileUnit > 0) then write (SumFileUnit, '(A)') - write (SumFileUnit, '(A)') 'Uniform wind. Module '//TRIM(FlowField_IO_Ver%Name)//' '//TRIM(FlowField_IO_Ver%Ver) + write (SumFileUnit, '(A)') 'Uniform wind. Module '//TRIM(InflowWind_IO_Ver%Name)//' '//TRIM(InflowWind_IO_Ver%Ver) write (SumFileUnit, '(A)') ' FileName: '//TRIM(InitInp%WindFileName) write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', UF%RefHeight write (SumFileUnit, '(A34,G12.4)') ' Reference length (m): ', UF%RefLength @@ -567,12 +411,48 @@ subroutine UniformWind_AllocArrays(UF, ErrStat, ErrMsg) end subroutine +subroutine Uniform_WriteHH(UF, FileRootName, unit, ErrStat, ErrMsg) + + type(UniformFieldType), intent(in) :: UF !< Parameter + character(*), intent(in) :: FileRootName !< RootName for output files + integer(IntKi), intent(in) :: Unit !< Indicates whether an error occurred (see NWTC_Library) + integer(IntKi), intent(out) :: ErrStat !< Error status of the operation + character(*), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + character(*), parameter :: RoutineName = 'Uniform_WriteHH' + integer(IntKi) :: i + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + call OpenFOutFile(unit, trim(FileRootName)//'.UniformWind.dat', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + write (unit, "(A)") "#" + write (unit, "(A)") '# Uniform Wind (deterministic) file for ENFAST generated by InflowWind' + write (unit, "(A)") "#" + write (unit, "(A)") "! Time Wind Wind Vertical Horiz. Pwr.Law Lin.Vert. Gust Upflow" + write (unit, "(A)") "! Speed Dir Speed Shear Vert.Shr Shear Speed Angle" + write (unit, "(A)") "! (sec) (m/s) (Deg) (m/s) (m/s) (deg)" + + do i = 1, UF%DataSize + write (unit, "(F15.5,8(1x,F11.4))") UF%Time(i), UF%VelH(i), UF%AngleH(i)*R2D, UF%VelV(i), & + UF%ShrH(i), UF%ShrV(i), UF%LinShrV(i), UF%VelGust(i), UF%AngleV(i)*R2D + end do + + close (unit) + +end subroutine Uniform_WriteHH + !> Read_TurbSim reads the binary TurbSim-format FF file (.bts). It fills the FFData array with !! velocity data for the grids and fills the Tower array with velocities at points on the tower !! (if data exists). -subroutine TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) +subroutine IfW_TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) - type(TurbSimInitInputType), intent(in) :: InitInp + type(TurbSim_InitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(Grid3DFieldType), intent(out) :: G3D type(WindFileDat), intent(out) :: FileDat @@ -795,7 +675,7 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) ! Store wind file metadata !---------------------------------------------------------------------------- - call Grid3DField_PopulateWindFileDat(G3D, InitInp%WindFileName, 3, G3D%NTGrids > 0, FileDat) + call Grid3D_PopulateWindFileDat(G3D, InitInp%WindFileName, 3, G3D%NTGrids > 0, FileDat) !---------------------------------------------------------------------------- ! Write the summary file @@ -804,7 +684,7 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) if (SumFileUnit > 0) then write (SumFileUnit, '(A)') write (SumFileUnit, '(A)') 'TurbSim wind type. Read by InflowWind sub-module ' & - //TRIM(FlowField_IO_Ver%Name)//' '//TRIM(FlowField_IO_Ver%Ver) + //TRIM(InflowWind_IO_Ver%Name)//' '//TRIM(InflowWind_IO_Ver%Ver) write (SumFileUnit, '(A)') TRIM(TmpErrMsg) write (SumFileUnit, '(5x,A)') 'FileName: '//TRIM(InitInp%WindFileName) write (SumFileUnit, '(5x,A29,I3)') 'Binary file format id: ', G3D%WindFileFormat @@ -845,9 +725,9 @@ subroutine TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) end subroutine -subroutine HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) +subroutine IfW_HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) - type(HAWCInitInputType), intent(in) :: InitInp + type(HAWC_InitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(Grid3DFieldType), intent(out) :: G3D type(WindFileDat), intent(out) :: FileDat @@ -912,7 +792,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) ! Validate initialization iput !---------------------------------------------------------------------------- - call Grid3DField_ValidateInput(InitInp%G3D, 3, TmpErrStat, TmpErrMsg) + call Grid3D_ValidateInput(InitInp%G3D, 3, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -1004,7 +884,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) ! Scale turbulence to requested intensity !---------------------------------------------------------------------------- - call ScaleTurbulence(InitInp%G3D, G3D%Vel, ScaleFactors, TmpErrStat, TmpErrMsg) + call Grid3D_ScaleTurbulence(InitInp%G3D, G3D%Vel, ScaleFactors, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -1026,7 +906,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) ! Store wind file metadata !---------------------------------------------------------------------------- - call Grid3DField_PopulateWindFileDat(G3D, InitInp%WindFileName(1), 5, .false., FileDat) + call Grid3D_PopulateWindFileDat(G3D, InitInp%WindFileName(1), 5, .false., FileDat) !---------------------------------------------------------------------------- ! Write the summary file @@ -1034,7 +914,7 @@ subroutine HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) if (SumFileUnit > 0) then write (SumFileUnit, '(A)') - write (SumFileUnit, '(A)') 'HAWC wind type. Read by InflowWind sub-module FlowField_IO' + write (SumFileUnit, '(A)') 'HAWC wind type. Read by InflowWind sub-module InflowWind_IO' write (SumFileUnit, '(A34,G12.4)') ' Reference height (m): ', G3D%RefHeight write (SumFileUnit, '(A34,G12.4)') ' Timestep (s): ', G3D%DTime @@ -1058,9 +938,9 @@ subroutine HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) end subroutine !> User_Init initializes a user defined wind field. -subroutine User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) +subroutine IfW_User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) - type(UserInitInputType), intent(in) :: InitInp + type(User_InitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(UserFieldType), intent(out) :: UF type(WindFileDat), intent(out) :: FileDat @@ -1081,10 +961,9 @@ subroutine User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) end subroutine !> Grid4D_Init initializes a wind field defined by a 4D grid. -subroutine Grid4D_Init(InitInp, SumFileUnit, G4D, FileDat, ErrStat, ErrMsg) +subroutine IfW_Grid4D_Init(InitInp, G4D, FileDat, ErrStat, ErrMsg) - type(Grid4DInitInputType), intent(in) :: InitInp - integer(IntKi), intent(in) :: SumFileUnit + type(Grid4D_InitInputType), intent(in) :: InitInp type(Grid4DFieldType), intent(out) :: G4D type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat @@ -1112,53 +991,47 @@ subroutine Grid4D_Init(InitInp, SumFileUnit, G4D, FileDat, ErrStat, ErrMsg) ! Initialize velocities to zero G4D%Vel = 0.0_SiKi - if (SumFileUnit > 0) then - write (SumFileUnit, '(A)') InitInp%n - end if - end subroutine -subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, ErrMsg) +subroutine IfW_Bladed_Init(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, ErrMsg) - type(BladedInitInputType), intent(in) :: InitInp !< Initialization data passed to the module + type(Bladed_InitInputType), intent(in) :: InitInp !< Initialization data passed to the module integer(IntKi), intent(in) :: SumFileUnit - type(BladedInitOutputType), intent(out) :: InitOut !< Initial output + type(Bladed_InitOutputType), intent(out) :: InitOut !< Initial output type(Grid3DFieldType), intent(out) :: G3D !< Parameters type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered character(*), intent(out) :: ErrMsg !< Message about errors - ! REAL(ReKi), INTENT( OUT) :: TI (3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI - character(*), parameter :: RoutineName = "Bladed_ReadFile" - type(Grid3DInitInputType) :: G3D_InitInp ! initialization input for grid 3d field - real(ReKi) :: BinTI(3) ! turbulence intensities of the wind components as defined in the FF binary file, not necessarially the actual TI - real(ReKi) :: NatTI(3) ! turbulence intensities of the wind components as defined in the native FF summary file + character(*), parameter :: RoutineName = "Bladed_Init" + real(ReKi) :: TI(3) ! turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI + type(Grid3D_InitInputType) :: G3D_InitInp ! initialization input for grid 3d field + real(ReKi) :: BinTI(3) ! turbulence intensities of the wind components as defined in the FF binary file, not necessarially the actual TI + real(ReKi) :: NatTI(3) ! turbulence intensities of the wind components as defined in the native FF summary file real(ReKi) :: UBar real(ReKi) :: ZCenter real(ReKi) :: ScaleFactors(3) ! turbulence scaling factors - real(ReKi) :: TI(3) real(ReKi) :: SigmaF(3) ! Turbulence standard deviation - integer(IntKi) :: ScaleMethod - integer(IntKi) :: UnitWind ! Unit number for the InflowWind input file + integer(IntKi) :: UnitWind ! Unit number for the InflowWind input file integer(B2Ki) :: Dum_Int2 integer(IntKi) :: I logical :: CWise - logical :: LHR ! Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) + logical :: LHR ! Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) logical :: Exists - character(1028) :: SumFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. - character(1028) :: TwrFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. + character(1028) :: SumFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. + character(1028) :: TwrFile ! length is LEN(ParamData%WindFileName) + the 4-character extension. character(1024) :: BinFileName character(1024) :: PriPath - character(ErrMsgLen) :: TmpErrMsg ! temporary error message - integer(IntKi) :: TmpErrStat ! temporary error status + character(ErrMsgLen) :: TmpErrMsg ! temporary error message + integer(IntKi) :: TmpErrStat ! temporary error status ErrMsg = '' ErrStat = ErrID_None if (InitInp%NativeBladedFmt) then - call Bladed_ReadNativeSummary(InitInp%WindFileName, G3D_InitInp%PLExp, G3D_InitInp%VLinShr, & - G3D_InitInp%HLinShr, G3D_InitInp%RefLength, NatTI, G3D%MeanWS, & + call Bladed_ReadNativeSummary(InitInp%WindFileName, G3D%PLExp, G3D%VLinShr, & + G3D%HLinShr, G3D_InitInp%RefLength, NatTI, G3D%MeanWS, & G3D%RefHeight, InitOut%PropagationDir, InitOut%VFlowAngle, & BinFileName, G3D_InitInp%XOffset, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) @@ -1191,30 +1064,29 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, G3D_InitInp%URef = G3D%MeanWS G3D_InitInp%WindProfileType = WindProfileType_PL ! it could also have logarithmic, but I'm going to leave that off for now - InitOut%TI = 100.0_ReKi + TI = 100.0_ReKi UBar = 0.0_ReKi LHR = .true. else InitOut%PropagationDir = 0.0_ReKi InitOut%VFlowAngle = 0.0_ReKi - G3D_InitInp%VLinShr = 0.0_ReKi - G3D_InitInp%HLinShr = 0.0_ReKi - G3D_InitInp%RefLength = 1.0_ReKi + G3D%VLinShr = 0.0_ReKi + G3D%HLinShr = 0.0_ReKi + G3D%RefLength = 1.0_ReKi BinFileName = InitInp%WindFileName end if ! Get a unit number to use - call GetNewUnit(UnitWind, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return - !---------------------------------------------------------------------------------------------- - ! Open the binary file, read its "header" (first 2-byte integer) to determine what format - ! binary file it is, and close it. - !---------------------------------------------------------------------------------------------- + !---------------------------------------------------------------------------- + ! 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 SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) @@ -1226,14 +1098,14 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, close (UnitWind) if (TmpErrStat /= 0) then - call SetErrStat(ErrID_Fatal, ' Error reading first binary integer from file "'//TRIM(BinFileName)//'."', & - ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, ' Error reading first binary integer from file "' & + //TRIM(BinFileName)//'."', ErrStat, ErrMsg, RoutineName) return end if - !---------------------------------------------------------------------------------------------- + !---------------------------------------------------------------------------- ! Read the files to get the required FF data. - !---------------------------------------------------------------------------------------------- + !---------------------------------------------------------------------------- ! Store the binary format information so the InflowWind code can use it. ! Also changes to IntKi from INT(2) to compare in the SELECT below @@ -1241,25 +1113,26 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, select case (G3D%WindFileFormat) - case (-1, -2, -3, -99) ! Bladed-style binary format + case (-1, -2, -3, -99) ! Bladed-style binary format if (.not. InitInp%NativeBladedFmt) then - !........................................................................................... - ! Create full-field summary file name from binary file root name. Also get tower file - ! name. - !........................................................................................... + !---------------------------------------------------------------------- + ! Create full-field summary file name from binary file root name. + ! Also get tower file name. + !---------------------------------------------------------------------- call GetRoot(BinFileName, SumFile) TwrFile = TRIM(SumFile)//'.twr' SumFile = TRIM(SumFile)//'.sum' - !........................................................................................... + !---------------------------------------------------------------------- ! Read the summary file to get necessary scaling information - !........................................................................................... + !---------------------------------------------------------------------- - call Bladed_ReadTurbSimSummary(UnitWind, TRIM(SumFile), CWise, ZCenter, InitOut%TI, UBar, G3D%RefHeight, G3D%Periodic, LHR, TmpErrStat, TmpErrMsg) + call Bladed_ReadTurbSimSummary(UnitWind, TRIM(SumFile), CWise, ZCenter, TI, & + UBar, G3D%RefHeight, G3D%Periodic, LHR, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then close (UnitWind) @@ -1268,9 +1141,9 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, end if - !........................................................................................... + !------------------------------------------------------------------------- ! Open the binary file and read its header - !........................................................................................... + !------------------------------------------------------------------------- call OpenBInpFile(UnitWind, TRIM(BinFileName), TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) @@ -1279,7 +1152,7 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, return end if - if (Dum_Int2 == -99) then ! Newer-style BLADED format + if (Dum_Int2 == -99) then ! Newer-style BLADED format call Bladed_ReadHeader1(UnitWind, BinTI, G3D, InitInp%NativeBladedFmt, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then @@ -1292,7 +1165,7 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, if (.not. InitInp%NativeBladedFmt) then do I = 1, G3D%NComp - if (BinTI(I) > 0) InitOut%TI(I) = BinTI(I) + if (BinTI(I) > 0) TI(I) = BinTI(I) end do end if @@ -1335,11 +1208,11 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, ! Read the binary grids (converted tƒo m/s) and close the file !------------------------------------------------------------------------- - call Bladed_ReadGrids(UnitWind, InitInp%NativeBladedFmt, CWise, LHR, InitOut%TI, G3D, TmpErrStat, TmpErrMsg) + call Bladed_ReadGrids(UnitWind, InitInp%NativeBladedFmt, CWise, LHR, TI, G3D, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) close (UnitWind) - if (InitInp%NativeBladedFmt) InitOut%TI = NatTI*100.0_ReKi ! report these TI for the native Bladed format in percent + if (InitInp%NativeBladedFmt) TI = NatTI*100.0_ReKi ! report these TI for the native Bladed format in percent if (ErrStat >= AbortErrLev) return @@ -1386,6 +1259,11 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, !---------------------------------------------------------------------------- G3D%AddMeanAfterInterp = .false. + G3D%Z0 = G3D_InitInp%Z0 + G3D%PLExp = G3D_InitInp%PLExp + G3D%VLinShr = G3D_InitInp%VLinShr + G3D%HLinShr = G3D_InitInp%HLinShr + G3D%RefLength = G3D_InitInp%RefLength if (InitInp%NativeBladedFmt) then @@ -1393,12 +1271,12 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, G3D%AddMeanAfterInterp = .true. ! Validate scaling data if we've got native-Bladed format - call Grid3DField_ValidateInput(G3D_InitInp, G3D%NComp, TmpErrStat, TmpErrMsg) + call Grid3D_ValidateInput(G3D_InitInp, G3D%NComp, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return ! scale to requested TI (or use requested scale factors) - call ScaleTurbulence(G3D_InitInp, G3D%Vel(:, :, :, 1:G3D%NSteps), ScaleFactors, TmpErrStat, TmpErrMsg) + call Grid3D_ScaleTurbulence(G3D_InitInp, G3D%Vel(:, :, :, 1:G3D%NSteps), ScaleFactors, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return else @@ -1414,24 +1292,27 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, G3D%TotalTime = (G3D%NSteps - 1)*G3D%DTime end if - IF (InitInp%NativeBladedFmt) THEN + if (InitInp%NativeBladedFmt) then G3D%InitXPosition = G3D_InitInp%XOffset - END IF + end if - !------------------------------------------------------------------------------------------------- - ! Set the InitOutput information - !------------------------------------------------------------------------------------------------- + !---------------------------------------------------------------------------- + ! Store wind file metadata + !---------------------------------------------------------------------------- - InitOut%TI = TI + call Grid3D_PopulateWindFileDat(G3D, InitInp%WindFileName, InitInp%WindType, G3D%NTGrids > 0, FileDat) - !------------------------------------------------------------------------------------------------- + FileDat%TI = TI + FileDat%TI_listed = .true. + + !---------------------------------------------------------------------------- ! Write to the summary file - !------------------------------------------------------------------------------------------------- + !---------------------------------------------------------------------------- if (SumFileUnit > 0) then write (SumFileUnit, '(A)') write (SumFileUnit, '(A)') 'Bladed-style wind type. Read by InflowWind sub-module '// & - TRIM(FlowField_IO_Ver%Name)//' '//TRIM(FlowField_IO_Ver%Ver) + TRIM(InflowWind_IO_Ver%Name)//' '//TRIM(InflowWind_IO_Ver%Ver) write (SumFileUnit, '(A)') TRIM(TmpErrMsg) write (SumFileUnit, '(A)') ' FileName: '//TRIM(InitInp%WindFileName) write (SumFileUnit, '(A34,I3)') ' Binary file format id: ', G3D%WindFileFormat @@ -1471,7 +1352,7 @@ subroutine Bladed_ReadFile(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, end if end if -end subroutine Bladed_ReadFile +end subroutine IfW_Bladed_Init subroutine Bladed_ReadTurbSimSummary(UnitWind, FileName, CWise, ZCenter, TI, UBar, RefHt, Periodic, LHR, ErrStat, ErrMsg) @@ -1673,7 +1554,7 @@ subroutine Bladed_ReadTurbSimSummary(UnitWind, FileName, CWise, ZCenter, TI, UBa !------------------------------------------------------------------------------------------- ! #5: Get the grid "HEIGHT OFFSET", if it exists (in TurbSim). Otherwise, assume it's zero - ! ZGOffset = HH - GridBase - ParamData%FF%FFZHWid + ! ZGOffset = HH - GridBase - ParamData%FF%ZHWid !------------------------------------------------------------------------------------------- if (INDEX(LINE, 'HEIGHT OFFSET') > 0) then @@ -1719,15 +1600,15 @@ subroutine Bladed_ReadTurbSimSummary(UnitWind, FileName, CWise, ZCenter, TI, UBa end do !WHILE - !------------------------------------------------------------------------------------------------- + !---------------------------------------------------------------------------- ! Close the summary file - !------------------------------------------------------------------------------------------------- + !---------------------------------------------------------------------------- close (UnitWind) - !------------------------------------------------------------------------------------------------- + !---------------------------------------------------------------------------- ! Calculate the height of the grid center - !------------------------------------------------------------------------------------------------- + !---------------------------------------------------------------------------- ZCenter = RefHt - ZGOffset @@ -1848,7 +1729,6 @@ end subroutine Cleanup end subroutine Bladed_ReadNativeSummary -!==================================================================================================== !> Reads the binary headers from the turbulence files of the old Bladed variety. Note that !! because of the normalization, neither ParamData%FF%NZGrids or ParamData%FF%NYGrids are larger than 32 points. !! 21-Sep-2009 - B. Jonkman, NREL/NWTC. @@ -2217,7 +2097,7 @@ subroutine Bladed_ReadGrids(UnitWind, NativeBladedFmt, CWise, LHR, TI, G3D, ErrS ! Loop through time steps do IT = 1, G3D%NSteps - ! Read raw data (NFFComp,NYGrids,NZGrids) + ! Read raw data (NComp,NYGrids,NZGrids) read (UnitWind, IOStat=TmpErrStat) raw_ff ! If data was read successfully, transfer into velocity array, continue @@ -2241,7 +2121,7 @@ subroutine Bladed_ReadGrids(UnitWind, NativeBladedFmt, CWise, LHR, TI, G3D, ErrS 'ic = '//TRIM(Num2LStr(ic))// & ', ir = '//TRIM(Num2LStr(ir))// & ', it = '//TRIM(Num2LStr(it))// & - ', nffsteps = '//TRIM(Num2LStr(G3D%NSteps)), ErrStat, ErrMsg, RoutineName) + ', nsteps = '//TRIM(Num2LStr(G3D%NSteps)), ErrStat, ErrMsg, RoutineName) return end do @@ -2404,7 +2284,7 @@ subroutine Bladed_ReadTower(UnitWind, G3D, TwrFileName, ErrStat, ErrMsg) read (UnitWind, IOSTAT=TmpErrStat) raw_twr ! normalized wind-component, INT(2) if (TmpErrStat /= 0) then call SetErrStat(ErrID_Fatal, ' Error reading binary tower data file. it = '//TRIM(Num2LStr(it))// & - ', nffsteps = '//TRIM(Num2LStr(G3D%NSteps)), ErrStat, ErrMsg, RoutineName) + ', nsteps = '//TRIM(Num2LStr(G3D%NSteps)), ErrStat, ErrMsg, RoutineName) G3D%NTGrids = 0 return end if @@ -2426,7 +2306,7 @@ subroutine Bladed_ReadTower(UnitWind, G3D, TwrFileName, ErrStat, ErrMsg) end subroutine Bladed_ReadTower -subroutine Grid3DField_PopulateWindFileDat(Grid3DField, FileName, WindType, HasTower, FileDat) +subroutine Grid3D_PopulateWindFileDat(Grid3DField, FileName, WindType, HasTower, FileDat) type(Grid3DFieldType), intent(in) :: Grid3DField character(*), intent(in) :: FileName @@ -2445,7 +2325,8 @@ subroutine Grid3DField_PopulateWindFileDat(Grid3DField, FileName, WindType, HasT if (Grid3DField%Periodic) then FileDat%TRange = [0.0_ReKi, Grid3DField%TotalTime] FileDat%TRange_Limited = .false. - else ! Shift the time range to compensate for the shifting of the wind grid + else + ! Shift the time range to compensate for the shifting of the wind grid FileDat%TRange = [0.0_ReKi, Grid3DField%TotalTime] - Grid3DField%InitXPosition*Grid3DField%InvMWS FileDat%TRange_Limited = .true. end if @@ -2470,9 +2351,9 @@ subroutine Grid3DField_PopulateWindFileDat(Grid3DField, FileName, WindType, HasT end subroutine -subroutine Grid3DField_AddMeanVelocity(InitInp, G3D) +subroutine Grid3D_AddMeanVelocity(InitInp, G3D) - type(Grid3DInitInputType), intent(in) :: InitInp !< Initialization input data passed to the module + type(Grid3D_InitInputType), intent(in) :: InitInp !< Initialization input data passed to the module type(Grid3DFieldType), intent(inout) :: G3D !< Initialization input data passed to the module real(ReKi) :: Z ! height @@ -2533,15 +2414,15 @@ subroutine Grid3DField_AddMeanVelocity(InitInp, G3D) end do end if -end subroutine Grid3DField_AddMeanVelocity +end subroutine Grid3D_AddMeanVelocity -subroutine ScaleTurbulence(InitInp, Vel, ScaleFactors, ErrStat, ErrMsg) +subroutine Grid3D_ScaleTurbulence(InitInp, Vel, ScaleFactors, ErrStat, ErrMsg) - type(Grid3DInitInputType), intent(IN) :: InitInp !< Initialization input data passed to the module + type(Grid3D_InitInputType), intent(in) :: InitInp !< Initialization input data passed to the module real(SiKi), intent(INOUT) :: Vel(:, :, :, :) !< full-field wind inflow data - real(ReKi), intent(OUT) :: ScaleFactors(3) !< scaling factors that were used - integer(IntKi), intent(OUT) :: ErrStat !< determines if an error has been encountered - character(*), intent(OUT) :: ErrMsg !< Message about errors + real(ReKi), intent(out) :: ScaleFactors(3) !< scaling factors that were used + integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered + character(*), intent(out) :: ErrMsg !< Message about errors ! Local Variables: ! note that the variables used to compute statistics use double precision: @@ -2620,17 +2501,16 @@ subroutine ScaleTurbulence(InitInp, Vel, ScaleFactors, ErrStat, ErrMsg) Vel(ic, :, :, :) = real(ScaleFactors(ic)*Vel(ic, :, :, :), SiKi) end do -end subroutine ScaleTurbulence +end subroutine Grid3D_ScaleTurbulence -subroutine Grid3DField_ValidateInput(InitInp, NComp, ErrStat, ErrMsg) +subroutine Grid3D_ValidateInput(InitInp, NComp, ErrStat, ErrMsg) - type(Grid3DInitInputType), intent(IN) :: InitInp !< Initialization input data passed to the module - integer(IntKi), intent(IN) :: NComp !< number of full-field wind components (normally 3) + type(Grid3D_InitInputType), intent(in) :: InitInp !< Initialization input data passed to the module + integer(IntKi), intent(in) :: NComp !< number of full-field wind components (normally 3) - character(*), parameter :: RoutineName = 'Grid3DField_ValidateInput' - integer(intki) :: ic ! loop counter - integer(IntKi), intent(OUT) :: ErrStat !< determines if an error has been encountered - character(*), intent(OUT) :: ErrMsg !< Message about errors + character(*), parameter :: RoutineName = 'Grid3DField_ValidateInput' + integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered + character(*), intent(out) :: ErrMsg !< Message about errors ErrStat = ErrID_None ErrMsg = "" @@ -2660,6 +2540,339 @@ subroutine Grid3DField_ValidateInput(InitInp, NComp, ErrStat, ErrMsg) end if end if -end subroutine Grid3DField_ValidateInput +end subroutine + +subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) + + type(Grid3DFieldType), intent(in) :: G3D !< Parameters + character(*), intent(in) :: FileRootName !< Name of the file to write the output in + integer(IntKi), intent(in) :: Unit !< Indicates whether an error occurred (see NWTC_Library) + integer(IntKi), intent(out) :: ErrStat !< Indicates whether an error occurred (see NWTC_Library) + character(*), intent(out) :: ErrMsg !< Error message associated with the ErrStat + + character(*), parameter :: RoutineName = 'Grid3D_WriteBladed' + real(ReKi), parameter :: Tolerance = 0.0001 ! The largest difference between two numbers that are assumed to be equal + integer(IntKi) :: ic, it, iy, iz + real(ReKi), allocatable :: MeanVal(:, :) + real(ReKi), allocatable :: SigmaGrid(:, :) + real(ReKi) :: TI(3) !< array containing turbulence intensity (for scaling factors) + real(ReKi) :: Sigma(3) !< array containing standard deviations (for scaling factors) + real(ReKi) :: Scl(3) !< array containing scaling factors + real(ReKi) :: Off(3) !< array containing offsets + real(ReKi) :: Tmp + real(ReKi) :: MeanWS_nonZero !< advection speed (mean wind speed at hub) + real(ReKi) :: delta(3) + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + delta = [G3D%MeanWS*G3D%DTime, 1.0_SiKi/G3D%InvDY, 1.0_SiKi/G3D%InvDZ] + + call AllocAry(MeanVal, G3D%NYGrids, G3D%NZGrids, "MeanVal", ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + call AllocAry(SigmaGrid, G3D%NYGrids, G3D%NZGrids, "SigmaGrid", ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Loop through components + do ic = 3, 1, -1 + + ! mean values: + MeanVal = 0.0_SiKi + do it = 1, G3D%NSteps + MeanVal = MeanVal + G3D%Vel(ic, :, :, it) + end do + MeanVal = MeanVal/real(G3D%NSteps, SiKi) + + ! standard deviations (with 1/N scaling factor): + SigmaGrid = 0.0_SiKi + do it = 1, size(G3D%Vel, 4) + SigmaGrid = SigmaGrid + G3D%Vel(ic, :, :, it)**2 + end do + SigmaGrid = SigmaGrid/G3D%NSteps + SigmaGrid = sqrt(max(SigmaGrid - MeanVal**2, 0.0_ReKi)) + + ! now get the average standard deviation for each component: + Sigma(ic) = sum(SigmaGrid)/size(SigmaGrid) ! get the average sigma over the grid + Sigma(ic) = max(100.0_ReKi*Tolerance, Sigma(ic)) ! make sure this scaling isn't too small + + end do + + ! We need to take into account the shear across the grid in the sigma calculations for scaling the data, + ! and ensure that 32.767*sigma_u >= |V-UHub| so that we don't get values out of the range of our scaling values + ! in this BLADED-style binary output. Tmp is |V-UHub| + ! Get the range of wind speed values for scaling in BLADED-format .wnd files + Tmp = max(abs(maxval(G3D%Vel(:, :, 1, :)) - G3D%MeanWS), abs(minval(G3D%Vel(1, :, :, :)) - G3D%MeanWS)) + Sigma(1) = max(Sigma(1), 0.05_ReKi*Tmp) + do ic = 2, 3 + ! put the abs() after the maxval() and minval() to avoid stack-overflow issues with large wind files + Sigma(ic) = max(Sigma(ic), 0.05_ReKi*abs(maxVAL(G3D%Vel(ic, :, :, :))), 0.05_ReKi*abs(minval(G3D%Vel(ic, :, :, :)))) + end do + + ! Put normalizing factors into the summary file. The user can use them to + ! tell a simulation program how to rescale the data. + if (abs(G3D%MeanWS) < 0.1_ReKi) then + MeanWS_nonZero = sign(0.1_ReKi, G3D%MeanWS) + else + MeanWS_nonZero = G3D%MeanWS + end if + + TI = Sigma/MeanWS_nonZero + + !---------------------------------------------------------------------------- + ! The summary file + !---------------------------------------------------------------------------- + + call OpenFOutFile(unit, trim(FileRootName)//'-Bladed.sum', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! The string "TurbSim" needs to be in the 2nd line of the summary file if AeroDyn will read this. + write (unit, "( / 'TurbSim - This summary file was generated by ', A, ' on ' , A , ' at ' , A , '.' / )") "NWTC_Library", CurDate(), CurTime() + write (unit, '(/)') + write (unit, '(/)') + write (unit, '( L10, 2X, "Clockwise rotation when looking downwind?")') .false. + write (unit, '( F10.3, 2X, "Hub height [m]")') G3D%RefHeight + write (unit, '( F10.3, 2X, "Grid height [m]")') delta(3)*(G3D%NZGrids - 1) + write (unit, '( F10.3, 2X, "Grid width [m]")') delta(2)*(G3D%NYGrids - 1) + write (unit, '(/"BLADED-style binary scaling parameters:"/)') + write (unit, '( 2X, "UBar = ", F9.4, " m/s")') MeanWS_nonZero + write (unit, '( 2X, "TI(u) = ", F9.4, " %")') 100.0*TI(1) + write (unit, '( 2X, "TI(v) = ", F9.4, " %")') 100.0*TI(2) + write (unit, '( 2X, "TI(w) = ", F9.4, " %")') 100.0*TI(3) + write (unit, '(/)') + write (unit, '( 2X, "Height offset = ", F9.4, " m" )') G3D%RefHeight - 0.5*delta(3)*(G3D%NZGrids - 1) - G3D%GridBase + write (unit, '( 2X, "Grid Base = ", F9.4, " m" )') G3D%GridBase + if (G3D%Periodic) then + write (unit, '()') + write (unit, '( A)') 'Creating a PERIODIC output file.' + end if + write (unit, '( A)') 'Creating a BLADED LEFT-HAND RULE output file.' + + close (unit) + + !---------------------------------------------------------------------------- + ! The BINARY file + !---------------------------------------------------------------------------- + + call OpenBOutFile(unit, TRIM(FileRootName)//'-Bladed.wnd', ErrStat, ErrMsg) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + write (unit) INT(-99, B2Ki) ! -99 = New Bladed format + write (unit) INT(4, B2Ki) ! 4 = improved von karman (not used, but needed for next 7 inputs) + write (unit) INT(size(G3D%Vel, 3), B4Ki) ! size(FFWind,3) = 3 = number of wind components + write (unit) real(45.0_SiKi, SiKi) ! Latitude (degrees) (informational, not used in FAST) + write (unit) real(0.03_SiKi, SiKi) ! Roughness length (m) (informational, not used in FAST) + write (unit) real(G3D%RefHeight, SiKi) ! Reference Height (m) (informational, not used in FAST) + write (unit) real(100.0*TI(1), SiKi) ! Longitudinal turbulence intensity (%) + write (unit) real(100.0*TI(2), SiKi) ! Lateral turbulence intensity (%) + write (unit) real(100.0*TI(3), SiKi) ! Vertical turbulence intensity (%) + + write (unit) real(delta(3), SiKi) ! grid spacing in vertical direction, in m + write (unit) real(delta(2), SiKi) ! grid spacing in lateral direction, in m + write (unit) real(delta(1), SiKi) ! grid spacing in longitudinal direciton, in m + write (unit) INT(G3D%NSteps/2, B4Ki) ! half the number of points in alongwind direction + write (unit) real(MeanWS_nonZero, SiKi) ! the mean wind speed in m/s + write (unit) real(0, SiKi) ! the vertical length scale of the longitudinal component in m + write (unit) real(0, SiKi) ! the lateral length scale of the longitudinal component in m + write (unit) real(0, SiKi) ! the longitudinal length scale of the longitudinal component in m + write (unit) INT(0, B4Ki) ! an unused integer + write (unit) INT(0, B4Ki) ! the random number seed + write (unit) INT(G3D%NZGrids, B4Ki) ! the number of grid points vertically + write (unit) INT(G3D%NYGrids, B4Ki) ! the number of grid points laterally + write (unit) INT(0, B4Ki) ! the vertical length scale of the lateral component, not used + write (unit) INT(0, B4Ki) ! the lateral length scale of the lateral component, not used + write (unit) INT(0, B4Ki) ! the longitudinal length scale of the lateral component, not used + write (unit) INT(0, B4Ki) ! the vertical length scale of the vertical component, not used + write (unit) INT(0, B4Ki) ! the lateral length scale of the vertical component, not used + write (unit) INT(0, B4Ki) ! the longitudinal length scale of the vertical component, not used + + ! Scaling value to convert wind speeds to 16-bit integers + do ic = 1, 3 + if (.not. EqualRealNos(Sigma(ic), 0.0_ReKi)) then + Scl(ic) = 1000.0/(Sigma(ic)) + else + Scl(ic) = 1.0_ReKi + end if + end do + + ! Bladed convention is positive V is pointed along negative Y (IEC turbine coordinate) + Scl(2) = -Scl(2) + + ! Offset value to convert wind speeds to 16-bit integers + if (G3D%AddMeanAfterInterp) then ! Note that this will not take into account any shear!!! + Off(1) = 0.0 + else + Off(1) = G3D%MeanWS*Scl(1) + end if + Off(2) = 0.0 + Off(3) = 0.0 + + ! Scale velocity for 16-bit integers and write to file + do it = 1, G3D%NSteps + do iz = 1, G3D%NZGrids + do iy = 1, G3D%NYGrids + write (unit) NINT(G3D%Vel(:, iy, iz, it)*Scl - Off, B2Ki) ! scale to int16 + end do !IY + end do !IZ + end do !IT + + close (unit) + +end subroutine Grid3D_WriteBladed + +subroutine Grid3D_WriteVTK(G3D, FileRootName, unit, ErrStat, ErrMsg) + + type(Grid3DFieldType), intent(in) :: G3D !< Parameters + character(*), intent(in) :: FileRootName !< RootName for output files + integer(IntKi), intent(in) :: unit !< Error status of the operation + integer(IntKi), intent(out) :: ErrStat !< Error status of the operation + character(*), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + character(*), parameter :: RoutineName = 'ConvertField_toVTK' + character(1024) :: RootPathName + character(1024) :: FileName + integer :: i + integer :: iy + integer :: iz + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + call GetPath(FileRootName, RootPathName) + + ! Loop through time steps + do i = 1, G3D%NSteps + + ! Create the output vtk file with naming /vtk/DisYZ.t.vtk + RootPathName = trim(RootPathName)//PathSep//"vtk" + call MkDir(trim(RootPathName)) ! make this directory if it doesn't already exist + + FileName = trim(RootPathName)//PathSep//"DisYZ.t"//trim(num2lstr(i))//".vtp" + + ! see WrVTK_SP_header + call OpenFOutFile(unit, TRIM(FileName), ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + write (unit, '(A)') '# vtk DataFile Version 3.0' + write (unit, '(A)') "InflowWind YZ Slice at T= "//trim(num2lstr((i - 1)*G3D%DTime))//" s" + write (unit, '(A)') 'ASCII' + write (unit, '(A)') 'DATASET STRUCTURED_POINTS' + + ! Note: gridVals must be stored such that the left-most dimension is X + ! and the right-most dimension is Z (see WrVTK_SP_vectors3D) + write (unit, '(A,3(i5,1X))') 'DIMENSIONS ', 1, G3D%NYGrids, G3D%NZGrids + write (unit, '(A,3(f10.2,1X))') 'ORIGIN ', G3D%InitXPosition, -G3D%YHWid, G3D%GridBase + write (unit, '(A,3(f10.2,1X))') 'SPACING ', 0.0_ReKi, 1.0_SiKi/G3D%InvDY, 1.0_SiKi/G3D%InvDZ + write (unit, '(A,i5)') 'POINT_DATA ', G3D%NYGrids*G3D%NZGrids + write (unit, '(A)') 'VECTORS DisYZ float' + + do iz = 1, G3D%NZGrids + do iy = 1, G3D%NYGrids + write (unit, '(3(f10.2,1X))') G3D%Vel(:, iy, iz, i) + end do + end do + + close (unit) + + end do + +end subroutine Grid3D_WriteVTK + +subroutine Grid3D_WriteHAWC(G3D, FileRootName, unit, ErrStat, ErrMsg) + + character(*), intent(in) :: FileRootName !< Name of the file to write the output in + type(Grid3DFieldType), intent(in) :: G3D !< Parameters + integer(IntKi), intent(in) :: unit !< Error status of the operation + integer(IntKi), intent(out) :: ErrStat !< Indicates whether an error occurred (see NWTC_Library) + character(*), intent(out) :: ErrMsg !< Error message associated with the ErrStat + + character(*), parameter :: RoutineName = 'Grid3D_WriteHAWC' + character(*), parameter :: Comp(3) = (/'u', 'v', 'w'/) + real(ReKi) :: delta(3) + integer(IntKi) :: IC, IX, IY, IZ + real(ReKi), allocatable :: MeanVal(:) + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(1024) :: RootWithoutPathName + + ErrStat = ErrID_None + ErrMsg = "" + + ! Array containing dx, dy, dz in meters + delta = [G3D%MeanWS*G3D%DTime, 1.0_ReKi/G3D%InvDY, 1.0_ReKi/G3D%InvDZ] + + ! Allocate array to hold mean value by Z location + call AllocAry(MeanVal, G3D%NZGrids, "MeanVal", ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + ! Calculate mean value at each Z location + MeanVal = sum(G3D%Vel(1, 1, :, :), dim=2)/G3D%NSteps + + !---------------------------------------------------------------------------- + ! Write summary file + !---------------------------------------------------------------------------- + + call OpenFOutFile(unit, trim(FileRootName)//'-HAWC.sum', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + write (unit, '(A)') '; Wind file converted to HAWC format on '//CurDate()//' at '//CurTime() + + write (unit, '()') + do IZ = G3D%NZGrids, 1, -1 + write (unit, '(A,I3,A,F15.5)') '; mean removed at z(', iz, ') = ', MeanVal(iz) + end do + + write (unit, '(A)') 'turb_format 1 ;' + + write (unit, '()') + write (unit, '(A)') 'begin mann;' + + ic = INDEX(FileRootName, '\', BACK=.true.) + ic = MAX(ic, INDEX(FileRootName, '/', BACK=.true.)) + RootWithoutPathName = FileRootName((ic + 1):) + + write (unit, '(2x,A, T30, A, " ;")') 'filename_u', trim(RootWithoutPathName)//'-HAWC-u.bin' + write (unit, '(2x,A, T30, A, " ;")') 'filename_v', trim(RootWithoutPathName)//'-HAWC-v.bin' + write (unit, '(2x,A, T30, A, " ;")') 'filename_w', trim(RootWithoutPathName)//'-HAWC-w.bin' + + write (unit, '(2x,A, T30, I8, 1x, F15.5, " ;")') 'box_dim_u', G3D%NSteps, delta(1) + write (unit, '(2x,A, T30, I8, 1x, F15.5, " ;")') 'box_dim_v', G3D%NYGrids, delta(2) + write (unit, '(2x,A, T30, I8, 1x, F15.5, " ;")') 'box_dim_w', G3D%NZGrids, delta(3) + + write (unit, '(2x,A)') 'dont_scale 1; converter did not rescale turbulence to unit standard deviation' + write (unit, '(A)') 'end mann;' + close (unit) + + !---------------------------------------------------------------------------- + ! Write the binary files for each component + !---------------------------------------------------------------------------- + + do IC = 1, G3D%NComp + + call OpenBOutFile(unit, trim(FileRootName)//'-HAWC-'//Comp(ic)//'.bin', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + + do IX = 1, G3D%NSteps + do IY = G3D%NYGrids, 1, -1 + write (unit, IOSTAT=ErrStat2) G3D%Vel(ic, iy, :, ix) - MeanVal + end do + end do + + close (unit) + + MeanVal = 0.0_SiKi + + end do + +end subroutine Grid3D_WriteHAWC -end module FlowField_IO +end module InflowWind_IO diff --git a/modules/inflowwind/src/FlowField_IO.txt b/modules/inflowwind/src/InflowWind_IO.txt similarity index 76% rename from modules/inflowwind/src/FlowField_IO.txt rename to modules/inflowwind/src/InflowWind_IO.txt index d5223aff59..a6d825bde9 100644 --- a/modules/inflowwind/src/FlowField_IO.txt +++ b/modules/inflowwind/src/InflowWind_IO.txt @@ -9,18 +9,41 @@ include Registry_NWTC_Library.txt usefrom IfW_FlowField.txt -typedef FlowField_IO SteadyInitInputType ReKi HWindSpeed - - - "Horizontal wind speed" m/s +#---------------------------------------------------------------------------------------------------------------------------------- +typedef InflowWind_IO WindFileDat character(1024) FileName - - - "Name of the windfile retrieved" - +typedef ^ ^ IntKi WindType - 0 - "Type of the windfile" - +typedef ^ ^ ReKi RefHt - - - "Reference height given in file" meters +typedef ^ ^ Logical RefHt_Set - - - "Reference height was given in file" - +typedef ^ ^ DbKi DT - - - "TimeStep of the wind file -- zero value for none" seconds +typedef ^ ^ IntKi NumTSteps - - - "Number of timesteps in the time range of wind file" - +typedef ^ ^ Logical ConstantDT - - - "Timesteps are the same throughout file" - +typedef ^ ^ ReKi TRange {2} - - "Time range of the wind file" seconds +typedef ^ ^ Logical TRange_Limited - - - "TRange limits strictly enforced" - +typedef ^ ^ ReKi YRange {2} - - "Range in y direction" meters +typedef ^ ^ Logical YRange_Limited - - - "YRange limits strictly enforced" - +typedef ^ ^ ReKi ZRange {2} - - "Range in z direction" meters +typedef ^ ^ Logical ZRange_Limited - - - "ZRange limits strictly enforced" - +typedef ^ ^ IntKi BinaryFormat - - - "Binary format identifier" - +typedef ^ ^ Logical IsBinary - - - "Windfile is a binary file" - +typedef ^ ^ ReKi TI {3} - - "Turbulence intensity (U,V,W)" - +typedef ^ ^ Logical TI_listed - - - "Turbulence intesity given in file" - +typedef ^ ^ ReKi MWS - - - "Approximate mean wind speed" - + +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ Steady_InitInputType ReKi HWindSpeed - - - "Horizontal wind speed" m/s typedef ^ ^ ReKi RefHt - - - "Reference height for horizontal wind speed" meters typedef ^ ^ ReKi PLExp - - - "Power law exponent" - -typedef ^ UniformInitInputType character(1024) WindFileName - - - "Name of the wind file to use" - +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ Uniform_InitInputType character(1024) WindFileName - - - "Name of the wind file to use" - typedef ^ ^ ReKi RefHt - - - "Reference height for horizontal wind speed" meters typedef ^ ^ ReKi RefLength - - - "Reference length for linear horizontal and vertical sheer" - typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians typedef ^ ^ logical UseInputFile - .true. - "Flag for toggling file based IO in wind type 2." - typedef ^ ^ FileInfoType PassedFileData - - - "Optional slot for wind type 2 data if file IO is not used." - -typedef ^ Grid3DInitInputType IntKi ScaleMethod - 0 - "Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation]" - +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ Grid3D_InitInputType IntKi ScaleMethod - 0 - "Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation]" - typedef ^ ^ ReKi SF 3 0 - "Turbulence scaling factor for each direction [ScaleMethod=1]" - typedef ^ ^ ReKi SigmaF 3 0 - "Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2]" - typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - @@ -33,72 +56,37 @@ typedef ^ ^ ReKi RefLength typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - typedef ^ ^ ReKi XOffset - 0 - "distance offset for FF wind files" m -typedef ^ TurbSimInitInputType character(1024) WindFileName - - - "Name of the wind file to use" - +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ TurbSim_InitInputType character(1024) WindFileName - - - "Name of the wind file to use" - -typedef ^ BladedInitInputType character(1024) WindFileName - - - "Root filename" - +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ Bladed_InitInputType character(1024) WindFileName - - - "Root filename" - +typedef ^ ^ IntKi WindType - - - "Whether this is native Bladed (needs wind profile and TI scaling) or not" - typedef ^ ^ logical NativeBladedFmt - - - "Whether this is native Bladed (needs wind profile and TI scaling) or not" - typedef ^ ^ logical TowerFileExist - - - "Tower file exists" - typedef ^ ^ IntKi TurbineID - 0 - "Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm)" - typedef ^ ^ logical FixedWindFileRootName - .false. - "Do the wind data files have a fixed (DEFAULT) file name? (used by FAST.Farm)" - -typedef ^ BladedInitOutputType ReKi TI {3} - - "Turbulence intensity given in the file" - -typedef ^ ^ ReKi PropagationDir - - - "Propogation direction from native Bladed format" degrees +typedef ^ Bladed_InitOutputType ReKi PropagationDir - - - "Propogation direction from native Bladed format" degrees typedef ^ ^ ReKi VFlowAngle - - - "Vertical flow angle from native Bladed format" degrees -typedef ^ HAWCInitInputType character(1024) WindFileName {3} - - "Name of the wind file to use" - +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ HAWC_InitInputType character(1024) WindFileName {3} - - "Name of the wind file to use" - typedef ^ ^ IntKi nx - 0 - "Number of grids in the x direction (in the 3 files above)" - typedef ^ ^ IntKi ny - 0 - "Number of grids in the y direction (in the 3 files above)" - typedef ^ ^ IntKi nz - 0 - "Number of grids in the z direction (in the 3 files above)" - typedef ^ ^ ReKi dx - 0 - "size of grids in the x direction (in the 3 files above)" - typedef ^ ^ ReKi dy - 0 - "size of grids in the y direction (in the 3 files above)" - typedef ^ ^ ReKi dz - 0 - "size of grids in the z direction (in the 3 files above)" - -typedef ^ ^ Grid3DInitInputType G3D - - - "Grid3D initialization input" - +typedef ^ ^ Grid3D_InitInputType G3D - - - "Grid3D initialization input" - -typedef ^ UserInitInputType SiKi Dummy - - - "User field initialization input dummy value" - +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ User_InitInputType SiKi Dummy - - - "User field initialization input dummy value" - -typedef ^ Grid4DInitInputType IntKi n 4 - - "number of grid points in the x, y, z, and t directions" - +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ Grid4D_InitInputType IntKi n 4 - - "number of grid points in the x, y, z, and t directions" - typedef ^ ^ ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s" typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" -typedef ^ PointsInitInputType IntKi Dummy - - - "Point field initialization input dummy value" - - -typedef ^ InitInputType IntKi WindType - 0 - "Type of the windfile" - -typedef ^ ^ IntKi SumFileUnit - - - "Unit number for the summary file (-1 for none). Provided by IfW." - -typedef ^ ^ ReKi PropagationDir - - - "Direction of wind propagation" radians -typedef ^ ^ ReKi VFlowAngle - - - "Vertical (upflow) angle" - -typedef ^ ^ logical VelInterpCubic - .false. - "Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7]" - -typedef ^ ^ logical OutputAccel - .false. - "Flag to indicate that wind acceleration should be output" - -typedef ^ ^ SteadyInitInputType Steady - - - "" - -typedef ^ ^ UniformInitInputType Uniform - - - "" - -typedef ^ ^ TurbSimInitInputType TurbSim - - - "" - -typedef ^ ^ BladedInitInputType Bladed - - - "" - -typedef ^ ^ HAWCInitInputType HAWC - - - "" - -typedef ^ ^ UserInitInputType User - - - "" - -typedef ^ ^ Grid4DInitInputType Grid4D - - - "" - -typedef ^ ^ PointsInitInputType Points - - - "" - - -typedef ^ WindFileDat character(1024) FileName - - - "Name of the windfile retrieved" - -typedef ^ ^ IntKi WindType - 0 - "Type of the windfile" - -typedef ^ ^ ReKi RefHt - - - "Reference height given in file" meters -typedef ^ ^ Logical RefHt_Set - - - "Reference height was given in file" - -typedef ^ ^ DbKi DT - - - "TimeStep of the wind file -- zero value for none" seconds -typedef ^ ^ IntKi NumTSteps - - - "Number of timesteps in the time range of wind file" - -typedef ^ ^ Logical ConstantDT - - - "Timesteps are the same throughout file" - -typedef ^ ^ ReKi TRange {2} - - "Time range of the wind file" seconds -typedef ^ ^ Logical TRange_Limited - - - "TRange limits strictly enforced" - -typedef ^ ^ ReKi YRange {2} - - "Range in y direction" meters -typedef ^ ^ Logical YRange_Limited - - - "YRange limits strictly enforced" - -typedef ^ ^ ReKi ZRange {2} - - "Range in z direction" meters -typedef ^ ^ Logical ZRange_Limited - - - "ZRange limits strictly enforced" - -typedef ^ ^ IntKi BinaryFormat - - - "Binary format identifier" - -typedef ^ ^ Logical IsBinary - - - "Windfile is a binary file" - -typedef ^ ^ ReKi TI {3} - - "Turbulence intensity (U,V,W)" - -typedef ^ ^ Logical TI_listed - - - "Turbulence intesity given in file" - -typedef ^ ^ ReKi MWS - - - "Approximate mean wind speed" - - -typedef ^ InitOutputType ProgDesc Ver - - - "Version information off FFWind submodule" - -typedef ^ ^ WindFileDat FileDat - - - "" - -typedef ^ ^ BladedInitOutputType Bladed - - - "" - - - - +#---------------------------------------------------------------------------------------------------------------------------------- +typedef ^ Points_InitInputType IntKi Dummy - - - "Point field initialization input dummy value" - diff --git a/modules/inflowwind/src/InflowWind_IO_Types.f90 b/modules/inflowwind/src/InflowWind_IO_Types.f90 new file mode 100644 index 0000000000..a486af7d63 --- /dev/null +++ b/modules/inflowwind/src/InflowWind_IO_Types.f90 @@ -0,0 +1,2209 @@ +!STARTOFREGISTRYGENERATEDFILE 'InflowWind_IO_Types.f90' +! +! WARNING This file is generated automatically by the FAST registry. +! Do not edit. Your changes to this file will be lost. +! +! FAST Registry +!********************************************************************************************************************************* +! InflowWind_IO_Types +!................................................................................................................................. +! This file is part of InflowWind_IO. +! +! Copyright (C) 2012-2016 National Renewable Energy Laboratory +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +! +! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. +! +!********************************************************************************************************************************* +!> This module contains the user-defined types needed in InflowWind_IO. It also contains copy, destroy, pack, and +!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. +MODULE InflowWind_IO_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE IfW_FlowField_Types +USE NWTC_Library +IMPLICIT NONE +! ========= WindFileDat ======= + TYPE, PUBLIC :: WindFileDat + character(1024) :: FileName !< Name of the windfile retrieved [-] + INTEGER(IntKi) :: WindType = 0 !< Type of the windfile [-] + REAL(ReKi) :: RefHt !< Reference height given in file [meters] + LOGICAL :: RefHt_Set !< Reference height was given in file [-] + REAL(DbKi) :: DT !< TimeStep of the wind file -- zero value for none [seconds] + INTEGER(IntKi) :: NumTSteps !< Number of timesteps in the time range of wind file [-] + LOGICAL :: ConstantDT !< Timesteps are the same throughout file [-] + REAL(ReKi) , DIMENSION(1:2) :: TRange !< Time range of the wind file [seconds] + LOGICAL :: TRange_Limited !< TRange limits strictly enforced [-] + REAL(ReKi) , DIMENSION(1:2) :: YRange !< Range in y direction [meters] + LOGICAL :: YRange_Limited !< YRange limits strictly enforced [-] + REAL(ReKi) , DIMENSION(1:2) :: ZRange !< Range in z direction [meters] + LOGICAL :: ZRange_Limited !< ZRange limits strictly enforced [-] + INTEGER(IntKi) :: BinaryFormat !< Binary format identifier [-] + LOGICAL :: IsBinary !< Windfile is a binary file [-] + REAL(ReKi) , DIMENSION(1:3) :: TI !< Turbulence intensity (U,V,W) [-] + LOGICAL :: TI_listed !< Turbulence intesity given in file [-] + REAL(ReKi) :: MWS !< Approximate mean wind speed [-] + END TYPE WindFileDat +! ======================= +! ========= Steady_InitInputType ======= + TYPE, PUBLIC :: Steady_InitInputType + REAL(ReKi) :: HWindSpeed !< Horizontal wind speed [m/s] + REAL(ReKi) :: RefHt !< Reference height for horizontal wind speed [meters] + REAL(ReKi) :: PLExp !< Power law exponent [-] + END TYPE Steady_InitInputType +! ======================= +! ========= Uniform_InitInputType ======= + TYPE, PUBLIC :: Uniform_InitInputType + character(1024) :: WindFileName !< Name of the wind file to use [-] + REAL(ReKi) :: RefHt !< Reference height for horizontal wind speed [meters] + REAL(ReKi) :: RefLength !< Reference length for linear horizontal and vertical sheer [-] + REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] + LOGICAL :: UseInputFile = .true. !< Flag for toggling file based IO in wind type 2. [-] + TYPE(FileInfoType) :: PassedFileData !< Optional slot for wind type 2 data if file IO is not used. [-] + END TYPE Uniform_InitInputType +! ======================= +! ========= Grid3D_InitInputType ======= + TYPE, PUBLIC :: Grid3D_InitInputType + INTEGER(IntKi) :: ScaleMethod = 0 !< Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation] [-] + REAL(ReKi) , DIMENSION(1:3) :: SF !< Turbulence scaling factor for each direction [ScaleMethod=1] [-] + REAL(ReKi) , DIMENSION(1:3) :: SigmaF !< Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2] [-] + INTEGER(IntKi) :: WindProfileType = -1 !< Wind profile type (0=constant;1=logarithmic;2=power law) [-] + REAL(ReKi) :: RefHt = 0 !< Reference (hub) height of the grid [meters] + REAL(ReKi) :: URef = 0 !< Mean u-component wind speed at the reference height [meters] + REAL(ReKi) :: PLExp = 0 !< Power law exponent (used for PL wind profile type only) [-] + REAL(ReKi) :: VLinShr = 0 !< Vertical linear wind shear coefficient (used for vertical linear wind profile type only) [-] + REAL(ReKi) :: HLinShr = 0 !< Horizontal linear wind shear coefficient (used for horizontal wind profile type only) [-] + REAL(ReKi) :: RefLength = 1 !< Reference (rotor) length of the grid (used for horizontal wind profile type only) [-] + REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] + REAL(ReKi) :: XOffset = 0 !< distance offset for FF wind files [m] + END TYPE Grid3D_InitInputType +! ======================= +! ========= TurbSim_InitInputType ======= + TYPE, PUBLIC :: TurbSim_InitInputType + character(1024) :: WindFileName !< Name of the wind file to use [-] + END TYPE TurbSim_InitInputType +! ======================= +! ========= Bladed_InitInputType ======= + TYPE, PUBLIC :: Bladed_InitInputType + character(1024) :: WindFileName !< Root filename [-] + INTEGER(IntKi) :: WindType !< Whether this is native Bladed (needs wind profile and TI scaling) or not [-] + LOGICAL :: NativeBladedFmt !< Whether this is native Bladed (needs wind profile and TI scaling) or not [-] + LOGICAL :: TowerFileExist !< Tower file exists [-] + INTEGER(IntKi) :: TurbineID = 0 !< Wind turbine ID number in the fixed (DEFAULT) file name when FixedWindFileRootName = .TRUE. (used by FAST.Farm) [-] + LOGICAL :: FixedWindFileRootName = .false. !< Do the wind data files have a fixed (DEFAULT) file name? (used by FAST.Farm) [-] + END TYPE Bladed_InitInputType +! ======================= +! ========= Bladed_InitOutputType ======= + TYPE, PUBLIC :: Bladed_InitOutputType + REAL(ReKi) :: PropagationDir !< Propogation direction from native Bladed format [degrees] + REAL(ReKi) :: VFlowAngle !< Vertical flow angle from native Bladed format [degrees] + END TYPE Bladed_InitOutputType +! ======================= +! ========= HAWC_InitInputType ======= + TYPE, PUBLIC :: HAWC_InitInputType + character(1024) , DIMENSION(1:3) :: WindFileName !< Name of the wind file to use [-] + INTEGER(IntKi) :: nx = 0 !< Number of grids in the x direction (in the 3 files above) [-] + INTEGER(IntKi) :: ny = 0 !< Number of grids in the y direction (in the 3 files above) [-] + INTEGER(IntKi) :: nz = 0 !< Number of grids in the z direction (in the 3 files above) [-] + REAL(ReKi) :: dx = 0 !< size of grids in the x direction (in the 3 files above) [-] + REAL(ReKi) :: dy = 0 !< size of grids in the y direction (in the 3 files above) [-] + REAL(ReKi) :: dz = 0 !< size of grids in the z direction (in the 3 files above) [-] + TYPE(Grid3D_InitInputType) :: G3D !< Grid3D initialization input [-] + END TYPE HAWC_InitInputType +! ======================= +! ========= User_InitInputType ======= + TYPE, PUBLIC :: User_InitInputType + REAL(SiKi) :: Dummy !< User field initialization input dummy value [-] + END TYPE User_InitInputType +! ======================= +! ========= Grid4D_InitInputType ======= + TYPE, PUBLIC :: Grid4D_InitInputType + INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of grid points in the x, y, z, and t directions [-] + REAL(ReKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s] + REAL(ReKi) , DIMENSION(1:3) :: pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:)) [m] + END TYPE Grid4D_InitInputType +! ======================= +! ========= Points_InitInputType ======= + TYPE, PUBLIC :: Points_InitInputType + INTEGER(IntKi) :: Dummy !< Point field initialization input dummy value [-] + END TYPE Points_InitInputType +! ======================= +CONTAINS + SUBROUTINE InflowWind_IO_CopyWindFileDat( SrcWindFileDatData, DstWindFileDatData, CtrlCode, ErrStat, ErrMsg ) + TYPE(WindFileDat), INTENT(IN) :: SrcWindFileDatData + TYPE(WindFileDat), INTENT(INOUT) :: DstWindFileDatData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyWindFileDat' +! + ErrStat = ErrID_None + ErrMsg = "" + DstWindFileDatData%FileName = SrcWindFileDatData%FileName + DstWindFileDatData%WindType = SrcWindFileDatData%WindType + DstWindFileDatData%RefHt = SrcWindFileDatData%RefHt + DstWindFileDatData%RefHt_Set = SrcWindFileDatData%RefHt_Set + DstWindFileDatData%DT = SrcWindFileDatData%DT + DstWindFileDatData%NumTSteps = SrcWindFileDatData%NumTSteps + DstWindFileDatData%ConstantDT = SrcWindFileDatData%ConstantDT + DstWindFileDatData%TRange = SrcWindFileDatData%TRange + DstWindFileDatData%TRange_Limited = SrcWindFileDatData%TRange_Limited + DstWindFileDatData%YRange = SrcWindFileDatData%YRange + DstWindFileDatData%YRange_Limited = SrcWindFileDatData%YRange_Limited + DstWindFileDatData%ZRange = SrcWindFileDatData%ZRange + DstWindFileDatData%ZRange_Limited = SrcWindFileDatData%ZRange_Limited + DstWindFileDatData%BinaryFormat = SrcWindFileDatData%BinaryFormat + DstWindFileDatData%IsBinary = SrcWindFileDatData%IsBinary + DstWindFileDatData%TI = SrcWindFileDatData%TI + DstWindFileDatData%TI_listed = SrcWindFileDatData%TI_listed + DstWindFileDatData%MWS = SrcWindFileDatData%MWS + END SUBROUTINE InflowWind_IO_CopyWindFileDat + + SUBROUTINE InflowWind_IO_DestroyWindFileDat( WindFileDatData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(WindFileDat), INTENT(INOUT) :: WindFileDatData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyWindFileDat' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE InflowWind_IO_DestroyWindFileDat + + SUBROUTINE InflowWind_IO_PackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(WindFileDat), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackWindFileDat' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%FileName) ! FileName + Int_BufSz = Int_BufSz + 1 ! WindType + Re_BufSz = Re_BufSz + 1 ! RefHt + Int_BufSz = Int_BufSz + 1 ! RefHt_Set + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! NumTSteps + Int_BufSz = Int_BufSz + 1 ! ConstantDT + Re_BufSz = Re_BufSz + SIZE(InData%TRange) ! TRange + Int_BufSz = Int_BufSz + 1 ! TRange_Limited + Re_BufSz = Re_BufSz + SIZE(InData%YRange) ! YRange + Int_BufSz = Int_BufSz + 1 ! YRange_Limited + Re_BufSz = Re_BufSz + SIZE(InData%ZRange) ! ZRange + Int_BufSz = Int_BufSz + 1 ! ZRange_Limited + Int_BufSz = Int_BufSz + 1 ! BinaryFormat + Int_BufSz = Int_BufSz + 1 ! IsBinary + Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI + Int_BufSz = Int_BufSz + 1 ! TI_listed + Re_BufSz = Re_BufSz + 1 ! MWS + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%FileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%FileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%WindType + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefHt + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%RefHt_Set, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DbKiBuf(Db_Xferred) = InData%DT + Db_Xferred = Db_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumTSteps + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%ConstantDT, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%TRange,1), UBOUND(InData%TRange,1) + ReKiBuf(Re_Xferred) = InData%TRange(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%TRange_Limited, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%YRange,1), UBOUND(InData%YRange,1) + ReKiBuf(Re_Xferred) = InData%YRange(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%YRange_Limited, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%ZRange,1), UBOUND(InData%ZRange,1) + ReKiBuf(Re_Xferred) = InData%ZRange(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%ZRange_Limited, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BinaryFormat + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%IsBinary, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%TI,1), UBOUND(InData%TI,1) + ReKiBuf(Re_Xferred) = InData%TI(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = TRANSFER(InData%TI_listed, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%MWS + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_PackWindFileDat + + SUBROUTINE InflowWind_IO_UnPackWindFileDat( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(WindFileDat), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackWindFileDat' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%FileName) + OutData%FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%WindType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefHt_Set = TRANSFER(IntKiBuf(Int_Xferred), OutData%RefHt_Set) + Int_Xferred = Int_Xferred + 1 + OutData%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + OutData%NumTSteps = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ConstantDT = TRANSFER(IntKiBuf(Int_Xferred), OutData%ConstantDT) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%TRange,1) + i1_u = UBOUND(OutData%TRange,1) + DO i1 = LBOUND(OutData%TRange,1), UBOUND(OutData%TRange,1) + OutData%TRange(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%TRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%TRange_Limited) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%YRange,1) + i1_u = UBOUND(OutData%YRange,1) + DO i1 = LBOUND(OutData%YRange,1), UBOUND(OutData%YRange,1) + OutData%YRange(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%YRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%YRange_Limited) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%ZRange,1) + i1_u = UBOUND(OutData%ZRange,1) + DO i1 = LBOUND(OutData%ZRange,1), UBOUND(OutData%ZRange,1) + OutData%ZRange(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%ZRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%ZRange_Limited) + Int_Xferred = Int_Xferred + 1 + OutData%BinaryFormat = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%IsBinary = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsBinary) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%TI,1) + i1_u = UBOUND(OutData%TI,1) + DO i1 = LBOUND(OutData%TI,1), UBOUND(OutData%TI,1) + OutData%TI(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%TI_listed = TRANSFER(IntKiBuf(Int_Xferred), OutData%TI_listed) + Int_Xferred = Int_Xferred + 1 + OutData%MWS = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_UnPackWindFileDat + + SUBROUTINE InflowWind_IO_CopySteady_InitInputType( SrcSteady_InitInputTypeData, DstSteady_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Steady_InitInputType), INTENT(IN) :: SrcSteady_InitInputTypeData + TYPE(Steady_InitInputType), INTENT(INOUT) :: DstSteady_InitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopySteady_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstSteady_InitInputTypeData%HWindSpeed = SrcSteady_InitInputTypeData%HWindSpeed + DstSteady_InitInputTypeData%RefHt = SrcSteady_InitInputTypeData%RefHt + DstSteady_InitInputTypeData%PLExp = SrcSteady_InitInputTypeData%PLExp + END SUBROUTINE InflowWind_IO_CopySteady_InitInputType + + SUBROUTINE InflowWind_IO_DestroySteady_InitInputType( Steady_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Steady_InitInputType), INTENT(INOUT) :: Steady_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroySteady_InitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE InflowWind_IO_DestroySteady_InitInputType + + SUBROUTINE InflowWind_IO_PackSteady_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Steady_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackSteady_InitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! HWindSpeed + Re_BufSz = Re_BufSz + 1 ! RefHt + Re_BufSz = Re_BufSz + 1 ! PLExp + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%HWindSpeed + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PLExp + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_PackSteady_InitInputType + + SUBROUTINE InflowWind_IO_UnPackSteady_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Steady_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackSteady_InitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%HWindSpeed = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PLExp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_UnPackSteady_InitInputType + + SUBROUTINE InflowWind_IO_CopyUniform_InitInputType( SrcUniform_InitInputTypeData, DstUniform_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Uniform_InitInputType), INTENT(IN) :: SrcUniform_InitInputTypeData + TYPE(Uniform_InitInputType), INTENT(INOUT) :: DstUniform_InitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyUniform_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUniform_InitInputTypeData%WindFileName = SrcUniform_InitInputTypeData%WindFileName + DstUniform_InitInputTypeData%RefHt = SrcUniform_InitInputTypeData%RefHt + DstUniform_InitInputTypeData%RefLength = SrcUniform_InitInputTypeData%RefLength + DstUniform_InitInputTypeData%PropagationDir = SrcUniform_InitInputTypeData%PropagationDir + DstUniform_InitInputTypeData%UseInputFile = SrcUniform_InitInputTypeData%UseInputFile + CALL NWTC_Library_Copyfileinfotype( SrcUniform_InitInputTypeData%PassedFileData, DstUniform_InitInputTypeData%PassedFileData, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE InflowWind_IO_CopyUniform_InitInputType + + SUBROUTINE InflowWind_IO_DestroyUniform_InitInputType( Uniform_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Uniform_InitInputType), INTENT(INOUT) :: Uniform_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyUniform_InitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + CALL NWTC_Library_Destroyfileinfotype( Uniform_InitInputTypeData%PassedFileData, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END SUBROUTINE InflowWind_IO_DestroyUniform_InitInputType + + SUBROUTINE InflowWind_IO_PackUniform_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Uniform_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackUniform_InitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName + Re_BufSz = Re_BufSz + 1 ! RefHt + Re_BufSz = Re_BufSz + 1 ! RefLength + Re_BufSz = Re_BufSz + 1 ! PropagationDir + Int_BufSz = Int_BufSz + 1 ! UseInputFile + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PassedFileData: size of buffers for each call to pack subtype + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedFileData, ErrStat2, ErrMsg2, .TRUE. ) ! PassedFileData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PassedFileData + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PassedFileData + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PassedFileData + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%WindFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + ReKiBuf(Re_Xferred) = InData%RefHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PropagationDir + Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%UseInputFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedFileData, ErrStat2, ErrMsg2, OnlySize ) ! PassedFileData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END SUBROUTINE InflowWind_IO_PackUniform_InitInputType + + SUBROUTINE InflowWind_IO_UnPackUniform_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Uniform_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackUniform_InitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%WindFileName) + OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PropagationDir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%UseInputFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%UseInputFile) + Int_Xferred = Int_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL NWTC_Library_Unpackfileinfotype( Re_Buf, Db_Buf, Int_Buf, OutData%PassedFileData, ErrStat2, ErrMsg2 ) ! PassedFileData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END SUBROUTINE InflowWind_IO_UnPackUniform_InitInputType + + SUBROUTINE InflowWind_IO_CopyGrid3D_InitInputType( SrcGrid3D_InitInputTypeData, DstGrid3D_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Grid3D_InitInputType), INTENT(IN) :: SrcGrid3D_InitInputTypeData + TYPE(Grid3D_InitInputType), INTENT(INOUT) :: DstGrid3D_InitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyGrid3D_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstGrid3D_InitInputTypeData%ScaleMethod = SrcGrid3D_InitInputTypeData%ScaleMethod + DstGrid3D_InitInputTypeData%SF = SrcGrid3D_InitInputTypeData%SF + DstGrid3D_InitInputTypeData%SigmaF = SrcGrid3D_InitInputTypeData%SigmaF + DstGrid3D_InitInputTypeData%WindProfileType = SrcGrid3D_InitInputTypeData%WindProfileType + DstGrid3D_InitInputTypeData%RefHt = SrcGrid3D_InitInputTypeData%RefHt + DstGrid3D_InitInputTypeData%URef = SrcGrid3D_InitInputTypeData%URef + DstGrid3D_InitInputTypeData%PLExp = SrcGrid3D_InitInputTypeData%PLExp + DstGrid3D_InitInputTypeData%VLinShr = SrcGrid3D_InitInputTypeData%VLinShr + DstGrid3D_InitInputTypeData%HLinShr = SrcGrid3D_InitInputTypeData%HLinShr + DstGrid3D_InitInputTypeData%RefLength = SrcGrid3D_InitInputTypeData%RefLength + DstGrid3D_InitInputTypeData%Z0 = SrcGrid3D_InitInputTypeData%Z0 + DstGrid3D_InitInputTypeData%XOffset = SrcGrid3D_InitInputTypeData%XOffset + END SUBROUTINE InflowWind_IO_CopyGrid3D_InitInputType + + SUBROUTINE InflowWind_IO_DestroyGrid3D_InitInputType( Grid3D_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Grid3D_InitInputType), INTENT(INOUT) :: Grid3D_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyGrid3D_InitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE InflowWind_IO_DestroyGrid3D_InitInputType + + SUBROUTINE InflowWind_IO_PackGrid3D_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Grid3D_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackGrid3D_InitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! ScaleMethod + Re_BufSz = Re_BufSz + SIZE(InData%SF) ! SF + Re_BufSz = Re_BufSz + SIZE(InData%SigmaF) ! SigmaF + Int_BufSz = Int_BufSz + 1 ! WindProfileType + Re_BufSz = Re_BufSz + 1 ! RefHt + Re_BufSz = Re_BufSz + 1 ! URef + Re_BufSz = Re_BufSz + 1 ! PLExp + Re_BufSz = Re_BufSz + 1 ! VLinShr + Re_BufSz = Re_BufSz + 1 ! HLinShr + Re_BufSz = Re_BufSz + 1 ! RefLength + Re_BufSz = Re_BufSz + 1 ! Z0 + Re_BufSz = Re_BufSz + 1 ! XOffset + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%ScaleMethod + Int_Xferred = Int_Xferred + 1 + DO i1 = LBOUND(InData%SF,1), UBOUND(InData%SF,1) + ReKiBuf(Re_Xferred) = InData%SF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%SigmaF,1), UBOUND(InData%SigmaF,1) + ReKiBuf(Re_Xferred) = InData%SigmaF(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%WindProfileType + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefHt + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%URef + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%PLExp + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VLinShr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%HLinShr + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%RefLength + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%Z0 + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%XOffset + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_PackGrid3D_InitInputType + + SUBROUTINE InflowWind_IO_UnPackGrid3D_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Grid3D_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackGrid3D_InitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%ScaleMethod = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + i1_l = LBOUND(OutData%SF,1) + i1_u = UBOUND(OutData%SF,1) + DO i1 = LBOUND(OutData%SF,1), UBOUND(OutData%SF,1) + OutData%SF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%SigmaF,1) + i1_u = UBOUND(OutData%SigmaF,1) + DO i1 = LBOUND(OutData%SigmaF,1), UBOUND(OutData%SigmaF,1) + OutData%SigmaF(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%WindProfileType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%RefHt = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%URef = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%PLExp = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VLinShr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%HLinShr = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%RefLength = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%Z0 = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%XOffset = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_UnPackGrid3D_InitInputType + + SUBROUTINE InflowWind_IO_CopyTurbSim_InitInputType( SrcTurbSim_InitInputTypeData, DstTurbSim_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(TurbSim_InitInputType), INTENT(IN) :: SrcTurbSim_InitInputTypeData + TYPE(TurbSim_InitInputType), INTENT(INOUT) :: DstTurbSim_InitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyTurbSim_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstTurbSim_InitInputTypeData%WindFileName = SrcTurbSim_InitInputTypeData%WindFileName + END SUBROUTINE InflowWind_IO_CopyTurbSim_InitInputType + + SUBROUTINE InflowWind_IO_DestroyTurbSim_InitInputType( TurbSim_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(TurbSim_InitInputType), INTENT(INOUT) :: TurbSim_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyTurbSim_InitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE InflowWind_IO_DestroyTurbSim_InitInputType + + SUBROUTINE InflowWind_IO_PackTurbSim_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(TurbSim_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackTurbSim_InitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%WindFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE InflowWind_IO_PackTurbSim_InitInputType + + SUBROUTINE InflowWind_IO_UnPackTurbSim_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(TurbSim_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackTurbSim_InitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%WindFileName) + OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END SUBROUTINE InflowWind_IO_UnPackTurbSim_InitInputType + + SUBROUTINE InflowWind_IO_CopyBladed_InitInputType( SrcBladed_InitInputTypeData, DstBladed_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Bladed_InitInputType), INTENT(IN) :: SrcBladed_InitInputTypeData + TYPE(Bladed_InitInputType), INTENT(INOUT) :: DstBladed_InitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyBladed_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBladed_InitInputTypeData%WindFileName = SrcBladed_InitInputTypeData%WindFileName + DstBladed_InitInputTypeData%WindType = SrcBladed_InitInputTypeData%WindType + DstBladed_InitInputTypeData%NativeBladedFmt = SrcBladed_InitInputTypeData%NativeBladedFmt + DstBladed_InitInputTypeData%TowerFileExist = SrcBladed_InitInputTypeData%TowerFileExist + DstBladed_InitInputTypeData%TurbineID = SrcBladed_InitInputTypeData%TurbineID + DstBladed_InitInputTypeData%FixedWindFileRootName = SrcBladed_InitInputTypeData%FixedWindFileRootName + END SUBROUTINE InflowWind_IO_CopyBladed_InitInputType + + SUBROUTINE InflowWind_IO_DestroyBladed_InitInputType( Bladed_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Bladed_InitInputType), INTENT(INOUT) :: Bladed_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyBladed_InitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE InflowWind_IO_DestroyBladed_InitInputType + + SUBROUTINE InflowWind_IO_PackBladed_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Bladed_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackBladed_InitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1*LEN(InData%WindFileName) ! WindFileName + Int_BufSz = Int_BufSz + 1 ! WindType + Int_BufSz = Int_BufSz + 1 ! NativeBladedFmt + Int_BufSz = Int_BufSz + 1 ! TowerFileExist + Int_BufSz = Int_BufSz + 1 ! TurbineID + Int_BufSz = Int_BufSz + 1 ! FixedWindFileRootName + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO I = 1, LEN(InData%WindFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + IntKiBuf(Int_Xferred) = InData%WindType + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%NativeBladedFmt, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%TowerFileExist, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%TurbineID + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%FixedWindFileRootName, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE InflowWind_IO_PackBladed_InitInputType + + SUBROUTINE InflowWind_IO_UnPackBladed_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Bladed_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackBladed_InitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + DO I = 1, LEN(OutData%WindFileName) + OutData%WindFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%WindType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%NativeBladedFmt = TRANSFER(IntKiBuf(Int_Xferred), OutData%NativeBladedFmt) + Int_Xferred = Int_Xferred + 1 + OutData%TowerFileExist = TRANSFER(IntKiBuf(Int_Xferred), OutData%TowerFileExist) + Int_Xferred = Int_Xferred + 1 + OutData%TurbineID = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%FixedWindFileRootName = TRANSFER(IntKiBuf(Int_Xferred), OutData%FixedWindFileRootName) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE InflowWind_IO_UnPackBladed_InitInputType + + SUBROUTINE InflowWind_IO_CopyBladed_InitOutputType( SrcBladed_InitOutputTypeData, DstBladed_InitOutputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Bladed_InitOutputType), INTENT(IN) :: SrcBladed_InitOutputTypeData + TYPE(Bladed_InitOutputType), INTENT(INOUT) :: DstBladed_InitOutputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyBladed_InitOutputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstBladed_InitOutputTypeData%PropagationDir = SrcBladed_InitOutputTypeData%PropagationDir + DstBladed_InitOutputTypeData%VFlowAngle = SrcBladed_InitOutputTypeData%VFlowAngle + END SUBROUTINE InflowWind_IO_CopyBladed_InitOutputType + + SUBROUTINE InflowWind_IO_DestroyBladed_InitOutputType( Bladed_InitOutputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Bladed_InitOutputType), INTENT(INOUT) :: Bladed_InitOutputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyBladed_InitOutputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE InflowWind_IO_DestroyBladed_InitOutputType + + SUBROUTINE InflowWind_IO_PackBladed_InitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Bladed_InitOutputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackBladed_InitOutputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! PropagationDir + Re_BufSz = Re_BufSz + 1 ! VFlowAngle + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%PropagationDir + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%VFlowAngle + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_PackBladed_InitOutputType + + SUBROUTINE InflowWind_IO_UnPackBladed_InitOutputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Bladed_InitOutputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackBladed_InitOutputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%PropagationDir = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%VFlowAngle = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_UnPackBladed_InitOutputType + + SUBROUTINE InflowWind_IO_CopyHAWC_InitInputType( SrcHAWC_InitInputTypeData, DstHAWC_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(HAWC_InitInputType), INTENT(IN) :: SrcHAWC_InitInputTypeData + TYPE(HAWC_InitInputType), INTENT(INOUT) :: DstHAWC_InitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyHAWC_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstHAWC_InitInputTypeData%WindFileName = SrcHAWC_InitInputTypeData%WindFileName + DstHAWC_InitInputTypeData%nx = SrcHAWC_InitInputTypeData%nx + DstHAWC_InitInputTypeData%ny = SrcHAWC_InitInputTypeData%ny + DstHAWC_InitInputTypeData%nz = SrcHAWC_InitInputTypeData%nz + DstHAWC_InitInputTypeData%dx = SrcHAWC_InitInputTypeData%dx + DstHAWC_InitInputTypeData%dy = SrcHAWC_InitInputTypeData%dy + DstHAWC_InitInputTypeData%dz = SrcHAWC_InitInputTypeData%dz + CALL InflowWind_IO_Copygrid3d_initinputtype( SrcHAWC_InitInputTypeData%G3D, DstHAWC_InitInputTypeData%G3D, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN + END SUBROUTINE InflowWind_IO_CopyHAWC_InitInputType + + SUBROUTINE InflowWind_IO_DestroyHAWC_InitInputType( HAWC_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(HAWC_InitInputType), INTENT(INOUT) :: HAWC_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyHAWC_InitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + CALL InflowWind_IO_Destroygrid3d_initinputtype( HAWC_InitInputTypeData%G3D, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END SUBROUTINE InflowWind_IO_DestroyHAWC_InitInputType + + SUBROUTINE InflowWind_IO_PackHAWC_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(HAWC_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackHAWC_InitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + SIZE(InData%WindFileName)*LEN(InData%WindFileName) ! WindFileName + Int_BufSz = Int_BufSz + 1 ! nx + Int_BufSz = Int_BufSz + 1 ! ny + Int_BufSz = Int_BufSz + 1 ! nz + Re_BufSz = Re_BufSz + 1 ! dx + Re_BufSz = Re_BufSz + 1 ! dy + Re_BufSz = Re_BufSz + 1 ! dz + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! G3D: size of buffers for each call to pack subtype + CALL InflowWind_IO_Packgrid3d_initinputtype( Re_Buf, Db_Buf, Int_Buf, InData%G3D, ErrStat2, ErrMsg2, .TRUE. ) ! G3D + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! G3D + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! G3D + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! G3D + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO i1 = LBOUND(InData%WindFileName,1), UBOUND(InData%WindFileName,1) + DO I = 1, LEN(InData%WindFileName) + IntKiBuf(Int_Xferred) = ICHAR(InData%WindFileName(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + IntKiBuf(Int_Xferred) = InData%nx + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%ny + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%nz + Int_Xferred = Int_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dx + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dy + Re_Xferred = Re_Xferred + 1 + ReKiBuf(Re_Xferred) = InData%dz + Re_Xferred = Re_Xferred + 1 + CALL InflowWind_IO_Packgrid3d_initinputtype( Re_Buf, Db_Buf, Int_Buf, InData%G3D, ErrStat2, ErrMsg2, OnlySize ) ! G3D + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + END SUBROUTINE InflowWind_IO_PackHAWC_InitInputType + + SUBROUTINE InflowWind_IO_UnPackHAWC_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(HAWC_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackHAWC_InitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + i1_l = LBOUND(OutData%WindFileName,1) + i1_u = UBOUND(OutData%WindFileName,1) + DO i1 = LBOUND(OutData%WindFileName,1), UBOUND(OutData%WindFileName,1) + DO I = 1, LEN(OutData%WindFileName) + OutData%WindFileName(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + OutData%nx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%ny = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%nz = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%dx = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dy = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + OutData%dz = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL InflowWind_IO_Unpackgrid3d_initinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%G3D, ErrStat2, ErrMsg2 ) ! G3D + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + END SUBROUTINE InflowWind_IO_UnPackHAWC_InitInputType + + SUBROUTINE InflowWind_IO_CopyUser_InitInputType( SrcUser_InitInputTypeData, DstUser_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(User_InitInputType), INTENT(IN) :: SrcUser_InitInputTypeData + TYPE(User_InitInputType), INTENT(INOUT) :: DstUser_InitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyUser_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstUser_InitInputTypeData%Dummy = SrcUser_InitInputTypeData%Dummy + END SUBROUTINE InflowWind_IO_CopyUser_InitInputType + + SUBROUTINE InflowWind_IO_DestroyUser_InitInputType( User_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(User_InitInputType), INTENT(INOUT) :: User_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyUser_InitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE InflowWind_IO_DestroyUser_InitInputType + + SUBROUTINE InflowWind_IO_PackUser_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(User_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackUser_InitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Re_BufSz = Re_BufSz + 1 ! Dummy + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + ReKiBuf(Re_Xferred) = InData%Dummy + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_PackUser_InitInputType + + SUBROUTINE InflowWind_IO_UnPackUser_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(User_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackUser_InitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%Dummy = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END SUBROUTINE InflowWind_IO_UnPackUser_InitInputType + + SUBROUTINE InflowWind_IO_CopyGrid4D_InitInputType( SrcGrid4D_InitInputTypeData, DstGrid4D_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Grid4D_InitInputType), INTENT(IN) :: SrcGrid4D_InitInputTypeData + TYPE(Grid4D_InitInputType), INTENT(INOUT) :: DstGrid4D_InitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyGrid4D_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstGrid4D_InitInputTypeData%n = SrcGrid4D_InitInputTypeData%n + DstGrid4D_InitInputTypeData%delta = SrcGrid4D_InitInputTypeData%delta + DstGrid4D_InitInputTypeData%pZero = SrcGrid4D_InitInputTypeData%pZero + END SUBROUTINE InflowWind_IO_CopyGrid4D_InitInputType + + SUBROUTINE InflowWind_IO_DestroyGrid4D_InitInputType( Grid4D_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Grid4D_InitInputType), INTENT(INOUT) :: Grid4D_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyGrid4D_InitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE InflowWind_IO_DestroyGrid4D_InitInputType + + SUBROUTINE InflowWind_IO_PackGrid4D_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Grid4D_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackGrid4D_InitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + SIZE(InData%n) ! n + Re_BufSz = Re_BufSz + SIZE(InData%delta) ! delta + Re_BufSz = Re_BufSz + SIZE(InData%pZero) ! pZero + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + DO i1 = LBOUND(InData%n,1), UBOUND(InData%n,1) + IntKiBuf(Int_Xferred) = InData%n(i1) + Int_Xferred = Int_Xferred + 1 + END DO + DO i1 = LBOUND(InData%delta,1), UBOUND(InData%delta,1) + ReKiBuf(Re_Xferred) = InData%delta(i1) + Re_Xferred = Re_Xferred + 1 + END DO + DO i1 = LBOUND(InData%pZero,1), UBOUND(InData%pZero,1) + ReKiBuf(Re_Xferred) = InData%pZero(i1) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE InflowWind_IO_PackGrid4D_InitInputType + + SUBROUTINE InflowWind_IO_UnPackGrid4D_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Grid4D_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackGrid4D_InitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + i1_l = LBOUND(OutData%n,1) + i1_u = UBOUND(OutData%n,1) + DO i1 = LBOUND(OutData%n,1), UBOUND(OutData%n,1) + OutData%n(i1) = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END DO + i1_l = LBOUND(OutData%delta,1) + i1_u = UBOUND(OutData%delta,1) + DO i1 = LBOUND(OutData%delta,1), UBOUND(OutData%delta,1) + OutData%delta(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + i1_l = LBOUND(OutData%pZero,1) + i1_u = UBOUND(OutData%pZero,1) + DO i1 = LBOUND(OutData%pZero,1), UBOUND(OutData%pZero,1) + OutData%pZero(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END SUBROUTINE InflowWind_IO_UnPackGrid4D_InitInputType + + SUBROUTINE InflowWind_IO_CopyPoints_InitInputType( SrcPoints_InitInputTypeData, DstPoints_InitInputTypeData, CtrlCode, ErrStat, ErrMsg ) + TYPE(Points_InitInputType), INTENT(IN) :: SrcPoints_InitInputTypeData + TYPE(Points_InitInputType), INTENT(INOUT) :: DstPoints_InitInputTypeData + INTEGER(IntKi), INTENT(IN ) :: CtrlCode + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg +! Local + INTEGER(IntKi) :: i,j,k + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_CopyPoints_InitInputType' +! + ErrStat = ErrID_None + ErrMsg = "" + DstPoints_InitInputTypeData%Dummy = SrcPoints_InitInputTypeData%Dummy + END SUBROUTINE InflowWind_IO_CopyPoints_InitInputType + + SUBROUTINE InflowWind_IO_DestroyPoints_InitInputType( Points_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) + TYPE(Points_InitInputType), INTENT(INOUT) :: Points_InitInputTypeData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers + + INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 + LOGICAL :: DEALLOCATEpointers_local + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_DestroyPoints_InitInputType' + + ErrStat = ErrID_None + ErrMsg = "" + + IF (PRESENT(DEALLOCATEpointers)) THEN + DEALLOCATEpointers_local = DEALLOCATEpointers + ELSE + DEALLOCATEpointers_local = .true. + END IF + + END SUBROUTINE InflowWind_IO_DestroyPoints_InitInputType + + SUBROUTINE InflowWind_IO_PackPoints_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(Points_InitInputType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_PackPoints_InitInputType' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! Dummy + IF ( Re_BufSz .GT. 0 ) THEN + ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + + IntKiBuf(Int_Xferred) = InData%Dummy + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE InflowWind_IO_PackPoints_InitInputType + + SUBROUTINE InflowWind_IO_UnPackPoints_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(Points_InitInputType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_IO_UnPackPoints_InitInputType' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + OutData%Dummy = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + END SUBROUTINE InflowWind_IO_UnPackPoints_InitInputType + +END MODULE InflowWind_IO_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index 969651e2b2..b97fd29a68 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -19,22 +19,9 @@ !********************************************************************************************************************************** MODULE InflowWind_Subs - USE InflowWind_Types - USE NWTC_Library - - !------------------------------------------------------------------------------------------------- - ! The included wind modules (TYPES modules are inherited from InflowWind_Types, so not specified here again.) - !------------------------------------------------------------------------------------------------- - USE IfW_UniformWind ! uniform wind files (text files) - USE IfW_TSFFWind ! TurbSim style full-field binary wind files - USE IfW_BladedFFWind ! Bladed style full-field binary wind files - USE IfW_UserWind ! User-defined wind module - USE IfW_HAWCWind ! full-field binary wind files in HAWC format - USE IfW_4Dext ! 4D wind field from external source (e.g., FAST.Farm) - -!!! USE FDWind ! 4-D binary wind files -!!! USE CTWind ! coherent turbulence from KH billow - binary file superimposed on another wind type - + USE InflowWind_Types + USE NWTC_Library + USE IfW_FlowField, only: IfW_FlowField_GetVelAcc IMPLICIT NONE @@ -863,19 +850,15 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM !----------------------------------------------------------------- ! Copy over the general information that applies to everything !----------------------------------------------------------------- - p%CTTS_Flag = .FALSE. ! Copy the WindType over. - p%WindType = InputFileData%WindType - ! Convert the PropagationDir to radians and store this. For simplicity, we will shift it to be between -pi and pi + p%FlowField%PropagationDir = D2R * InputFileData%PropagationDir + CALL MPi2Pi( p%FlowField%PropagationDir ) ! Shift if necessary so that the value is between -pi and pi - p%PropagationDir = D2R * InputFileData%PropagationDir - CALL MPi2Pi( p%PropagationDir ) ! Shift if necessary so that the value is between -pi and pi - - p%VFlowAngle = D2R * InputFileData%VFlowAngle + p%FlowField%VFlowAngle = D2R * InputFileData%VFlowAngle ! Copy over the list of wind coordinates. Move the arrays to the new one. p%NWindVel = InputFileData%NWindVel @@ -1012,9 +995,15 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM ! Create the rotation matrices -- rotate from XYZ to X'Y'Z' (wind aligned along X) coordinates ! Included in this rotation is the wind upflow (inclination) angle (rotation about Y axis) - p%RotToWind(1,:) = (/ COS(-p%VFlowAngle) * COS(-p%PropagationDir), COS(-p%VFlowAngle) * SIN(-p%PropagationDir), -SIN(-p%VFlowAngle) /) - p%RotToWind(2,:) = (/ -SIN(-p%PropagationDir), COS(-p%PropagationDir), 0.0_ReKi /) - p%RotToWind(3,:) = (/ SIN(-p%VFlowAngle) * COS(-p%PropagationDir), SIN(-p%VFlowAngle) * SIN(-p%PropagationDir), COS(-p%VFlowAngle) /) + p%FlowField%RotToWind(1,:) = [ COS(-p%FlowField%VFlowAngle) * COS(-p%FlowField%PropagationDir), & + COS(-p%FlowField%VFlowAngle) * SIN(-p%FlowField%PropagationDir), & + -SIN(-p%FlowField%VFlowAngle) ] + p%FlowField%RotToWind(2,:) = [ -SIN(-p%FlowField%PropagationDir), & + COS(-p%FlowField%PropagationDir), & + 0.0_ReKi ] + p%FlowField%RotToWind(3,:) = [ SIN(-p%FlowField%VFlowAngle) * COS(-p%FlowField%PropagationDir), & + SIN(-p%FlowField%VFlowAngle) * SIN(-p%FlowField%PropagationDir), & + COS(-p%FlowField%VFlowAngle) ] ! Create the rotation matrices -- rotate from X'Y'Z' (wind aligned along X) to global XYZ coordinates: this is the same as a ! rotation about the (positive) upflow angle multiplied by a rotation about the (positive) wind direction: @@ -1022,7 +1011,7 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM ! loal wind = R( -p%VFlowAngle) * R (-p%PropagationDir) [global wind] ! = R^T(p%VFlowAngle) * R^T(p%PropagationDir) [global wind] ! = (R(p%PropagationDir) * R(p%VFlowAngle))^T [global wind] - p%RotFromWind = TRANSPOSE(p%RotToWind) + p%FlowField%RotFromWind = TRANSPOSE(p%FlowField%RotToWind) ! Create the array used for holding the rotated list of WindViXYZ coordinates in the wind reference frame, and populate it CALL AllocAry( p%WindViXYZprime, 3, p%NWindVel, 'Array for WindViXYZ coordinates in the wind reference frame', & @@ -1035,10 +1024,10 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM p%WindViXYZprime = 0.0_ReKi ! set the output points. Note rotation is about the hub height at [0 0 H]. See InflowWind_SetParameters for details. DO I = 1,p%NWindVel - p%WindViXYZprime(:,I) = MATMUL( p%RotToWind, (p%WindViXYZ(:,I) - p%RefPosition )) + p%RefPosition + p%WindViXYZprime(:,I) = MATMUL( p%FlowField%RotToWind, (p%WindViXYZ(:,I) - p%RefPosition )) + p%RefPosition ENDDO - p%RotateWindBox = .not. (EqualRealNos (p%PropagationDir, 0.0_ReKi) .AND. EqualRealNos (p%VFlowAngle, 0.0_ReKi)) + p%FlowField%RotateWindBox = .not. (EqualRealNos (p%FlowField%PropagationDir, 0.0_ReKi) .AND. EqualRealNos (p%FlowField%VFlowAngle, 0.0_ReKi)) END SUBROUTINE InflowWind_SetParameters @@ -1458,298 +1447,41 @@ END SUBROUTINE InflowWind_CloseSumFile SUBROUTINE CalculateOutput( Time, InputData, p, x, xd, z, OtherStates, y, m, FillWrOut, ErrStat, ErrMsg ) - USE IfW_FlowField, only: IfW_FlowField_GetVelAcc - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="CalcOutput" - - - ! Inputs / Outputs - - REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds - TYPE(InflowWind_InputType), INTENT(IN ) :: InputData !< Inputs at Time - TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time - TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time - TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time - TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherStates !< Other states at Time - TYPE(InflowWind_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (IN for mesh reasons and data allocation) - TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables - LOGICAL, INTENT(IN ) :: FillWrOut !< Flag to determine if we need to fill WriteOutput values - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - REAL(ReKi), ALLOCATABLE :: PositionXYZprime(:,:) !< PositionXYZ array in the prime (wind) coordinates - - INTEGER(IntKi) :: I !< Generic counters - - - ! Temporary variables for error handling - INTEGER(IntKi) :: TmpErrStat - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - - - - ! Initialize ErrStat - ErrStat = ErrID_None - ErrMsg = "" - - !----------------------------------------------------------------------- - ! Points coordinate transforms from to global to wind file coordinates - !----------------------------------------------------------------------- - - if (p%FlowField%Enabled) then - CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, InputData%PositionXYZ, & - y%VelocityUVW, y%AccelUVW, TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - ! Call IfW_UniformWind_CalcOutput again in order to get the values needed for the OutList -- note that we do not report errors from this - IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, p%WindViXYZ, & - m%WindViUVW, m%WindAiUVW, TmpErrStat, TmpErrMsg) - ENDIF - return - end if - - - !----------------------------------------------------------------------- - ! Points coordinate transforms from to global to wind file coordinates - !----------------------------------------------------------------------- - - - !> Make a copy of the InputData%PositionXYZ coordinates with the applied rotation matrix... - !! This copy is made because if we translate it to the prime coordinates, then back again, we - !! may shift the points by some small amount of machine error, and we don't want to do that. - !! - !! Note that we allocate this at every call to CalcOutput. The reason is that we may call CalcOutput - !! multiple times in each timestep with different sized InputData%PositionXYZ arrays (if calling for LIDAR - !! data etc). We don't really want to have extra copies of OtherStates lying around in order to be able to - !! do this. - CALL AllocAry( PositionXYZprime, 3, SIZE(InputData%PositionXYZ,DIM=2), & - "Array for holding the XYZprime position data", TmpErrStat, TmpErrMsg ) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! Apply the coordinate transformation to the PositionXYZ coordinates to get the PositionXYZprime coordinate list - ! If the PropagationDir is zero, we don't need to apply this and will simply copy the data. Repeat for the WindViXYZ. - IF ( .not. p%RotateWindBox ) THEN - PositionXYZprime = InputData%PositionXYZ - ELSE - ! NOTE: rotations are about the hub at [ 0 0 H ]. See InflowWind_SetParameters for details. - DO I = 1,SIZE(InputData%PositionXYZ,DIM=2) - PositionXYZprime(:,I) = MATMUL( p%RotToWind, (InputData%PositionXYZ(:,I) - p%RefPosition) ) + p%RefPosition - ENDDO - ENDIF - - - !--------------------------------- - ! - - ! Compute the wind velocities by stepping through all the data points and calling the appropriate GetWindSpeed routine - SELECT CASE ( p%WindType ) - - CASE (Steady_WindNumber, Uniform_WindNumber) - - ! InputData only contains the Position array, so we can pass that directly. - CALL IfW_UniformWind_CalcOutput( Time, PositionXYZprime, p%UniformWind, y%VelocityUVW, m%UniformWind, TmpErrStat, TmpErrMsg) - - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - ! Call IfW_UniformWind_CalcOutput again in order to get the values needed for the OutList -- note that we do not report errors from this - IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - ! Move the arrays for the Velocity information - CALL IfW_UniformWind_CalcOutput( Time, p%WindViXYZprime, p%UniformWind, m%WindViUVW, m%UniformWind, TmpErrStat, TmpErrMsg) - ENDIF - - CASE (TSFF_WindNumber) - - ! InputData only contains the Position array, so we can pass that directly. - CALL IfW_TSFFWind_CalcOutput( Time, PositionXYZprime, p%TSFFWind, y%VelocityUVW, m%TSFFWind, TmpErrStat, TmpErrMsg) - - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! Call IfW_TSFFWind_CalcOutput again in order to get the values needed for the OutList - IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - ! Move the arrays for the Velocity information - CALL IfW_TSFFWind_CalcOutput( Time, p%WindViXYZprime, p%TSFFWind, m%WindViUVW, m%TSFFWind, TmpErrStat, TmpErrMsg) - - ! Out of bounds errors will be ErrID_Severe, not ErrID_Fatal - IF ( TmpErrStat >= ErrID_Fatal ) THEN - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - ENDIF - - - - CASE (BladedFF_WindNumber) !also includes BladedFF_Shr_WindNumber - - ! InputData only contains the Position array, so we can pass that directly. - CALL IfW_BladedFFWind_CalcOutput( Time, PositionXYZprime, p%BladedFFWind, y%VelocityUVW, m%BladedFFWind, TmpErrStat, TmpErrMsg) - - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! Call IfW_BladedFFWind_CalcOutput again in order to get the values needed for the OutList - IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - ! Move the arrays for the Velocity information - CALL IfW_BladedFFWind_CalcOutput( Time, p%WindViXYZprime, p%BladedFFWind, m%WindViUVW, m%BladedFFWind, TmpErrStat, TmpErrMsg) - - ! Out of bounds errors will be ErrID_Severe, not ErrID_Fatal - IF ( TmpErrStat >= ErrID_Fatal ) THEN - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - ENDIF - - - CASE (User_WindNumber) - - ! InputData only contains the Position array, so we can pass that directly. - CALL IfW_UserWind_CalcOutput( Time, PositionXYZprime, p%UserWind, y%VelocityUVW, m%UserWind, TmpErrStat, TmpErrMsg) - - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! Call IfW_UserWind_CalcOutput again in order to get the values needed for the OutList - IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - ! Move the arrays for the Velocity information - CALL IfW_UserWind_CalcOutput( Time, p%WindViXYZprime, p%UserWind, m%WindViUVW, m%UserWind, TmpErrStat, TmpErrMsg) - - ! Out of bounds errors will be ErrID_Severe, not ErrID_Fatal - IF ( TmpErrStat >= ErrID_Fatal ) THEN - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - ENDIF - - CASE ( HAWC_WindNumber ) - - ! InputData only contains the Position array, so we can pass that directly. - CALL IfW_HAWCWind_CalcOutput( Time, PositionXYZprime, p%HAWCWind, y%VelocityUVW, m%HAWCWind, TmpErrStat, TmpErrMsg) - - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! Call IfW_TSFFWind_CalcOutput again in order to get the values needed for the OutList - IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - CALL IfW_HAWCWind_CalcOutput( Time, p%WindViXYZprime, p%HAWCWind, m%WindViUVW, m%HAWCWind, TmpErrStat, TmpErrMsg) - - ! Out of bounds errors will be ErrID_Severe, not ErrID_Fatal - IF ( TmpErrStat >= ErrID_Fatal ) THEN - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - ENDIF - - - CASE ( FDext_WindNumber ) - - CALL IfW_4Dext_CalcOutput(Time, PositionXYZprime, p%FDext, y%VelocityUVW, m%FDext, TmpErrStat, TmpErrMsg) - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - - ! Call IfW_4Dext_CalcOutput again in order to get the values needed for the OutList - IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - ! Move the arrays for the Velocity information - CALL IfW_4Dext_CalcOutput(Time, p%WindViXYZprime, p%FDext, m%WindViUVW, m%FDext, TmpErrStat, TmpErrMsg) - - ! Out of bounds errors will be ErrID_Severe, not ErrID_Fatal - IF ( TmpErrStat >= ErrID_Fatal ) THEN - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) - RETURN - ENDIF - - ENDIF - - - ! If it isn't one of the above cases, we have a problem and won't be able to continue - - CASE DEFAULT - - CALL SetErrStat( ErrID_Fatal, ' Error: Undefined wind type '//TRIM(Num2LStr(p%WindType))//'. '// & - 'Call WindInflow_Init() before calling this function.', ErrStat, ErrMsg, RoutineName ) - - y%VelocityUVW(:,:) = 0.0 - RETURN - - END SELECT - - - ! Add coherent turbulence to background wind - -!!! IF (p%CTTS_Flag) THEN -!!! -!!! DO PointCounter = 1, SIZE(InputData%Position, 2) -!!! -!!! TempWindSpeed = CTTS_GetWindSpeed( Time, InputData%Position(:,PointCounter), ErrStat, ErrMsg ) -!!! -!!! ! Error Handling -- move ErrMsg inside CTTS_GetWindSPeed and simplify -!!! IF (ErrStat >= ErrID_Severe) THEN -!!! ErrMsg = 'IfW_CalcOutput: Error in CTTS_GetWindSpeed for point number '//TRIM(Num2LStr(PointCounter)) -!!! EXIT ! Exit the loop -!!! ENDIF -!!! -!!! y%Velocity(:,PointCounter) = y%Velocity(:,PointCounter) + TempWindSpeed -!!! -!!! ENDDO -!!! -!!! ! If something went badly wrong, Return -!!! IF (ErrStat >= ErrID_Severe ) RETURN -!!! -!!! ENDIF -!!! - !ENDIF - - - - - - !----------------------------------------------------------------------- - ! Windspeed coordinate transforms from Wind file coordinates to global - !----------------------------------------------------------------------- - - ! The VelocityUVW array data that has been returned from the sub-modules is in the wind file (X'Y'Z') coordinates at - ! this point. These must be rotated to the global XYZ coordinates. So now we apply the coordinate transformation - ! to the VelocityUVW(prime) coordinates (in wind X'Y'Z' coordinate frame) returned from the submodules to the XYZ - ! coordinate frame, but only if PropagationDir is not zero. This is only a rotation of the returned wind field, so - ! UVW contains the direction components of the wind at XYZ after translation from the U'V'W' wind velocity components - ! in the X'Y'Z' (wind file) coordinate frame. - ! NOTE: rotations are about the hub at [ 0 0 H ]. See InflowWind_SetParameters for details. - IF ( p%RotateWindBox ) THEN - DO I = 1,SIZE(y%VelocityUVW,DIM=2) - y%VelocityUVW(:,I) = MATMUL( p%RotFromWind, y%VelocityUVW(:,I) ) - ENDDO - ENDIF - - ! We also need to rotate the reference frame for the WindViUVW array - ! NOTE: rotations are about the hub at [ 0 0 H ]. See InflowWind_SetParameters for details. - IF ( p%RotateWindBox .AND. FillWrOut ) THEN - DO I = 1,SIZE(m%WindViUVW,DIM=2) - m%WindViUVW(:,I) = MATMUL( p%RotFromWind, m%WindViUVW(:,I) ) - ENDDO - ENDIF + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(InflowWind_InputType), INTENT(IN ) :: InputData !< Inputs at Time + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherStates !< Other states at Time + TYPE(InflowWind_OutputType), INTENT(INOUT) :: y !< Outputs computed at Time (IN for mesh reasons and data allocation) + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables + LOGICAL, INTENT(IN ) :: FillWrOut !< Flag to determine if we need to fill WriteOutput values + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + CHARACTER(*), PARAMETER :: RoutineName="CalculateOutput" + + ! Temporary variables for error handling + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = "" - ! Done with the prime coordinates for the XYZ position information that was passed in. - IF (ALLOCATED(PositionXYZprime)) DEALLOCATE(PositionXYZprime) + ! Get velocities and accelerations for the given positions + CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, InputData%PositionXYZ, & + y%VelocityUVW, y%AccelUVW, TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev) RETURN + ! Get velocities and accelerations for OutList variables, no error check + IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN + CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, p%WindViXYZ, & + m%WindViUVW, m%WindAiUVW, TmpErrStat, TmpErrMsg) + ENDIF END SUBROUTINE CalculateOutput diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index 5031018ab8..a05bf1e959 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -31,13 +31,7 @@ !! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. MODULE InflowWind_Types !--------------------------------------------------------------------------------------------------------------------------------- -USE IfW_FlowField_Types -USE IfW_UniformWind_Types -USE IfW_TSFFWind_Types -USE IfW_BladedFFWind_Types -USE IfW_HAWCWind_Types -USE IfW_UserWind_Types -USE IfW_4Dext_Types +USE InflowWind_IO_Types USE Lidar_Types USE NWTC_Library IMPLICIT NONE @@ -50,30 +44,9 @@ MODULE InflowWind_Types INTEGER(IntKi), PUBLIC, PARAMETER :: User_WindNumber = 6 ! User defined wind. [-] INTEGER(IntKi), PUBLIC, PARAMETER :: BladedFF_Shr_WindNumber = 7 ! Native Bladed binary full-field file. [-] INTEGER(IntKi), PUBLIC, PARAMETER :: FDext_WindNumber = 8 ! 4D wind from external souce (i.e., FAST.Farm). [-] - INTEGER(IntKi), PUBLIC, PARAMETER :: Highest_WindNumber = 8 ! Highest wind number supported. [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Point_WindNumber = 9 ! 4D wind from external souce (i.e., FAST.Farm). [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Highest_WindNumber = 9 ! Highest wind number supported. [-] INTEGER(IntKi), PUBLIC, PARAMETER :: IfW_NumPtsAvg = 144 ! Number of points averaged for rotor-average wind speed [-] -! ========= WindFileMetaData ======= - TYPE, PUBLIC :: WindFileMetaData - CHARACTER(1024) :: FileName !< Name of the windfile retrieved [-] - INTEGER(IntKi) :: WindType = 0 !< Type of the windfile [-] - REAL(ReKi) :: RefHt !< Reference height given in file [meters] - LOGICAL :: RefHt_Set !< Reference height was given in file [-] - REAL(DbKi) :: DT !< TimeStep of the wind file -- zero value for none [seconds] - INTEGER(IntKi) :: NumTSteps !< Number of timesteps in the time range of wind file [-] - LOGICAL :: ConstantDT !< Timesteps are the same throughout file [-] - REAL(ReKi) , DIMENSION(1:2) :: TRange !< Time range of the wind file [seconds] - LOGICAL :: TRange_Limited !< TRange limits strictly enforced [-] - REAL(ReKi) , DIMENSION(1:2) :: YRange !< Range in y direction [meters] - LOGICAL :: YRange_Limited !< YRange limits strictly enforced [-] - REAL(ReKi) , DIMENSION(1:2) :: ZRange !< Range in z direction [meters] - LOGICAL :: ZRange_Limited !< ZRange limits strictly enforced [-] - INTEGER(IntKi) :: BinaryFormat !< Binary format identifier [-] - LOGICAL :: IsBinary !< Windfile is a binary file [-] - REAL(ReKi) , DIMENSION(1:3) :: TI !< Turbulence intensity (U,V,W) [-] - LOGICAL :: TI_listed !< Turbulence intesity given in file [-] - REAL(ReKi) :: MWS !< Approximate mean wind speed [-] - END TYPE WindFileMetaData -! ======================= ! ========= InflowWind_InputFile ======= TYPE, PUBLIC :: InflowWind_InputFile LOGICAL :: EchoFlag !< Echo the input file [-] @@ -113,7 +86,7 @@ MODULE InflowWind_Types INTEGER(IntKi) :: NumPulseGate !< the number of range gates to return wind speeds at [-] REAL(ReKi) , DIMENSION(1:3) :: RotorApexOffsetPos !< position of the lidar unit relative to the rotor apex of rotation [m] LOGICAL :: LidRadialVel !< TRUE => return radial component, FALSE => return 'x' direction estimate [-] - TYPE(IfW_FFWind_InitInputType) :: FF !< scaling data [-] + TYPE(Grid3D_InitInputType) :: FF !< scaling data [-] END TYPE InflowWind_InputFile ! ======================= ! ========= InflowWind_InitInputType ======= @@ -131,7 +104,7 @@ MODULE InflowWind_Types TYPE(FileInfoType) :: WindType2Data !< Optional slot for wind type 2 data if file IO is not used. [-] LOGICAL :: OutputAccel = .FALSE. !< Flag to output wind acceleration [-] TYPE(Lidar_InitInputType) :: lidar !< InitInput for lidar data [-] - TYPE(IfW_4Dext_InitInputType) :: FDext !< InitInput for 4D external wind data [-] + TYPE(Grid4D_InitInputType) :: FDext !< InitInput for 4D external wind data [-] REAL(ReKi) :: RadAvg !< Radius (from hub) used for averaging wind speed [-] END TYPE InflowWind_InitInputType ! ======================= @@ -140,7 +113,7 @@ MODULE InflowWind_Types CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< Names of output-to-file channels [-] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< Units of output-to-file channels [-] TYPE(ProgDesc) :: Ver !< Version information of InflowWind module [-] - TYPE(WindFileMetaData) :: WindFileInfo !< Meta data from the wind file [-] + TYPE(WindFileDat) :: WindFileInfo !< Meta data from the wind file [-] CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] CHARACTER(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_u !< Names of the inputs used in linearization [-] LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_y !< Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame [-] @@ -150,32 +123,20 @@ MODULE InflowWind_Types ! ======================= ! ========= InflowWind_ParameterType ======= TYPE, PUBLIC :: InflowWind_ParameterType + TYPE(FlowFieldType) :: FlowField !< Parameters from Full-Field [-] CHARACTER(1024) :: RootFileName !< Root of the InflowWind input filename [-] - LOGICAL :: CTTS_Flag = .FALSE. !< determines if coherent turbulence is used [-] - LOGICAL :: RotateWindBox = .FALSE. !< determines if wind will be rotated [-] + INTEGER(IntKi) :: WindType = 0 !< Type of wind -- set to Undef_Wind initially [-] REAL(DbKi) :: DT !< Time step for cont. state integration & disc. state update [seconds] - REAL(ReKi) :: PropagationDir !< Direction of wind propagation [radians] - REAL(ReKi) :: VFlowAngle !< Vertical (upflow) angle [radians] - REAL(ReKi) , DIMENSION(1:3,1:3) :: RotToWind !< Rotation matrix for rotating from the global XYZ coordinate system to the wind coordinate system (wind along X') [-] - REAL(ReKi) , DIMENSION(1:3,1:3) :: RotFromWind !< Rotation matrix for rotating from the wind coordinate system (wind along X') back to the global XYZ coordinate system. Equal to TRANSPOSE(RotToWind) [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViXYZprime !< List of XYZ coordinates for velocity measurements, translated to the wind coordinate system (prime coordinates). This equals MATMUL( RotToWind, ParamData%WindViXYZ ) [meters] - INTEGER(IntKi) :: WindType = 0 !< Type of wind -- set to Undef_Wind initially [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViXYZ !< List of XYZ coordinates for wind velocity measurements, 3xNWindVel [meters] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PositionAvg !< (non-rotated) positions of points used for averaging wind speed [meters] REAL(ReKi) :: ReferenceHeight !< Height of the wind turbine [meters] REAL(ReKi) , DIMENSION(1:3) :: RefPosition !< Reference position (point where box is rotated) [meters] INTEGER(IntKi) :: NWindVel !< Number of points in the wind velocity list [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViXYZ !< List of XYZ coordinates for wind velocity measurements, 3xNWindVel [meters] - TYPE(FlowFieldType) :: FlowField !< Parameters from Full-Field [-] - TYPE(IfW_UniformWind_ParameterType) :: UniformWind !< Parameters from UniformWind [-] - TYPE(IfW_TSFFWind_ParameterType) :: TSFFWind !< Parameters from TSFFWind -- TurbSim full-field format [-] - TYPE(IfW_BladedFFWind_ParameterType) :: BladedFFWind !< Parameters from BladedFFWind -- Bladed-style full-field format [-] - TYPE(IfW_HAWCWind_ParameterType) :: HAWCWind !< Parameters from HAWCWind [-] - TYPE(IfW_UserWind_ParameterType) :: UserWind !< Parameters from UserWind [-] - TYPE(IfW_4Dext_ParameterType) :: FDext !< Parameters from FDext [-] INTEGER(IntKi) :: NumOuts = 0 !< Number of parameters in the output list (number of outputs requested) [-] TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: OutParamLinIndx !< Index into WriteOutput for WindViXYZ in linearization analysis [-] TYPE(Lidar_ParameterType) :: lidar !< Lidar parameter data [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PositionAvg !< (non-rotated) positions of points used for averaging wind speed [meters] END TYPE InflowWind_ParameterType ! ======================= ! ========= InflowWind_InputType ======= @@ -218,13 +179,6 @@ MODULE InflowWind_Types ! ======================= ! ========= InflowWind_MiscVarType ======= TYPE, PUBLIC :: InflowWind_MiscVarType - INTEGER(IntKi) :: TimeIndex = 0 !< An Index into the TData array [-] - TYPE(IfW_UniformWind_MiscVarType) :: UniformWind !< MiscVars from UniformWind [-] - TYPE(IfW_TSFFWind_MiscVarType) :: TSFFWind !< MiscVars from TSFFWind [-] - TYPE(IfW_HAWCWind_MiscVarType) :: HAWCWind !< MiscVars from HAWCWind [-] - TYPE(IfW_BladedFFWind_MiscVarType) :: BladedFFWind !< MiscVars from BladedFFWind [-] - TYPE(IfW_UserWind_MiscVarType) :: UserWind !< MiscVars from UserWind [-] - TYPE(IfW_4Dext_MiscVarType) :: FDext !< MiscVars from FDext [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AllOuts !< An array holding the value of all of the calculated (not only selected) output channels [see OutListParameters.xlsx spreadsheet] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViUVW !< List of UVW velocities for wind velocity measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ [meters/second] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindAiUVW !< List of UVW accelerations for wind acceleration measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ [m/s^2] @@ -235,277 +189,6 @@ MODULE InflowWind_Types END TYPE InflowWind_MiscVarType ! ======================= CONTAINS - SUBROUTINE InflowWind_CopyWindFileMetaData( SrcWindFileMetaDataData, DstWindFileMetaDataData, CtrlCode, ErrStat, ErrMsg ) - TYPE(WindFileMetaData), INTENT(IN) :: SrcWindFileMetaDataData - TYPE(WindFileMetaData), INTENT(INOUT) :: DstWindFileMetaDataData - INTEGER(IntKi), INTENT(IN ) :: CtrlCode - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg -! Local - INTEGER(IntKi) :: i,j,k - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_CopyWindFileMetaData' -! - ErrStat = ErrID_None - ErrMsg = "" - DstWindFileMetaDataData%FileName = SrcWindFileMetaDataData%FileName - DstWindFileMetaDataData%WindType = SrcWindFileMetaDataData%WindType - DstWindFileMetaDataData%RefHt = SrcWindFileMetaDataData%RefHt - DstWindFileMetaDataData%RefHt_Set = SrcWindFileMetaDataData%RefHt_Set - DstWindFileMetaDataData%DT = SrcWindFileMetaDataData%DT - DstWindFileMetaDataData%NumTSteps = SrcWindFileMetaDataData%NumTSteps - DstWindFileMetaDataData%ConstantDT = SrcWindFileMetaDataData%ConstantDT - DstWindFileMetaDataData%TRange = SrcWindFileMetaDataData%TRange - DstWindFileMetaDataData%TRange_Limited = SrcWindFileMetaDataData%TRange_Limited - DstWindFileMetaDataData%YRange = SrcWindFileMetaDataData%YRange - DstWindFileMetaDataData%YRange_Limited = SrcWindFileMetaDataData%YRange_Limited - DstWindFileMetaDataData%ZRange = SrcWindFileMetaDataData%ZRange - DstWindFileMetaDataData%ZRange_Limited = SrcWindFileMetaDataData%ZRange_Limited - DstWindFileMetaDataData%BinaryFormat = SrcWindFileMetaDataData%BinaryFormat - DstWindFileMetaDataData%IsBinary = SrcWindFileMetaDataData%IsBinary - DstWindFileMetaDataData%TI = SrcWindFileMetaDataData%TI - DstWindFileMetaDataData%TI_listed = SrcWindFileMetaDataData%TI_listed - DstWindFileMetaDataData%MWS = SrcWindFileMetaDataData%MWS - END SUBROUTINE InflowWind_CopyWindFileMetaData - - SUBROUTINE InflowWind_DestroyWindFileMetaData( WindFileMetaDataData, ErrStat, ErrMsg, DEALLOCATEpointers ) - TYPE(WindFileMetaData), INTENT(INOUT) :: WindFileMetaDataData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers - - INTEGER(IntKi) :: i, i1, i2, i3, i4, i5 - LOGICAL :: DEALLOCATEpointers_local - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_DestroyWindFileMetaData' - - ErrStat = ErrID_None - ErrMsg = "" - - IF (PRESENT(DEALLOCATEpointers)) THEN - DEALLOCATEpointers_local = DEALLOCATEpointers - ELSE - DEALLOCATEpointers_local = .true. - END IF - - END SUBROUTINE InflowWind_DestroyWindFileMetaData - - SUBROUTINE InflowWind_PackWindFileMetaData( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(WindFileMetaData), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_PackWindFileMetaData' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%FileName) ! FileName - Int_BufSz = Int_BufSz + 1 ! WindType - Re_BufSz = Re_BufSz + 1 ! RefHt - Int_BufSz = Int_BufSz + 1 ! RefHt_Set - Db_BufSz = Db_BufSz + 1 ! DT - Int_BufSz = Int_BufSz + 1 ! NumTSteps - Int_BufSz = Int_BufSz + 1 ! ConstantDT - Re_BufSz = Re_BufSz + SIZE(InData%TRange) ! TRange - Int_BufSz = Int_BufSz + 1 ! TRange_Limited - Re_BufSz = Re_BufSz + SIZE(InData%YRange) ! YRange - Int_BufSz = Int_BufSz + 1 ! YRange_Limited - Re_BufSz = Re_BufSz + SIZE(InData%ZRange) ! ZRange - Int_BufSz = Int_BufSz + 1 ! ZRange_Limited - Int_BufSz = Int_BufSz + 1 ! BinaryFormat - Int_BufSz = Int_BufSz + 1 ! IsBinary - Re_BufSz = Re_BufSz + SIZE(InData%TI) ! TI - Int_BufSz = Int_BufSz + 1 ! TI_listed - Re_BufSz = Re_BufSz + 1 ! MWS - IF ( Re_BufSz .GT. 0 ) THEN - ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - DO I = 1, LEN(InData%FileName) - IntKiBuf(Int_Xferred) = ICHAR(InData%FileName(I:I), IntKi) - Int_Xferred = Int_Xferred + 1 - END DO ! I - IntKiBuf(Int_Xferred) = InData%WindType - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%RefHt - Re_Xferred = Re_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%RefHt_Set, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DbKiBuf(Db_Xferred) = InData%DT - Db_Xferred = Db_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%NumTSteps - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%ConstantDT, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%TRange,1), UBOUND(InData%TRange,1) - ReKiBuf(Re_Xferred) = InData%TRange(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%TRange_Limited, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%YRange,1), UBOUND(InData%YRange,1) - ReKiBuf(Re_Xferred) = InData%YRange(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%YRange_Limited, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%ZRange,1), UBOUND(InData%ZRange,1) - ReKiBuf(Re_Xferred) = InData%ZRange(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%ZRange_Limited, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = InData%BinaryFormat - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%IsBinary, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - DO i1 = LBOUND(InData%TI,1), UBOUND(InData%TI,1) - ReKiBuf(Re_Xferred) = InData%TI(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = TRANSFER(InData%TI_listed, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%MWS - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE InflowWind_PackWindFileMetaData - - SUBROUTINE InflowWind_UnPackWindFileMetaData( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(WindFileMetaData), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_UnPackWindFileMetaData' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%FileName) - OutData%FileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%WindType = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%RefHt = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%RefHt_Set = TRANSFER(IntKiBuf(Int_Xferred), OutData%RefHt_Set) - Int_Xferred = Int_Xferred + 1 - OutData%DT = DbKiBuf(Db_Xferred) - Db_Xferred = Db_Xferred + 1 - OutData%NumTSteps = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%ConstantDT = TRANSFER(IntKiBuf(Int_Xferred), OutData%ConstantDT) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%TRange,1) - i1_u = UBOUND(OutData%TRange,1) - DO i1 = LBOUND(OutData%TRange,1), UBOUND(OutData%TRange,1) - OutData%TRange(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%TRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%TRange_Limited) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%YRange,1) - i1_u = UBOUND(OutData%YRange,1) - DO i1 = LBOUND(OutData%YRange,1), UBOUND(OutData%YRange,1) - OutData%YRange(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%YRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%YRange_Limited) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%ZRange,1) - i1_u = UBOUND(OutData%ZRange,1) - DO i1 = LBOUND(OutData%ZRange,1), UBOUND(OutData%ZRange,1) - OutData%ZRange(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%ZRange_Limited = TRANSFER(IntKiBuf(Int_Xferred), OutData%ZRange_Limited) - Int_Xferred = Int_Xferred + 1 - OutData%BinaryFormat = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%IsBinary = TRANSFER(IntKiBuf(Int_Xferred), OutData%IsBinary) - Int_Xferred = Int_Xferred + 1 - i1_l = LBOUND(OutData%TI,1) - i1_u = UBOUND(OutData%TI,1) - DO i1 = LBOUND(OutData%TI,1), UBOUND(OutData%TI,1) - OutData%TI(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%TI_listed = TRANSFER(IntKiBuf(Int_Xferred), OutData%TI_listed) - Int_Xferred = Int_Xferred + 1 - OutData%MWS = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END SUBROUTINE InflowWind_UnPackWindFileMetaData - SUBROUTINE InflowWind_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrStat, ErrMsg ) TYPE(InflowWind_InputFile), INTENT(IN) :: SrcInputFileData TYPE(InflowWind_InputFile), INTENT(INOUT) :: DstInputFileData @@ -515,6 +198,7 @@ SUBROUTINE InflowWind_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCod ! Local INTEGER(IntKi) :: i,j,k INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_CopyInputFile' @@ -602,7 +286,7 @@ SUBROUTINE InflowWind_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCod DstInputFileData%NumPulseGate = SrcInputFileData%NumPulseGate DstInputFileData%RotorApexOffsetPos = SrcInputFileData%RotorApexOffsetPos DstInputFileData%LidRadialVel = SrcInputFileData%LidRadialVel - CALL IfW_FFWind_CopyInitInput( SrcInputFileData%FF, DstInputFileData%FF, CtrlCode, ErrStat2, ErrMsg2 ) + CALL InflowWind_IO_Copygrid3d_initinputtype( SrcInputFileData%FF, DstInputFileData%FF, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE InflowWind_CopyInputFile @@ -640,7 +324,7 @@ SUBROUTINE InflowWind_DestroyInputFile( InputFileData, ErrStat, ErrMsg, DEALLOCA IF (ALLOCATED(InputFileData%OutList)) THEN DEALLOCATE(InputFileData%OutList) ENDIF - CALL IfW_FFWind_DestroyInitInput( InputFileData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL InflowWind_IO_Destroygrid3d_initinputtype( InputFileData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE InflowWind_DestroyInputFile @@ -734,7 +418,7 @@ SUBROUTINE InflowWind_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Int_BufSz = Int_BufSz + 1 ! LidRadialVel ! Allocate buffers for subtypes, if any (we'll get sizes from these) Int_BufSz = Int_BufSz + 3 ! FF: size of buffers for each call to pack subtype - CALL IfW_FFWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF + CALL InflowWind_IO_Packgrid3d_initinputtype( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, .TRUE. ) ! FF CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -923,7 +607,7 @@ SUBROUTINE InflowWind_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat END DO IntKiBuf(Int_Xferred) = TRANSFER(InData%LidRadialVel, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 - CALL IfW_FFWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF + CALL InflowWind_IO_Packgrid3d_initinputtype( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -967,6 +651,7 @@ SUBROUTINE InflowWind_UnPackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS INTEGER(IntKi) :: Int_Xferred INTEGER(IntKi) :: i INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_UnPackInputFile' @@ -1173,7 +858,7 @@ SUBROUTINE InflowWind_UnPackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_FFWind_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF + CALL InflowWind_IO_Unpackgrid3d_initinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%FF, ErrStat2, ErrMsg2 ) ! FF CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -1215,7 +900,7 @@ SUBROUTINE InflowWind_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCod CALL Lidar_CopyInitInput( SrcInitInputData%lidar, DstInitInputData%lidar, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_4Dext_CopyInitInput( SrcInitInputData%FDext, DstInitInputData%FDext, CtrlCode, ErrStat2, ErrMsg2 ) + CALL InflowWind_IO_Copygrid4d_initinputtype( SrcInitInputData%FDext, DstInitInputData%FDext, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN DstInitInputData%RadAvg = SrcInitInputData%RadAvg @@ -1248,7 +933,7 @@ SUBROUTINE InflowWind_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCA CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL Lidar_DestroyInitInput( InitInputData%lidar, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_4Dext_DestroyInitInput( InitInputData%FDext, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL InflowWind_IO_Destroygrid4d_initinputtype( InitInputData%FDext, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) END SUBROUTINE InflowWind_DestroyInitInput @@ -1350,7 +1035,7 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! FDext: size of buffers for each call to pack subtype - CALL IfW_4Dext_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FDext, ErrStat2, ErrMsg2, .TRUE. ) ! FDext + CALL InflowWind_IO_Packgrid4d_initinputtype( Re_Buf, Db_Buf, Int_Buf, InData%FDext, ErrStat2, ErrMsg2, .TRUE. ) ! FDext CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -1502,7 +1187,7 @@ SUBROUTINE InflowWind_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_4Dext_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FDext, ErrStat2, ErrMsg2, OnlySize ) ! FDext + CALL InflowWind_IO_Packgrid4d_initinputtype( Re_Buf, Db_Buf, Int_Buf, InData%FDext, ErrStat2, ErrMsg2, OnlySize ) ! FDext CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -1737,7 +1422,7 @@ SUBROUTINE InflowWind_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_4Dext_UnpackInitInput( Re_Buf, Db_Buf, Int_Buf, OutData%FDext, ErrStat2, ErrMsg2 ) ! FDext + CALL InflowWind_IO_Unpackgrid4d_initinputtype( Re_Buf, Db_Buf, Int_Buf, OutData%FDext, ErrStat2, ErrMsg2 ) ! FDext CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -1790,7 +1475,7 @@ SUBROUTINE InflowWind_CopyInitOutput( SrcInitOutputData, DstInitOutputData, Ctrl CALL NWTC_Library_Copyprogdesc( SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - CALL InflowWind_Copywindfilemetadata( SrcInitOutputData%WindFileInfo, DstInitOutputData%WindFileInfo, CtrlCode, ErrStat2, ErrMsg2 ) + CALL InflowWind_IO_Copywindfiledat( SrcInitOutputData%WindFileInfo, DstInitOutputData%WindFileInfo, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN IF (ALLOCATED(SrcInitOutputData%LinNames_y)) THEN @@ -1884,7 +1569,7 @@ SUBROUTINE InflowWind_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLO ENDIF CALL NWTC_Library_Destroyprogdesc( InitOutputData%Ver, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL InflowWind_Destroywindfilemetadata( InitOutputData%WindFileInfo, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL InflowWind_IO_Destroywindfiledat( InitOutputData%WindFileInfo, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ALLOCATED(InitOutputData%LinNames_y)) THEN DEALLOCATE(InitOutputData%LinNames_y) @@ -1967,7 +1652,7 @@ SUBROUTINE InflowWind_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSta DEALLOCATE(Int_Buf) END IF Int_BufSz = Int_BufSz + 3 ! WindFileInfo: size of buffers for each call to pack subtype - CALL InflowWind_Packwindfilemetadata( Re_Buf, Db_Buf, Int_Buf, InData%WindFileInfo, ErrStat2, ErrMsg2, .TRUE. ) ! WindFileInfo + CALL InflowWind_IO_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%WindFileInfo, ErrStat2, ErrMsg2, .TRUE. ) ! WindFileInfo CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2097,7 +1782,7 @@ SUBROUTINE InflowWind_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrSta ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL InflowWind_Packwindfilemetadata( Re_Buf, Db_Buf, Int_Buf, InData%WindFileInfo, ErrStat2, ErrMsg2, OnlySize ) ! WindFileInfo + CALL InflowWind_IO_Packwindfiledat( Re_Buf, Db_Buf, Int_Buf, InData%WindFileInfo, ErrStat2, ErrMsg2, OnlySize ) ! WindFileInfo CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2346,7 +2031,7 @@ SUBROUTINE InflowWind_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, Err Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL InflowWind_Unpackwindfilemetadata( Re_Buf, Db_Buf, Int_Buf, OutData%WindFileInfo, ErrStat2, ErrMsg2 ) ! WindFileInfo + CALL InflowWind_IO_Unpackwindfiledat( Re_Buf, Db_Buf, Int_Buf, OutData%WindFileInfo, ErrStat2, ErrMsg2 ) ! WindFileInfo CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -2465,14 +2150,12 @@ SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ! ErrStat = ErrID_None ErrMsg = "" + CALL IfW_FlowField_Copyflowfieldtype( SrcParamData%FlowField, DstParamData%FlowField, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN DstParamData%RootFileName = SrcParamData%RootFileName - DstParamData%CTTS_Flag = SrcParamData%CTTS_Flag - DstParamData%RotateWindBox = SrcParamData%RotateWindBox + DstParamData%WindType = SrcParamData%WindType DstParamData%DT = SrcParamData%DT - DstParamData%PropagationDir = SrcParamData%PropagationDir - DstParamData%VFlowAngle = SrcParamData%VFlowAngle - DstParamData%RotToWind = SrcParamData%RotToWind - DstParamData%RotFromWind = SrcParamData%RotFromWind IF (ALLOCATED(SrcParamData%WindViXYZprime)) THEN i1_l = LBOUND(SrcParamData%WindViXYZprime,1) i1_u = UBOUND(SrcParamData%WindViXYZprime,1) @@ -2487,10 +2170,6 @@ SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, END IF DstParamData%WindViXYZprime = SrcParamData%WindViXYZprime ENDIF - DstParamData%WindType = SrcParamData%WindType - DstParamData%ReferenceHeight = SrcParamData%ReferenceHeight - DstParamData%RefPosition = SrcParamData%RefPosition - DstParamData%NWindVel = SrcParamData%NWindVel IF (ALLOCATED(SrcParamData%WindViXYZ)) THEN i1_l = LBOUND(SrcParamData%WindViXYZ,1) i1_u = UBOUND(SrcParamData%WindViXYZ,1) @@ -2505,27 +2184,23 @@ SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, END IF DstParamData%WindViXYZ = SrcParamData%WindViXYZ ENDIF - CALL IfW_FlowField_Copyflowfieldtype( SrcParamData%FlowField, DstParamData%FlowField, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_UniformWind_CopyParam( SrcParamData%UniformWind, DstParamData%UniformWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_TSFFWind_CopyParam( SrcParamData%TSFFWind, DstParamData%TSFFWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_BladedFFWind_CopyParam( SrcParamData%BladedFFWind, DstParamData%BladedFFWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_HAWCWind_CopyParam( SrcParamData%HAWCWind, DstParamData%HAWCWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_UserWind_CopyParam( SrcParamData%UserWind, DstParamData%UserWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_4Dext_CopyParam( SrcParamData%FDext, DstParamData%FDext, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN +IF (ALLOCATED(SrcParamData%PositionAvg)) THEN + i1_l = LBOUND(SrcParamData%PositionAvg,1) + i1_u = UBOUND(SrcParamData%PositionAvg,1) + i2_l = LBOUND(SrcParamData%PositionAvg,2) + i2_u = UBOUND(SrcParamData%PositionAvg,2) + IF (.NOT. ALLOCATED(DstParamData%PositionAvg)) THEN + ALLOCATE(DstParamData%PositionAvg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PositionAvg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstParamData%PositionAvg = SrcParamData%PositionAvg +ENDIF + DstParamData%ReferenceHeight = SrcParamData%ReferenceHeight + DstParamData%RefPosition = SrcParamData%RefPosition + DstParamData%NWindVel = SrcParamData%NWindVel DstParamData%NumOuts = SrcParamData%NumOuts IF (ALLOCATED(SrcParamData%OutParam)) THEN i1_l = LBOUND(SrcParamData%OutParam,1) @@ -2560,20 +2235,6 @@ SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, CALL Lidar_CopyParam( SrcParamData%lidar, DstParamData%lidar, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN -IF (ALLOCATED(SrcParamData%PositionAvg)) THEN - i1_l = LBOUND(SrcParamData%PositionAvg,1) - i1_u = UBOUND(SrcParamData%PositionAvg,1) - i2_l = LBOUND(SrcParamData%PositionAvg,2) - i2_u = UBOUND(SrcParamData%PositionAvg,2) - IF (.NOT. ALLOCATED(DstParamData%PositionAvg)) THEN - ALLOCATE(DstParamData%PositionAvg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PositionAvg.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - DstParamData%PositionAvg = SrcParamData%PositionAvg -ENDIF END SUBROUTINE InflowWind_CopyParam SUBROUTINE InflowWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -2597,26 +2258,17 @@ SUBROUTINE InflowWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointe DEALLOCATEpointers_local = .true. END IF + CALL IfW_FlowField_Destroyflowfieldtype( ParamData%FlowField, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ALLOCATED(ParamData%WindViXYZprime)) THEN DEALLOCATE(ParamData%WindViXYZprime) ENDIF IF (ALLOCATED(ParamData%WindViXYZ)) THEN DEALLOCATE(ParamData%WindViXYZ) ENDIF - CALL IfW_FlowField_Destroyflowfieldtype( ParamData%FlowField, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_UniformWind_DestroyParam( ParamData%UniformWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_TSFFWind_DestroyParam( ParamData%TSFFWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_BladedFFWind_DestroyParam( ParamData%BladedFFWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_HAWCWind_DestroyParam( ParamData%HAWCWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_UserWind_DestroyParam( ParamData%UserWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_4Dext_DestroyParam( ParamData%FDext, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) +IF (ALLOCATED(ParamData%PositionAvg)) THEN + DEALLOCATE(ParamData%PositionAvg) +ENDIF IF (ALLOCATED(ParamData%OutParam)) THEN DO i1 = LBOUND(ParamData%OutParam,1), UBOUND(ParamData%OutParam,1) CALL NWTC_Library_Destroyoutparmtype( ParamData%OutParam(i1), ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) @@ -2629,9 +2281,6 @@ SUBROUTINE InflowWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointe ENDIF CALL Lidar_DestroyParam( ParamData%lidar, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) -IF (ALLOCATED(ParamData%PositionAvg)) THEN - DEALLOCATE(ParamData%PositionAvg) -ENDIF END SUBROUTINE InflowWind_DestroyParam SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -2669,28 +2318,6 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1*LEN(InData%RootFileName) ! RootFileName - Int_BufSz = Int_BufSz + 1 ! CTTS_Flag - Int_BufSz = Int_BufSz + 1 ! RotateWindBox - Db_BufSz = Db_BufSz + 1 ! DT - Re_BufSz = Re_BufSz + 1 ! PropagationDir - Re_BufSz = Re_BufSz + 1 ! VFlowAngle - Re_BufSz = Re_BufSz + SIZE(InData%RotToWind) ! RotToWind - Re_BufSz = Re_BufSz + SIZE(InData%RotFromWind) ! RotFromWind - Int_BufSz = Int_BufSz + 1 ! WindViXYZprime allocated yes/no - IF ( ALLOCATED(InData%WindViXYZprime) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! WindViXYZprime upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%WindViXYZprime) ! WindViXYZprime - END IF - Int_BufSz = Int_BufSz + 1 ! WindType - Re_BufSz = Re_BufSz + 1 ! ReferenceHeight - Re_BufSz = Re_BufSz + SIZE(InData%RefPosition) ! RefPosition - Int_BufSz = Int_BufSz + 1 ! NWindVel - Int_BufSz = Int_BufSz + 1 ! WindViXYZ allocated yes/no - IF ( ALLOCATED(InData%WindViXYZ) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! WindViXYZ upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%WindViXYZ) ! WindViXYZ - END IF ! Allocate buffers for subtypes, if any (we'll get sizes from these) Int_BufSz = Int_BufSz + 3 ! FlowField: size of buffers for each call to pack subtype CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, .TRUE. ) ! FlowField @@ -2709,108 +2336,27 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 3 ! UniformWind: size of buffers for each call to pack subtype - CALL IfW_UniformWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%UniformWind, ErrStat2, ErrMsg2, .TRUE. ) ! UniformWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! UniformWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! UniformWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! UniformWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! TSFFWind: size of buffers for each call to pack subtype - CALL IfW_TSFFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%TSFFWind, ErrStat2, ErrMsg2, .TRUE. ) ! TSFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! TSFFWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! TSFFWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! TSFFWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! BladedFFWind: size of buffers for each call to pack subtype - CALL IfW_BladedFFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%BladedFFWind, ErrStat2, ErrMsg2, .TRUE. ) ! BladedFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! BladedFFWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! BladedFFWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! BladedFFWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! HAWCWind: size of buffers for each call to pack subtype - CALL IfW_HAWCWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%HAWCWind, ErrStat2, ErrMsg2, .TRUE. ) ! HAWCWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! HAWCWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! HAWCWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! HAWCWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! UserWind: size of buffers for each call to pack subtype - CALL IfW_UserWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%UserWind, ErrStat2, ErrMsg2, .TRUE. ) ! UserWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! UserWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! UserWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! UserWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! FDext: size of buffers for each call to pack subtype - CALL IfW_4Dext_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FDext, ErrStat2, ErrMsg2, .TRUE. ) ! FDext - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! FDext - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! FDext - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! FDext - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF + Int_BufSz = Int_BufSz + 1*LEN(InData%RootFileName) ! RootFileName + Int_BufSz = Int_BufSz + 1 ! WindType + Db_BufSz = Db_BufSz + 1 ! DT + Int_BufSz = Int_BufSz + 1 ! WindViXYZprime allocated yes/no + IF ( ALLOCATED(InData%WindViXYZprime) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WindViXYZprime upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WindViXYZprime) ! WindViXYZprime + END IF + Int_BufSz = Int_BufSz + 1 ! WindViXYZ allocated yes/no + IF ( ALLOCATED(InData%WindViXYZ) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! WindViXYZ upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%WindViXYZ) ! WindViXYZ + END IF + Int_BufSz = Int_BufSz + 1 ! PositionAvg allocated yes/no + IF ( ALLOCATED(InData%PositionAvg) ) THEN + Int_BufSz = Int_BufSz + 2*2 ! PositionAvg upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%PositionAvg) ! PositionAvg + END IF + Re_BufSz = Re_BufSz + 1 ! ReferenceHeight + Re_BufSz = Re_BufSz + SIZE(InData%RefPosition) ! RefPosition + Int_BufSz = Int_BufSz + 1 ! NWindVel Int_BufSz = Int_BufSz + 1 ! NumOuts Int_BufSz = Int_BufSz + 1 ! OutParam allocated yes/no IF ( ALLOCATED(InData%OutParam) ) THEN @@ -2857,11 +2403,6 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 1 ! PositionAvg allocated yes/no - IF ( ALLOCATED(InData%PositionAvg) ) THEN - Int_BufSz = Int_BufSz + 2*2 ! PositionAvg upper/lower bounds for each dimension - Re_BufSz = Re_BufSz + SIZE(InData%PositionAvg) ! PositionAvg - END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2889,32 +2430,42 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_Xferred = 1 Int_Xferred = 1 + CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, OnlySize ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF DO I = 1, LEN(InData%RootFileName) IntKiBuf(Int_Xferred) = ICHAR(InData%RootFileName(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I - IntKiBuf(Int_Xferred) = TRANSFER(InData%CTTS_Flag, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 - IntKiBuf(Int_Xferred) = TRANSFER(InData%RotateWindBox, IntKiBuf(1)) + IntKiBuf(Int_Xferred) = InData%WindType Int_Xferred = Int_Xferred + 1 DbKiBuf(Db_Xferred) = InData%DT Db_Xferred = Db_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%PropagationDir - Re_Xferred = Re_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%VFlowAngle - Re_Xferred = Re_Xferred + 1 - DO i2 = LBOUND(InData%RotToWind,2), UBOUND(InData%RotToWind,2) - DO i1 = LBOUND(InData%RotToWind,1), UBOUND(InData%RotToWind,1) - ReKiBuf(Re_Xferred) = InData%RotToWind(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - DO i2 = LBOUND(InData%RotFromWind,2), UBOUND(InData%RotFromWind,2) - DO i1 = LBOUND(InData%RotFromWind,1), UBOUND(InData%RotFromWind,1) - ReKiBuf(Re_Xferred) = InData%RotFromWind(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO IF ( .NOT. ALLOCATED(InData%WindViXYZprime) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2935,16 +2486,6 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END DO END DO END IF - IntKiBuf(Int_Xferred) = InData%WindType - Int_Xferred = Int_Xferred + 1 - ReKiBuf(Re_Xferred) = InData%ReferenceHeight - Re_Xferred = Re_Xferred + 1 - DO i1 = LBOUND(InData%RefPosition,1), UBOUND(InData%RefPosition,1) - ReKiBuf(Re_Xferred) = InData%RefPosition(i1) - Re_Xferred = Re_Xferred + 1 - END DO - IntKiBuf(Int_Xferred) = InData%NWindVel - Int_Xferred = Int_Xferred + 1 IF ( .NOT. ALLOCATED(InData%WindViXYZ) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2965,35 +2506,48 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END DO END DO END IF - CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, OnlySize ) ! FlowField - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN + IF ( .NOT. ALLOCATED(InData%PositionAvg) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PositionAvg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PositionAvg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%PositionAvg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PositionAvg,2) + Int_Xferred = Int_Xferred + 2 - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL IfW_UniformWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%UniformWind, ErrStat2, ErrMsg2, OnlySize ) ! UniformWind + DO i2 = LBOUND(InData%PositionAvg,2), UBOUND(InData%PositionAvg,2) + DO i1 = LBOUND(InData%PositionAvg,1), UBOUND(InData%PositionAvg,1) + ReKiBuf(Re_Xferred) = InData%PositionAvg(i1,i2) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + ReKiBuf(Re_Xferred) = InData%ReferenceHeight + Re_Xferred = Re_Xferred + 1 + DO i1 = LBOUND(InData%RefPosition,1), UBOUND(InData%RefPosition,1) + ReKiBuf(Re_Xferred) = InData%RefPosition(i1) + Re_Xferred = Re_Xferred + 1 + END DO + IntKiBuf(Int_Xferred) = InData%NWindVel + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%NumOuts + Int_Xferred = Int_Xferred + 1 + IF ( .NOT. ALLOCATED(InData%OutParam) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OutParam,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutParam,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%OutParam,1), UBOUND(InData%OutParam,1) + CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%OutParam(i1), ErrStat2, ErrMsg2, OnlySize ) ! OutParam CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3021,7 +2575,29 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_TSFFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%TSFFWind, ErrStat2, ErrMsg2, OnlySize ) ! TSFFWind + END DO + END IF + IF ( .NOT. ALLOCATED(InData%OutParamLinIndx) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OutParamLinIndx,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutParamLinIndx,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%OutParamLinIndx,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutParamLinIndx,2) + Int_Xferred = Int_Xferred + 2 + + DO i2 = LBOUND(InData%OutParamLinIndx,2), UBOUND(InData%OutParamLinIndx,2) + DO i1 = LBOUND(InData%OutParamLinIndx,1), UBOUND(InData%OutParamLinIndx,1) + IntKiBuf(Int_Xferred) = InData%OutParamLinIndx(i1,i2) + Int_Xferred = Int_Xferred + 1 + END DO + END DO + END IF + CALL Lidar_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%lidar, ErrStat2, ErrMsg2, OnlySize ) ! lidar CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -3049,591 +2625,36 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - CALL IfW_BladedFFWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%BladedFFWind, ErrStat2, ErrMsg2, OnlySize ) ! BladedFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL IfW_HAWCWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%HAWCWind, ErrStat2, ErrMsg2, OnlySize ) ! HAWCWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL IfW_UserWind_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%UserWind, ErrStat2, ErrMsg2, OnlySize ) ! UserWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL IfW_4Dext_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%FDext, ErrStat2, ErrMsg2, OnlySize ) ! FDext - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IntKiBuf(Int_Xferred) = InData%NumOuts - Int_Xferred = Int_Xferred + 1 - IF ( .NOT. ALLOCATED(InData%OutParam) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%OutParam,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutParam,1) - Int_Xferred = Int_Xferred + 2 - - DO i1 = LBOUND(InData%OutParam,1), UBOUND(InData%OutParam,1) - CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%OutParam(i1), ErrStat2, ErrMsg2, OnlySize ) ! OutParam - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - END DO - END IF - IF ( .NOT. ALLOCATED(InData%OutParamLinIndx) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%OutParamLinIndx,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutParamLinIndx,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%OutParamLinIndx,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%OutParamLinIndx,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%OutParamLinIndx,2), UBOUND(InData%OutParamLinIndx,2) - DO i1 = LBOUND(InData%OutParamLinIndx,1), UBOUND(InData%OutParamLinIndx,1) - IntKiBuf(Int_Xferred) = InData%OutParamLinIndx(i1,i2) - Int_Xferred = Int_Xferred + 1 - END DO - END DO - END IF - CALL Lidar_PackParam( Re_Buf, Db_Buf, Int_Buf, InData%lidar, ErrStat2, ErrMsg2, OnlySize ) ! lidar - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF ( .NOT. ALLOCATED(InData%PositionAvg) ) THEN - IntKiBuf( Int_Xferred ) = 0 - Int_Xferred = Int_Xferred + 1 - ELSE - IntKiBuf( Int_Xferred ) = 1 - Int_Xferred = Int_Xferred + 1 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PositionAvg,1) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PositionAvg,1) - Int_Xferred = Int_Xferred + 2 - IntKiBuf( Int_Xferred ) = LBOUND(InData%PositionAvg,2) - IntKiBuf( Int_Xferred + 1) = UBOUND(InData%PositionAvg,2) - Int_Xferred = Int_Xferred + 2 - - DO i2 = LBOUND(InData%PositionAvg,2), UBOUND(InData%PositionAvg,2) - DO i1 = LBOUND(InData%PositionAvg,1), UBOUND(InData%PositionAvg,1) - ReKiBuf(Re_Xferred) = InData%PositionAvg(i1,i2) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF END SUBROUTINE InflowWind_PackParam SUBROUTINE InflowWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) - REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) - TYPE(InflowWind_ParameterType), INTENT(INOUT) :: OutData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - ! Local variables - INTEGER(IntKi) :: Buf_size - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i - INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 - INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_UnPackParam' - ! buffers to store meshes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - DO I = 1, LEN(OutData%RootFileName) - OutData%RootFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) - Int_Xferred = Int_Xferred + 1 - END DO ! I - OutData%CTTS_Flag = TRANSFER(IntKiBuf(Int_Xferred), OutData%CTTS_Flag) - Int_Xferred = Int_Xferred + 1 - OutData%RotateWindBox = TRANSFER(IntKiBuf(Int_Xferred), OutData%RotateWindBox) - Int_Xferred = Int_Xferred + 1 - OutData%DT = DbKiBuf(Db_Xferred) - Db_Xferred = Db_Xferred + 1 - OutData%PropagationDir = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - OutData%VFlowAngle = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - i1_l = LBOUND(OutData%RotToWind,1) - i1_u = UBOUND(OutData%RotToWind,1) - i2_l = LBOUND(OutData%RotToWind,2) - i2_u = UBOUND(OutData%RotToWind,2) - DO i2 = LBOUND(OutData%RotToWind,2), UBOUND(OutData%RotToWind,2) - DO i1 = LBOUND(OutData%RotToWind,1), UBOUND(OutData%RotToWind,1) - OutData%RotToWind(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - i1_l = LBOUND(OutData%RotFromWind,1) - i1_u = UBOUND(OutData%RotFromWind,1) - i2_l = LBOUND(OutData%RotFromWind,2) - i2_u = UBOUND(OutData%RotFromWind,2) - DO i2 = LBOUND(OutData%RotFromWind,2), UBOUND(OutData%RotFromWind,2) - DO i1 = LBOUND(OutData%RotFromWind,1), UBOUND(OutData%RotFromWind,1) - OutData%RotFromWind(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindViXYZprime not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WindViXYZprime)) DEALLOCATE(OutData%WindViXYZprime) - ALLOCATE(OutData%WindViXYZprime(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WindViXYZprime.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%WindViXYZprime,2), UBOUND(OutData%WindViXYZprime,2) - DO i1 = LBOUND(OutData%WindViXYZprime,1), UBOUND(OutData%WindViXYZprime,1) - OutData%WindViXYZprime(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - OutData%WindType = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - OutData%ReferenceHeight = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - i1_l = LBOUND(OutData%RefPosition,1) - i1_u = UBOUND(OutData%RefPosition,1) - DO i1 = LBOUND(OutData%RefPosition,1), UBOUND(OutData%RefPosition,1) - OutData%RefPosition(i1) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - OutData%NWindVel = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindViXYZ not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%WindViXYZ)) DEALLOCATE(OutData%WindViXYZ) - ALLOCATE(OutData%WindViXYZ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WindViXYZ.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%WindViXYZ,2), UBOUND(OutData%WindViXYZ,2) - DO i1 = LBOUND(OutData%WindViXYZ,1), UBOUND(OutData%WindViXYZ,1) - OutData%WindViXYZ(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_FlowField_Unpackflowfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%FlowField, ErrStat2, ErrMsg2 ) ! FlowField - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_UniformWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%UniformWind, ErrStat2, ErrMsg2 ) ! UniformWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_TSFFWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%TSFFWind, ErrStat2, ErrMsg2 ) ! TSFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_BladedFFWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%BladedFFWind, ErrStat2, ErrMsg2 ) ! BladedFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_HAWCWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%HAWCWind, ErrStat2, ErrMsg2 ) ! HAWCWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_UserWind_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%UserWind, ErrStat2, ErrMsg2 ) ! UserWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:) + TYPE(InflowWind_ParameterType), INTENT(INOUT) :: OutData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + ! Local variables + INTEGER(IntKi) :: Buf_size + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i + INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1 + INTEGER(IntKi) :: i2, i2_l, i2_u ! bounds (upper/lower) for an array dimension 2 + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_UnPackParam' + ! buffers to store meshes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -3667,13 +2688,100 @@ SUBROUTINE InflowWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) Int_Xferred = Int_Xferred + Buf_size END IF - CALL IfW_4Dext_UnpackParam( Re_Buf, Db_Buf, Int_Buf, OutData%FDext, ErrStat2, ErrMsg2 ) ! FDext + CALL IfW_FlowField_Unpackflowfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%FlowField, ErrStat2, ErrMsg2 ) ! FlowField CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + DO I = 1, LEN(OutData%RootFileName) + OutData%RootFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + OutData%WindType = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 + OutData%DT = DbKiBuf(Db_Xferred) + Db_Xferred = Db_Xferred + 1 + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindViXYZprime not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WindViXYZprime)) DEALLOCATE(OutData%WindViXYZprime) + ALLOCATE(OutData%WindViXYZprime(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WindViXYZprime.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WindViXYZprime,2), UBOUND(OutData%WindViXYZprime,2) + DO i1 = LBOUND(OutData%WindViXYZprime,1), UBOUND(OutData%WindViXYZprime,1) + OutData%WindViXYZprime(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WindViXYZ not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%WindViXYZ)) DEALLOCATE(OutData%WindViXYZ) + ALLOCATE(OutData%WindViXYZ(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%WindViXYZ.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%WindViXYZ,2), UBOUND(OutData%WindViXYZ,2) + DO i1 = LBOUND(OutData%WindViXYZ,1), UBOUND(OutData%WindViXYZ,1) + OutData%WindViXYZ(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PositionAvg not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%PositionAvg)) DEALLOCATE(OutData%PositionAvg) + ALLOCATE(OutData%PositionAvg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PositionAvg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i2 = LBOUND(OutData%PositionAvg,2), UBOUND(OutData%PositionAvg,2) + DO i1 = LBOUND(OutData%PositionAvg,1), UBOUND(OutData%PositionAvg,1) + OutData%PositionAvg(i1,i2) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END IF + OutData%ReferenceHeight = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + i1_l = LBOUND(OutData%RefPosition,1) + i1_u = UBOUND(OutData%RefPosition,1) + DO i1 = LBOUND(OutData%RefPosition,1), UBOUND(OutData%RefPosition,1) + OutData%RefPosition(i1) = ReKiBuf(Re_Xferred) + Re_Xferred = Re_Xferred + 1 + END DO + OutData%NWindVel = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 OutData%NumOuts = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! OutParam not allocated @@ -3795,29 +2903,6 @@ SUBROUTINE InflowWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PositionAvg not allocated - Int_Xferred = Int_Xferred + 1 - ELSE - Int_Xferred = Int_Xferred + 1 - i1_l = IntKiBuf( Int_Xferred ) - i1_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - i2_l = IntKiBuf( Int_Xferred ) - i2_u = IntKiBuf( Int_Xferred + 1) - Int_Xferred = Int_Xferred + 2 - IF (ALLOCATED(OutData%PositionAvg)) DEALLOCATE(OutData%PositionAvg) - ALLOCATE(OutData%PositionAvg(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%PositionAvg.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - DO i2 = LBOUND(OutData%PositionAvg,2), UBOUND(OutData%PositionAvg,2) - DO i1 = LBOUND(OutData%PositionAvg,1), UBOUND(OutData%PositionAvg,1) - OutData%PositionAvg(i1,i2) = ReKiBuf(Re_Xferred) - Re_Xferred = Re_Xferred + 1 - END DO - END DO - END IF END SUBROUTINE InflowWind_UnPackParam SUBROUTINE InflowWind_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) @@ -5138,25 +4223,6 @@ SUBROUTINE InflowWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, Err ! ErrStat = ErrID_None ErrMsg = "" - DstMiscData%TimeIndex = SrcMiscData%TimeIndex - CALL IfW_UniformWind_CopyMisc( SrcMiscData%UniformWind, DstMiscData%UniformWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_TSFFWind_CopyMisc( SrcMiscData%TSFFWind, DstMiscData%TSFFWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_HAWCWind_CopyMisc( SrcMiscData%HAWCWind, DstMiscData%HAWCWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_BladedFFWind_CopyMisc( SrcMiscData%BladedFFWind, DstMiscData%BladedFFWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_UserWind_CopyMisc( SrcMiscData%UserWind, DstMiscData%UserWind, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN - CALL IfW_4Dext_CopyMisc( SrcMiscData%FDext, DstMiscData%FDext, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN IF (ALLOCATED(SrcMiscData%AllOuts)) THEN i1_l = LBOUND(SrcMiscData%AllOuts,1) i1_u = UBOUND(SrcMiscData%AllOuts,1) @@ -5232,176 +4298,60 @@ SUBROUTINE InflowWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers DEALLOCATEpointers_local = .true. END IF - CALL IfW_UniformWind_DestroyMisc( MiscData%UniformWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_TSFFWind_DestroyMisc( MiscData%TSFFWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_HAWCWind_DestroyMisc( MiscData%HAWCWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_BladedFFWind_DestroyMisc( MiscData%BladedFFWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_UserWind_DestroyMisc( MiscData%UserWind, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL IfW_4Dext_DestroyMisc( MiscData%FDext, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ALLOCATED(MiscData%AllOuts)) THEN DEALLOCATE(MiscData%AllOuts) ENDIF IF (ALLOCATED(MiscData%WindViUVW)) THEN DEALLOCATE(MiscData%WindViUVW) -ENDIF -IF (ALLOCATED(MiscData%WindAiUVW)) THEN - DEALLOCATE(MiscData%WindAiUVW) -ENDIF - CALL InflowWind_DestroyInput( MiscData%u_Avg, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL InflowWind_DestroyOutput( MiscData%y_Avg, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL InflowWind_DestroyInput( MiscData%u_Hub, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - CALL InflowWind_DestroyOutput( MiscData%y_Hub, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - END SUBROUTINE InflowWind_DestroyMisc - - SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) - REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) - REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) - INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) - TYPE(InflowWind_MiscVarType), INTENT(IN) :: InData - INTEGER(IntKi), INTENT( OUT) :: ErrStat - CHARACTER(*), INTENT( OUT) :: ErrMsg - LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly - ! Local variables - INTEGER(IntKi) :: Re_BufSz - INTEGER(IntKi) :: Re_Xferred - INTEGER(IntKi) :: Db_BufSz - INTEGER(IntKi) :: Db_Xferred - INTEGER(IntKi) :: Int_BufSz - INTEGER(IntKi) :: Int_Xferred - INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 - LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_PackMisc' - ! buffers to store subtypes, if any - REAL(ReKi), ALLOCATABLE :: Re_Buf(:) - REAL(DbKi), ALLOCATABLE :: Db_Buf(:) - INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - - OnlySize = .FALSE. - IF ( PRESENT(SizeOnly) ) THEN - OnlySize = SizeOnly - ENDIF - ! - ErrStat = ErrID_None - ErrMsg = "" - Re_BufSz = 0 - Db_BufSz = 0 - Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! TimeIndex - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! UniformWind: size of buffers for each call to pack subtype - CALL IfW_UniformWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%UniformWind, ErrStat2, ErrMsg2, .TRUE. ) ! UniformWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! UniformWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! UniformWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! UniformWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! TSFFWind: size of buffers for each call to pack subtype - CALL IfW_TSFFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%TSFFWind, ErrStat2, ErrMsg2, .TRUE. ) ! TSFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! TSFFWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! TSFFWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! TSFFWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! HAWCWind: size of buffers for each call to pack subtype - CALL IfW_HAWCWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%HAWCWind, ErrStat2, ErrMsg2, .TRUE. ) ! HAWCWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! HAWCWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! HAWCWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! HAWCWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! BladedFFWind: size of buffers for each call to pack subtype - CALL IfW_BladedFFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%BladedFFWind, ErrStat2, ErrMsg2, .TRUE. ) ! BladedFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! BladedFFWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! BladedFFWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! BladedFFWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! UserWind: size of buffers for each call to pack subtype - CALL IfW_UserWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%UserWind, ErrStat2, ErrMsg2, .TRUE. ) ! UserWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN +ENDIF +IF (ALLOCATED(MiscData%WindAiUVW)) THEN + DEALLOCATE(MiscData%WindAiUVW) +ENDIF + CALL InflowWind_DestroyInput( MiscData%u_Avg, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL InflowWind_DestroyOutput( MiscData%y_Avg, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL InflowWind_DestroyInput( MiscData%u_Hub, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL InflowWind_DestroyOutput( MiscData%y_Hub, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + END SUBROUTINE InflowWind_DestroyMisc - IF(ALLOCATED(Re_Buf)) THEN ! UserWind - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! UserWind - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! UserWind - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF - Int_BufSz = Int_BufSz + 3 ! FDext: size of buffers for each call to pack subtype - CALL IfW_4Dext_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FDext, ErrStat2, ErrMsg2, .TRUE. ) ! FDext - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN + SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) + REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:) + REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:) + INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:) + TYPE(InflowWind_MiscVarType), INTENT(IN) :: InData + INTEGER(IntKi), INTENT( OUT) :: ErrStat + CHARACTER(*), INTENT( OUT) :: ErrMsg + LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly + ! Local variables + INTEGER(IntKi) :: Re_BufSz + INTEGER(IntKi) :: Re_Xferred + INTEGER(IntKi) :: Db_BufSz + INTEGER(IntKi) :: Db_Xferred + INTEGER(IntKi) :: Int_BufSz + INTEGER(IntKi) :: Int_Xferred + INTEGER(IntKi) :: i,i1,i2,i3,i4,i5 + LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_PackMisc' + ! buffers to store subtypes, if any + REAL(ReKi), ALLOCATABLE :: Re_Buf(:) + REAL(DbKi), ALLOCATABLE :: Db_Buf(:) + INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:) - IF(ALLOCATED(Re_Buf)) THEN ! FDext - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! FDext - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! FDext - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF + OnlySize = .FALSE. + IF ( PRESENT(SizeOnly) ) THEN + OnlySize = SizeOnly + ENDIF + ! + ErrStat = ErrID_None + ErrMsg = "" + Re_BufSz = 0 + Db_BufSz = 0 + Int_BufSz = 0 Int_BufSz = Int_BufSz + 1 ! AllOuts allocated yes/no IF ( ALLOCATED(InData%AllOuts) ) THEN Int_BufSz = Int_BufSz + 2*1 ! AllOuts upper/lower bounds for each dimension @@ -5417,6 +4367,7 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_BufSz = Int_BufSz + 2*2 ! WindAiUVW upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WindAiUVW) ! WindAiUVW END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) Int_BufSz = Int_BufSz + 3 ! u_Avg: size of buffers for each call to pack subtype CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Avg, ErrStat2, ErrMsg2, .TRUE. ) ! u_Avg CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -5491,197 +4442,27 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName) RETURN END IF - END IF - IF ( Db_BufSz .GT. 0 ) THEN - ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF ( Int_BufSz .GT. 0 ) THEN - ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - END IF - IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) - - Re_Xferred = 1 - Db_Xferred = 1 - Int_Xferred = 1 - - IntKiBuf(Int_Xferred) = InData%TimeIndex - Int_Xferred = Int_Xferred + 1 - CALL IfW_UniformWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%UniformWind, ErrStat2, ErrMsg2, OnlySize ) ! UniformWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL IfW_TSFFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%TSFFWind, ErrStat2, ErrMsg2, OnlySize ) ! TSFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL IfW_HAWCWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%HAWCWind, ErrStat2, ErrMsg2, OnlySize ) ! HAWCWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL IfW_BladedFFWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%BladedFFWind, ErrStat2, ErrMsg2, OnlySize ) ! BladedFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL IfW_UserWind_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%UserWind, ErrStat2, ErrMsg2, OnlySize ) ! UserWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - CALL IfW_4Dext_PackMisc( Re_Buf, Db_Buf, Int_Buf, InData%FDext, ErrStat2, ErrMsg2, OnlySize ) ! FDext - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF + END IF + IF ( Db_BufSz .GT. 0 ) THEN + ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF ( Int_BufSz .GT. 0 ) THEN + ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 ) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them) + + Re_Xferred = 1 + Db_Xferred = 1 + Int_Xferred = 1 + IF ( .NOT. ALLOCATED(InData%AllOuts) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -5879,248 +4660,6 @@ SUBROUTINE InflowWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%TimeIndex = IntKiBuf(Int_Xferred) - Int_Xferred = Int_Xferred + 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_UniformWind_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%UniformWind, ErrStat2, ErrMsg2 ) ! UniformWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_TSFFWind_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%TSFFWind, ErrStat2, ErrMsg2 ) ! TSFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_HAWCWind_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%HAWCWind, ErrStat2, ErrMsg2 ) ! HAWCWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_BladedFFWind_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%BladedFFWind, ErrStat2, ErrMsg2 ) ! BladedFFWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_UserWind_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%UserWind, ErrStat2, ErrMsg2 ) ! UserWind - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_4Dext_UnpackMisc( Re_Buf, Db_Buf, Int_Buf, OutData%FDext, ErrStat2, ErrMsg2 ) ! FDext - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AllOuts not allocated Int_Xferred = Int_Xferred + 1 ELSE diff --git a/modules/inflowwind/tests/ifw_test_tools.F90 b/modules/inflowwind/tests/ifw_test_tools.F90 index bbbabbbdfc..bc8fdeebb0 100644 --- a/modules/inflowwind/tests/ifw_test_tools.F90 +++ b/modules/inflowwind/tests/ifw_test_tools.F90 @@ -13,7 +13,7 @@ function getInputFileData() INTEGER :: ErrStat CHARACTER(ErrMsgLen) :: ErrMsg TYPE(FileInfoType) :: getInputFileData - CHARACTER(1024), DIMENSION(55) :: data = (/ & + CHARACTER(1024), DIMENSION(56) :: data = (/ & '------- InflowWind v3.01.* INPUT FILE ------------------------------------------------------------------------- ', & 'Steady 8 m/s winds with no shear for FAST CertTests #20 and #25 ', & '--------------------------------------------------------------------------------------------------------------- ', & @@ -21,6 +21,7 @@ function getInputFileData() ' 1 WindType - switch for wind file type (1=steady; 2=uniform; 3=binary TurbSim FF; 4=binary Bladed-style FF; 5=HAWC format; 6=User defined; 7=native Bladed FF) ', & ' 0 PropagationDir - Direction of wind propagation (meteoroligical rotation from aligned with X (positive rotates towards -Y) -- degrees) ', & ' 0 VFlowAng - Upflow angle (degrees) (not used for native Bladed format WindType=7) ', & + ' false VelInterpCubic - Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7] ', & ' 1 NWindVel - Number of points to output the wind velocity (0 to 9) ', & ' 0 WindVxiList - List of coordinates in the inertial X direction (m) ', & ' 0 WindVyiList - List of coordinates in the inertial Y direction (m) ', & @@ -80,7 +81,7 @@ function getInputFileDataWindType2() INTEGER :: ErrStat CHARACTER(ErrMsgLen) :: ErrMsg TYPE(FileInfoType) :: getInputFileDataWindType2 - CHARACTER(1024), DIMENSION(55) :: data = (/ & + CHARACTER(1024), DIMENSION(56) :: data = (/ & '------- InflowWind v3.01.* INPUT FILE ------------------------------------------------------------------------- ', & 'Steady 8 m/s winds with no shear for FAST CertTests #20 and #25 ', & '--------------------------------------------------------------------------------------------------------------- ', & @@ -88,6 +89,7 @@ function getInputFileDataWindType2() ' 2 WindType - switch for wind file type (1=steady; 2=uniform; 3=binary TurbSim FF; 4=binary Bladed-style FF; 5=HAWC format; 6=User defined; 7=native Bladed FF) ', & ' 0 PropagationDir - Direction of wind propagation (meteoroligical rotation from aligned with X (positive rotates towards -Y) -- degrees) ', & ' 0 VFlowAng - Upflow angle (degrees) (not used for native Bladed format WindType=7) ', & + ' false VelInterpCubic - Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7] ', & ' 1 NWindVel - Number of points to output the wind velocity (0 to 9) ', & ' 0 WindVxiList - List of coordinates in the inertial X direction (m) ', & ' 0 WindVyiList - List of coordinates in the inertial Y direction (m) ', & diff --git a/modules/inflowwind/tests/test_outputs.F90 b/modules/inflowwind/tests/test_outputs.F90 index 3a89f57598..009a8bdd0d 100644 --- a/modules/inflowwind/tests/test_outputs.F90 +++ b/modules/inflowwind/tests/test_outputs.F90 @@ -44,7 +44,7 @@ subroutine test_outputs_parsing_alternate() PriPath = "" InFileInfo = getInputFileData() - InFileInfo%Lines(51:53) = (/ & + InFileInfo%Lines(52:54) = (/ & 'True SumPrint - Print summary data to .IfW.sum (flag) ', & ' OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-)', & '"Wind1VelX,Wind1VelY" - Wind velocity at point WindVxiList(1),WindVyiList(1),WindVziList(1). X, Y, and Z direction components. ' & diff --git a/modules/inflowwind/tests/test_steady_wind.F90 b/modules/inflowwind/tests/test_steady_wind.F90 index 3f6def1a54..6b0578402e 100644 --- a/modules/inflowwind/tests/test_steady_wind.F90 +++ b/modules/inflowwind/tests/test_steady_wind.F90 @@ -43,7 +43,7 @@ subroutine test_steady_wind_input_mult_heights() PriPath = "" InFileInfo = getInputFileData() - InFileInfo%Lines(8:11) = (/ & + InFileInfo%Lines(9:12) = (/ & ' 2 NWindVel - Number of points to output the wind velocity (0 to 9) ', & ' 0,0 WindVxiList - List of coordinates in the inertial X direction (m) ', & ' 0,0 WindVyiList - List of coordinates in the inertial Y direction (m) ', & diff --git a/modules/inflowwind/tests/test_uniform_wind.F90 b/modules/inflowwind/tests/test_uniform_wind.F90 index f5525cfb7e..13421e5da4 100644 --- a/modules/inflowwind/tests/test_uniform_wind.F90 +++ b/modules/inflowwind/tests/test_uniform_wind.F90 @@ -90,13 +90,13 @@ subroutine test_uniform_wind_direct_data() ! Results @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') - @assertEqual(0.0, p%UniformWind%TData(1)) - @assertEqual(0.1, p%UniformWind%TData(2)) - @assertEqual(999.9, p%UniformWind%TData(3)) + @assertEqual(0.0, p%FlowField%Uniform%Time(1)) + @assertEqual(0.1, p%FlowField%Uniform%Time(2)) + @assertEqual(999.9, p%FlowField%Uniform%Time(3)) - @assertEqual(12.0, p%UniformWind%V(1)) - @assertEqual(12.0, p%UniformWind%V(2)) - @assertEqual(12.0, p%UniformWind%V(3)) + @assertEqual(12.0, p%FlowField%Uniform%VelH(1)) + @assertEqual(12.0, p%FlowField%Uniform%VelH(2)) + @assertEqual(12.0, p%FlowField%Uniform%VelH(3)) end subroutine diff --git a/reg_tests/r-test b/reg_tests/r-test index b8cb84ed21..902a7b1918 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit b8cb84ed2154d1c4f89fa06a1d4be89c5749c12c +Subproject commit 902a7b19188daf83bb4089beac3d445c9305d0fc From 97bf5084eb177c628fdbafd2aacec1d550908116 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 28 Mar 2023 15:17:44 +0000 Subject: [PATCH 26/51] Fixed code to writes files from inflowwind_driver - lines swapped in Uniform_to_Grid3D - array dims swapped in Uniform_to_Grid3D - check for Z==0 in Uniform_to_Grid3D - array dims swapped in Grid3D_to_Uniform - fix real types in Grid3D_WriteBladed - fix swapped lines in Grid3D_WriteVTK which caused a nested directory to be created for each file (bug in existing code) --- modules/inflowwind/src/IfW_FlowField.f90 | 29 ++++---- modules/inflowwind/src/InflowWind_IO.f90 | 91 +++++++++++------------- 2 files changed, 54 insertions(+), 66 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index 0faf659c9a..ad538ff55b 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -1504,8 +1504,8 @@ subroutine Uniform_to_Grid3D(UF, InterpCubic, G3D, ErrStat, ErrMsg) G3D%DTime = 600.0_ReKi ! doesn't matter what the time step is G3D%NSteps = 2 ! "Number of time steps in the FF array else + G3D%DTime = minval(UF%Time(2:) - UF%Time(:size(UF%Time) - 1)) ! Delta time (seconds) if (G3D%DTime < 0.0001) then - G3D%DTime = minval(UF%Time(2:) - UF%Time(:size(UF%Time) - 1)) ! Delta time (seconds) call SetErrStat(ErrID_Fatal, "Smallest time step in uniform wind file is less that 0.0001 seconds. "// & "Increase the time step to convert to a FF file.", ErrStat, ErrMsg, RoutineName) return @@ -1521,7 +1521,7 @@ subroutine Uniform_to_Grid3D(UF, InterpCubic, G3D, ErrStat, ErrMsg) G3D%TotalTime = (G3D%NSteps - 1)*G3D%DTime ! The total time of the simulation (seconds) ! Allocate velocity array - call AllocAry(G3D%Vel, G3D%NZGrids, G3D%NYGrids, G3D%NComp, G3D%NSteps, 'G3D%Vel', ErrStat2, ErrMsg2) + call AllocAry(G3D%Vel, G3D%NComp, G3D%NYGrids, G3D%NZGrids, G3D%NSteps, 'G3D%Vel', ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -1553,9 +1553,14 @@ subroutine Uniform_to_Grid3D(UF, InterpCubic, G3D, ErrStat, ErrMsg) ! Calculate Z position PositionXYZ(3) = (iz - 1)*dz + G3D%GridBase - ! Calculate velocity at operating point and position, store in grid - G3D%Vel(:, iy, iz, it) = real(UniformField_GetVel(UF, op, PositionXYZ), SiKi) - + ! If Z is zero or less + if (PositionXYZ(3) <= 0.0_Reki) then + ! Set wind velocity to zero + G3D%Vel(:, iy, iz, it) = 0.0_SiKi + else + ! Calculate velocity at operating point and position, store in grid + G3D%Vel(:, iy, iz, it) = real(UniformField_GetVel(UF, op, PositionXYZ), SiKi) + end if end do ! iz end do ! iy end do ! it @@ -1656,11 +1661,8 @@ subroutine Grid3D_to_Uniform(G3D, UF, ErrStat, ErrMsg, SmoothingRadius) iz_ref = nint((G3D%RefHeight - G3D%GridBase)*G3D%InvDZ) + 1 UF%RefHeight = G3D%GridBase + (iz_ref - 1)/G3D%InvDZ ! make sure RefHt is on the grid - meanVel = 0.0_ReKi - do i = 1, UF%DataSize - meanVel = meanVel + G3D%Vel(iz_ref, iy_ref, :, i) - end do - meanVel = meanVel/UF%DataSize + ! Calculate mean value for each component through + meanVel = sum(G3D%Vel(:, iy_ref, iz_ref, :), dim=2)/UF%DataSize ! calculate the average upflow angle UF%AngleV = atan2(meanVel(3), TwoNorm(meanVel(1:2))) @@ -1682,7 +1684,7 @@ subroutine Grid3D_to_Uniform(G3D, UF, ErrStat, ErrMsg, SmoothingRadius) do i = 1, size(Vel, 4) do iy = 1, size(Vel, 2) do iz = 1, size(Vel, 1) - Vel(iz, iy, :, i) = matmul(transformMat, G3D%Vel(iz, iy, :, i)) + Vel(iz, iy, :, i) = matmul(transformMat, G3D%Vel(:, iy, iz, i)) end do end do end do @@ -1744,11 +1746,6 @@ subroutine Grid3D_to_Uniform(G3D, UF, ErrStat, ErrMsg, SmoothingRadius) end if end if - ! clean up - - if (allocated(Vel)) deallocate (Vel) - if (allocated(tmp)) deallocate (tmp) - end subroutine Grid3D_to_Uniform end module diff --git a/modules/inflowwind/src/InflowWind_IO.f90 b/modules/inflowwind/src/InflowWind_IO.f90 index b6889630a9..1321393ad4 100644 --- a/modules/inflowwind/src/InflowWind_IO.f90 +++ b/modules/inflowwind/src/InflowWind_IO.f90 @@ -1259,11 +1259,11 @@ subroutine IfW_Bladed_Init(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, !---------------------------------------------------------------------------- G3D%AddMeanAfterInterp = .false. - G3D%Z0 = G3D_InitInp%Z0 - G3D%PLExp = G3D_InitInp%PLExp - G3D%VLinShr = G3D_InitInp%VLinShr - G3D%HLinShr = G3D_InitInp%HLinShr - G3D%RefLength = G3D_InitInp%RefLength + G3D%Z0 = G3D_InitInp%Z0 + G3D%PLExp = G3D_InitInp%PLExp + G3D%VLinShr = G3D_InitInp%VLinShr + G3D%HLinShr = G3D_InitInp%HLinShr + G3D%RefLength = G3D_InitInp%RefLength if (InitInp%NativeBladedFmt) then @@ -2551,15 +2551,15 @@ subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) character(*), intent(out) :: ErrMsg !< Error message associated with the ErrStat character(*), parameter :: RoutineName = 'Grid3D_WriteBladed' - real(ReKi), parameter :: Tolerance = 0.0001 ! The largest difference between two numbers that are assumed to be equal + real(SiKi), parameter :: Tolerance = 0.0001 ! The largest difference between two numbers that are assumed to be equal integer(IntKi) :: ic, it, iy, iz - real(ReKi), allocatable :: MeanVal(:, :) - real(ReKi), allocatable :: SigmaGrid(:, :) - real(ReKi) :: TI(3) !< array containing turbulence intensity (for scaling factors) - real(ReKi) :: Sigma(3) !< array containing standard deviations (for scaling factors) - real(ReKi) :: Scl(3) !< array containing scaling factors - real(ReKi) :: Off(3) !< array containing offsets - real(ReKi) :: Tmp + real(SiKi), allocatable :: MeanVal(:, :) + real(SiKi), allocatable :: SigmaGrid(:, :) + real(SiKi) :: TI(3) !< array containing turbulence intensity (for scaling factors) + real(SiKi) :: Sigma(3) !< array containing standard deviations (for scaling factors) + real(SiKi) :: Scl(3) !< array containing scaling factors + real(SiKi) :: Off(3) !< array containing offsets + real(SiKi) :: Tmp real(ReKi) :: MeanWS_nonZero !< advection speed (mean wind speed at hub) real(ReKi) :: delta(3) integer(IntKi) :: ErrStat2 @@ -2568,7 +2568,7 @@ subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) ErrStat = ErrID_None ErrMsg = "" - delta = [G3D%MeanWS*G3D%DTime, 1.0_SiKi/G3D%InvDY, 1.0_SiKi/G3D%InvDZ] + delta = [G3D%MeanWS*G3D%DTime, 1.0_ReKi/G3D%InvDY, 1.0_ReKi/G3D%InvDZ] call AllocAry(MeanVal, G3D%NYGrids, G3D%NZGrids, "MeanVal", ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2582,23 +2582,15 @@ subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) do ic = 3, 1, -1 ! mean values: - MeanVal = 0.0_SiKi - do it = 1, G3D%NSteps - MeanVal = MeanVal + G3D%Vel(ic, :, :, it) - end do - MeanVal = MeanVal/real(G3D%NSteps, SiKi) + MeanVal = sum(G3D%Vel(ic, :, :, :),dim=3)/G3D%NSteps ! standard deviations (with 1/N scaling factor): - SigmaGrid = 0.0_SiKi - do it = 1, size(G3D%Vel, 4) - SigmaGrid = SigmaGrid + G3D%Vel(ic, :, :, it)**2 - end do - SigmaGrid = SigmaGrid/G3D%NSteps - SigmaGrid = sqrt(max(SigmaGrid - MeanVal**2, 0.0_ReKi)) + SigmaGrid = sum(G3D%Vel(ic, :, :, :)**2,dim=3)/G3D%NSteps + SigmaGrid = sqrt(max(SigmaGrid - MeanVal**2, 0.0_SiKi)) ! now get the average standard deviation for each component: Sigma(ic) = sum(SigmaGrid)/size(SigmaGrid) ! get the average sigma over the grid - Sigma(ic) = max(100.0_ReKi*Tolerance, Sigma(ic)) ! make sure this scaling isn't too small + Sigma(ic) = max(100.0_SiKi*Tolerance, Sigma(ic)) ! make sure this scaling isn't too small end do @@ -2607,10 +2599,10 @@ subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) ! in this BLADED-style binary output. Tmp is |V-UHub| ! Get the range of wind speed values for scaling in BLADED-format .wnd files Tmp = max(abs(maxval(G3D%Vel(:, :, 1, :)) - G3D%MeanWS), abs(minval(G3D%Vel(1, :, :, :)) - G3D%MeanWS)) - Sigma(1) = max(Sigma(1), 0.05_ReKi*Tmp) + Sigma(1) = max(Sigma(1), 0.05_SiKi*Tmp) do ic = 2, 3 ! put the abs() after the maxval() and minval() to avoid stack-overflow issues with large wind files - Sigma(ic) = max(Sigma(ic), 0.05_ReKi*abs(maxVAL(G3D%Vel(ic, :, :, :))), 0.05_ReKi*abs(minval(G3D%Vel(ic, :, :, :)))) + Sigma(ic) = max(Sigma(ic), 0.05_SiKi*abs(maxVAL(G3D%Vel(ic, :, :, :))), 0.05_SiKi*abs(minval(G3D%Vel(ic, :, :, :)))) end do ! Put normalizing factors into the summary file. The user can use them to @@ -2663,9 +2655,9 @@ subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return - write (unit) INT(-99, B2Ki) ! -99 = New Bladed format - write (unit) INT(4, B2Ki) ! 4 = improved von karman (not used, but needed for next 7 inputs) - write (unit) INT(size(G3D%Vel, 3), B4Ki) ! size(FFWind,3) = 3 = number of wind components + write (unit) int(-99, B2Ki) ! -99 = New Bladed format + write (unit) int(4, B2Ki) ! 4 = improved von karman (not used, but needed for next 7 inputs) + write (unit) int(size(G3D%Vel, 3), B4Ki) ! size(FFWind,3) = 3 = number of wind components write (unit) real(45.0_SiKi, SiKi) ! Latitude (degrees) (informational, not used in FAST) write (unit) real(0.03_SiKi, SiKi) ! Roughness length (m) (informational, not used in FAST) write (unit) real(G3D%RefHeight, SiKi) ! Reference Height (m) (informational, not used in FAST) @@ -2676,28 +2668,28 @@ subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) write (unit) real(delta(3), SiKi) ! grid spacing in vertical direction, in m write (unit) real(delta(2), SiKi) ! grid spacing in lateral direction, in m write (unit) real(delta(1), SiKi) ! grid spacing in longitudinal direciton, in m - write (unit) INT(G3D%NSteps/2, B4Ki) ! half the number of points in alongwind direction + write (unit) int(G3D%NSteps/2, B4Ki) ! half the number of points in alongwind direction write (unit) real(MeanWS_nonZero, SiKi) ! the mean wind speed in m/s write (unit) real(0, SiKi) ! the vertical length scale of the longitudinal component in m write (unit) real(0, SiKi) ! the lateral length scale of the longitudinal component in m write (unit) real(0, SiKi) ! the longitudinal length scale of the longitudinal component in m - write (unit) INT(0, B4Ki) ! an unused integer - write (unit) INT(0, B4Ki) ! the random number seed - write (unit) INT(G3D%NZGrids, B4Ki) ! the number of grid points vertically - write (unit) INT(G3D%NYGrids, B4Ki) ! the number of grid points laterally - write (unit) INT(0, B4Ki) ! the vertical length scale of the lateral component, not used - write (unit) INT(0, B4Ki) ! the lateral length scale of the lateral component, not used - write (unit) INT(0, B4Ki) ! the longitudinal length scale of the lateral component, not used - write (unit) INT(0, B4Ki) ! the vertical length scale of the vertical component, not used - write (unit) INT(0, B4Ki) ! the lateral length scale of the vertical component, not used - write (unit) INT(0, B4Ki) ! the longitudinal length scale of the vertical component, not used + write (unit) int(0, B4Ki) ! an unused integer + write (unit) int(0, B4Ki) ! the random number seed + write (unit) int(G3D%NZGrids, B4Ki) ! the number of grid points vertically + write (unit) int(G3D%NYGrids, B4Ki) ! the number of grid points laterally + write (unit) int(0, B4Ki) ! the vertical length scale of the lateral component, not used + write (unit) int(0, B4Ki) ! the lateral length scale of the lateral component, not used + write (unit) int(0, B4Ki) ! the longitudinal length scale of the lateral component, not used + write (unit) int(0, B4Ki) ! the vertical length scale of the vertical component, not used + write (unit) int(0, B4Ki) ! the lateral length scale of the vertical component, not used + write (unit) int(0, B4Ki) ! the longitudinal length scale of the vertical component, not used ! Scaling value to convert wind speeds to 16-bit integers do ic = 1, 3 - if (.not. EqualRealNos(Sigma(ic), 0.0_ReKi)) then + if (.not. EqualRealNos(Sigma(ic), 0.0_SiKi)) then Scl(ic) = 1000.0/(Sigma(ic)) else - Scl(ic) = 1.0_ReKi + Scl(ic) = 1.0_SiKi end if end do @@ -2744,14 +2736,13 @@ subroutine Grid3D_WriteVTK(G3D, FileRootName, unit, ErrStat, ErrMsg) character(ErrMsgLen) :: ErrMsg2 call GetPath(FileRootName, RootPathName) + RootPathName = trim(RootPathName)//PathSep//"vtk" + call MkDir(trim(RootPathName)) ! make this directory if it doesn't already exist ! Loop through time steps do i = 1, G3D%NSteps ! Create the output vtk file with naming /vtk/DisYZ.t.vtk - RootPathName = trim(RootPathName)//PathSep//"vtk" - call MkDir(trim(RootPathName)) ! make this directory if it doesn't already exist - FileName = trim(RootPathName)//PathSep//"DisYZ.t"//trim(num2lstr(i))//".vtp" ! see WrVTK_SP_header @@ -2768,7 +2759,7 @@ subroutine Grid3D_WriteVTK(G3D, FileRootName, unit, ErrStat, ErrMsg) ! and the right-most dimension is Z (see WrVTK_SP_vectors3D) write (unit, '(A,3(i5,1X))') 'DIMENSIONS ', 1, G3D%NYGrids, G3D%NZGrids write (unit, '(A,3(f10.2,1X))') 'ORIGIN ', G3D%InitXPosition, -G3D%YHWid, G3D%GridBase - write (unit, '(A,3(f10.2,1X))') 'SPACING ', 0.0_ReKi, 1.0_SiKi/G3D%InvDY, 1.0_SiKi/G3D%InvDZ + write (unit, '(A,3(f10.2,1X))') 'SPACING ', 0.0_ReKi, 1.0_ReKi/G3D%InvDY, 1.0_ReKi/G3D%InvDZ write (unit, '(A,i5)') 'POINT_DATA ', G3D%NYGrids*G3D%NZGrids write (unit, '(A)') 'VECTORS DisYZ float' @@ -2796,7 +2787,7 @@ subroutine Grid3D_WriteHAWC(G3D, FileRootName, unit, ErrStat, ErrMsg) character(*), parameter :: Comp(3) = (/'u', 'v', 'w'/) real(ReKi) :: delta(3) integer(IntKi) :: IC, IX, IY, IZ - real(ReKi), allocatable :: MeanVal(:) + real(SiKi), allocatable :: MeanVal(:) integer(IntKi) :: ErrStat2 character(ErrMsgLen) :: ErrMsg2 character(1024) :: RootWithoutPathName @@ -2863,7 +2854,7 @@ subroutine Grid3D_WriteHAWC(G3D, FileRootName, unit, ErrStat, ErrMsg) do IX = 1, G3D%NSteps do IY = G3D%NYGrids, 1, -1 - write (unit, IOSTAT=ErrStat2) G3D%Vel(ic, iy, :, ix) - MeanVal + write (unit, IOSTAT=ErrStat2) real(G3D%Vel(ic, iy, :, ix) - MeanVal, SiKi) end do end do From 4240273d82c635b8da6405ac5ff10ef647478d9b Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 28 Mar 2023 16:44:34 +0000 Subject: [PATCH 27/51] Fixed bug Grid3DField_GetBoundsT for periodic wind --- modules/inflowwind/src/IfW_FlowField.f90 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index ad538ff55b..9980f82ab1 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -988,9 +988,13 @@ subroutine Grid3DField_GetBoundsT(PosX, DT) ! in distance, X: InputInfo%PosX - p%InitXPosition - TIME*p%MeanWS TimeShifted = real(Time, ReKi) + (G3D%InitXPosition - PosX)*G3D%InvMWS - ! If field is periodic and time is after total time, remove total time - if (G3D%Periodic .and. TimeShifted > G3D%TotalTime) then - TimeShifted = TimeShifted - G3D%TotalTime + ! If field is periodic + if (G3D%Periodic) then + TimeShifted = MODULO(TimeShifted, G3D%TotalTime) + ! If TimeShifted is a very small negative number, + ! modulo returns the incorrect value due to internal rounding errors. + ! See bug report #471 + if (TimeShifted == G3D%TotalTime) TimeShifted = 0.0_ReKi end if ! Get position on T grid From cb31cdee525da89d643833ee78b7dcdbb38b9a44 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 28 Mar 2023 16:45:03 +0000 Subject: [PATCH 28/51] Updated FASTWrapper for FlowField structure --- glue-codes/fast-farm/src/FASTWrapper.f90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glue-codes/fast-farm/src/FASTWrapper.f90 b/glue-codes/fast-farm/src/FASTWrapper.f90 index 6c0bdc47fa..058943b0c6 100644 --- a/glue-codes/fast-farm/src/FASTWrapper.f90 +++ b/glue-codes/fast-farm/src/FASTWrapper.f90 @@ -185,7 +185,7 @@ SUBROUTINE FWrap_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init return end if - call move_alloc(m%Turbine%IfW%m%FDext%V, u%Vdist_High) + call move_alloc(m%Turbine%IfW%p%FlowField%Grid4D%Vel, u%Vdist_High) !................. @@ -557,7 +557,7 @@ SUBROUTINE FWrap_CalcOutput(p, u, y, m, ErrStat, ErrMsg) ErrMsg = '' ! put this back! - call move_alloc(m%Turbine%IfW%m%FDext%V, u%Vdist_High) + call move_alloc(m%Turbine%IfW%p%FlowField%Grid4D%Vel, u%Vdist_High) ! Turbine-dependent commands to the super controller: @@ -713,8 +713,8 @@ SUBROUTINE FWrap_SetInputs(u, m, t) REAL(DbKi), INTENT(IN ) :: t !< current simulation time ! set the 4d-wind-inflow input array (a bit of a hack [simplification] so that we don't have large amounts of data copied in multiple data structures): - call move_alloc(u%Vdist_High, m%Turbine%IfW%m%FDext%V) - m%Turbine%IfW%m%FDext%TgridStart = t + call move_alloc(u%Vdist_High, m%Turbine%IfW%p%FlowField%Grid4D%Vel) + m%Turbine%IfW%p%FlowField%Grid4D%TimeStart = t ! do something with the inputs from the super-controller: if ( m%Turbine%p_FAST%UseSC ) then From 2621d3151bf3e17d9d2c635ac11b13dff66efb6e Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 28 Mar 2023 17:48:55 +0000 Subject: [PATCH 29/51] Check IfW acceleration data in test --- reg_tests/executeInflowwindRegressionCase.py | 16 ++++++++++++++++ reg_tests/r-test | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/reg_tests/executeInflowwindRegressionCase.py b/reg_tests/executeInflowwindRegressionCase.py index d06b802e12..e1dab6f6da 100644 --- a/reg_tests/executeInflowwindRegressionCase.py +++ b/reg_tests/executeInflowwindRegressionCase.py @@ -112,6 +112,22 @@ testData, testInfo, _ = pass_fail.readFASTOut(localOutFile) baselineData, baselineInfo, _ = pass_fail.readFASTOut(baselineOutFile) +# Append acceleration data if present +localOutFileAcc = os.path.join(testBuildDirectory, "Points.Acceleration.dat") +baselineOutFileAcc = os.path.join(targetOutputDirectory, "Points.Acceleration.dat") +if os.path.exists(baselineOutFileAcc): + rtl.validateFileOrExit(localOutFileAcc) + rtl.validateFileOrExit(baselineOutFileAcc) + testDataAcc, testInfoAcc, _ = pass_fail.readFASTOut(localOutFile) + testInfo['attribute_names'] += [n+'a' for n in testInfoAcc['attribute_names'][4:]] + testInfo['attribute_units'] += [u+'a' for u in testInfoAcc['attribute_units'][4:]] + testData = np.hstack([testData, testDataAcc[:,4:]]) + + baselineDataAcc, baselineInfoAcc, _ = pass_fail.readFASTOut(baselineOutFile) + baselineInfo['attribute_names'] += [n+'a' for n in testInfoAcc['attribute_names'][4:]] + baselineInfo['attribute_units'] += [u+'a' for u in testInfoAcc['attribute_units'][4:]] + baselineData = np.hstack([baselineData, baselineDataAcc[:,4:]]) + passing_channels = pass_fail.passing_channels(testData.T, baselineData.T, rtol, atol) passing_channels = passing_channels.T diff --git a/reg_tests/r-test b/reg_tests/r-test index 902a7b1918..d7f5f0d3ac 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 902a7b19188daf83bb4089beac3d445c9305d0fc +Subproject commit d7f5f0d3ac9986b15ed8bb6e7bf7bdc0020efb1d From cf5c40647d6c40b877f00c76ac5af800d7bcef76 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Tue, 28 Mar 2023 17:55:34 +0000 Subject: [PATCH 30/51] Update regression 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 d7f5f0d3ac..512f287927 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit d7f5f0d3ac9986b15ed8bb6e7bf7bdc0020efb1d +Subproject commit 512f287927b50bc6aab45554319140d0fbeb742a From ce12a866f55faef50b8934a0e6373654414a6d63 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 5 Apr 2023 19:39:42 +0000 Subject: [PATCH 31/51] Integrated IfW BoxExceed --- modules/inflowwind/src/IfW_FFWind_Base.f90 | 1593 ----------------- modules/inflowwind/src/IfW_FFWind_Base.txt | 66 - modules/inflowwind/src/IfW_FlowField.f90 | 586 ++++-- modules/inflowwind/src/IfW_FlowField.txt | 3 +- .../inflowwind/src/IfW_FlowField_Types.f90 | 170 ++ modules/inflowwind/src/InflowWind.f90 | 1526 ++++++++++------ modules/inflowwind/src/InflowWind_Driver.f90 | 4 +- modules/inflowwind/src/InflowWind_Types.f90 | 7 + reg_tests/r-test | 2 +- 9 files changed, 1611 insertions(+), 2346 deletions(-) delete mode 100644 modules/inflowwind/src/IfW_FFWind_Base.f90 delete mode 100644 modules/inflowwind/src/IfW_FFWind_Base.txt diff --git a/modules/inflowwind/src/IfW_FFWind_Base.f90 b/modules/inflowwind/src/IfW_FFWind_Base.f90 deleted file mode 100644 index 8fd329c6ef..0000000000 --- a/modules/inflowwind/src/IfW_FFWind_Base.f90 +++ /dev/null @@ -1,1593 +0,0 @@ -!> This module uses full-field binary wind files to determine the wind inflow. -!! This module assumes that the origin, (0,0,0), is located at the tower centerline at ground level, -!! and that all units are specified in the metric system (using meters and seconds). -!! Data is shifted by half the grid width to account for turbine yaw (so that data in the X -!! direction actually starts at -1*p%FFYHWid meters). -MODULE IfW_FFWind_Base -!! -!! Created 25-Sep-2009 by B. Jonkman, National Renewable Energy Laboratory -!! using subroutines and modules from AeroDyn v12.58 -!! -!!---------------------------------------------------------------------------------------------------- -!! Feb 2013 v2.00.00 A. Platt -!! -- updated to the new framework -!! -- Modified to use NWTC_Library v. 2.0 -!! -- Note: Jacobians are not included in this version. -!! -!********************************************************************************************************************************** -! LICENSING -! Copyright (C) 2015-2016 National Renewable Energy Laboratory -! -! This file is part of InflowWind. -! -! Licensed under the Apache License, Version 2.0 (the "License"); -! you may not use this file except in compliance with the License. -! You may obtain a copy of the License at -! -! http://www.apache.org/licenses/LICENSE-2.0 -! -! Unless required by applicable law or agreed to in writing, software -! distributed under the License is distributed on an "AS IS" BASIS, -! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -! See the License for the specific language governing permissions and -! limitations under the License. -! -!********************************************************************************************************************************** - - USE NWTC_Library - USE IfW_FFWind_Base_Types - - IMPLICIT NONE - - - INTEGER(IntKi), PARAMETER :: WindProfileType_None = -1 !< don't add a mean wind profile - INTEGER(IntKi), PARAMETER :: WindProfileType_Constant = 0 !< constant wind - INTEGER(IntKi), PARAMETER :: WindProfileType_Log = 1 !< logarithmic - INTEGER(IntKi), PARAMETER :: WindProfileType_PL = 2 !< power law - - INTEGER(IntKi), PARAMETER :: ScaleMethod_None = 0 !< no scaling - INTEGER(IntKi), PARAMETER :: ScaleMethod_Direct = 1 !< direct scaling factors - INTEGER(IntKi), PARAMETER :: ScaleMethod_StdDev = 2 !< requested standard deviation - - -CONTAINS -!==================================================================================================== - -!==================================================================================================== -!> This routine acts as a wrapper for the GetWindSpeed routine. It steps through the array of input -!! positions and calls the GetWindSpeed routine to calculate the velocities at each point. -SUBROUTINE IfW_FFWind_CalcOutput(Time, PositionXYZ, p, m, Velocity, ErrStat, ErrMsg) - - IMPLICIT NONE - - - ! Passed Variables - REAL(DbKi), INTENT(IN ) :: Time !< time from the start of the simulation - REAL(ReKi), INTENT(IN ) :: PositionXYZ(:,:) !< Array of XYZ coordinates, 3xN - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - TYPE(IfW_FFWind_MiscVarType), INTENT(INOUT) :: m !< MiscVar - REAL(ReKi), INTENT(INOUT) :: Velocity(:,:) !< Velocity output at Time (Set to INOUT so that array does not get deallocated) - - ! Error handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< The error message - - ! local variables - INTEGER(IntKi) :: NumPoints ! Number of points specified by the PositionXYZ array - LOGICAL :: GridExceedAllow ! is this point allowed to exceed bounds of wind grid - LOGICAL :: GridExtrap ! did this point fall outside the wind box and get extrapolated? - - ! local counters - INTEGER(IntKi) :: PointNum ! a loop counter for the current point - - ! temporary variables - INTEGER(IntKi) :: TmpErrStat ! temporary error status - CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message - CHARACTER(*), PARAMETER :: RoutineName = 'IfW_FFWind_CalcOutput' - - - !------------------------------------------------------------------------------------------------- - ! Check that the module has been initialized. - !------------------------------------------------------------------------------------------------- - - ErrStat = ErrID_None - ErrMsg = '' - - !------------------------------------------------------------------------------------------------- - ! Initialize some things - !------------------------------------------------------------------------------------------------- - - - ! The array is transposed so that the number of points is the second index, x/y/z is the first. - ! This is just in case we only have a single point, the SIZE command returns the correct number of points. - NumPoints = SIZE(PositionXYZ,2) - - - ! Step through all the positions and get the velocities - !OMP PARALLEL default(shared) if(NumPoints>1000) - !OMP do private(PointNum, TmpErrStat, TmpErrMsg ) schedule(runtime) - DO PointNum = 1, NumPoints - - ! is this point allowed beyond the bounds of the wind box? - GridExceedAllow = p%BoxExceedAllowF .and. ( PointNum >= p%BoxExceedAllowIdx ) - - ! Calculate the velocity for the position - Velocity(:,PointNum) = FFWind_Interp(Time,PositionXYZ(:,PointNum),p,GridExceedAllow,GridExtrap,TmpErrStat,TmpErrMsg) - - ! Error handling - IF (TmpErrStat /= ErrID_None) THEN ! adding this so we don't have to convert numbers to strings every time - !OMP CRITICAL ! Needed to avoid data race on ErrStat and ErrMsg - ErrStat = ErrID_None - ErrMsg = "" - CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName//" [position=("// & - TRIM(Num2LStr(PositionXYZ(1,PointNum)))//", "// & - TRIM(Num2LStr(PositionXYZ(2,PointNum)))//", "// & - TRIM(Num2LStr(PositionXYZ(3,PointNum)))//") in wind-file coordinates]" ) - !OMP END CRITICAL - END IF - - if (GridExceedAllow .and. GridExtrap .and. (.not. m%BoxExceedWarned)) then - !$OMP CRITICAL ! Needed to avoid data race on issuing warning - call WrScr( "WARNING from InflowWind:") - call WrScr( "------------------------") - call WrScr( " Grid point extrapolated beyond bounds of full-field wind grid [position=(" // & - TRIM(Num2LStr(PositionXYZ(1,PointNum)))//", "//TRIM(Num2LStr(PositionXYZ(2,PointNum)))//", " // & - TRIM(Num2LStr(PositionXYZ(3,PointNum)))//") in wind-file coordinates, T="//trim(Num2LStr(Time))//"]."//NewLine// & - "This only occurs for free vortex wake points or LidarSim measurement locations. " // & - "Use a larger full-field wind grid if the simulation yields undesirable results. Further warnings are suppressed.") - call WrScr( "------------------------") - m%BoxExceedWarned = .TRUE. - !$OMP END CRITICAL - endif - - ENDDO - !OMP END DO - !OMP END PARALLEL - IF (ErrStat >= AbortErrLev) RETURN ! Return cannot be in parallel loop - - IF (p%AddMeanAfterInterp) THEN - DO PointNum = 1, NumPoints - Velocity(1,PointNum) = Velocity(1,PointNum) + CalculateMeanVelocity(p,PositionXYZ(3,PointNum),PositionXYZ(2,PointNum)) - ENDDO - END IF - - - RETURN - -END SUBROUTINE IfW_FFWind_CalcOutput -!+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- -!> This function is used to interpolate into the full-field wind array or tower array if it has -!! been defined and is necessary for the given inputs. It receives X, Y, Z and -!! TIME from the calling routine. It then computes a time shift due to a nonzero X based upon -!! the average windspeed. The modified time is used to decide which pair of time slices to interpolate -!! within and between. After finding the two time slices, it decides which four grid points bound the -!! (Y,Z) pair. It does a bilinear interpolation for each time slice. Linear interpolation is then used -!! to interpolate between time slices. This routine assumes that X is downwind, Y is to the left when -!! looking downwind and Z is up. It also assumes that no extrapolation will be needed. -!! -!! If tower points are used, it assumes the velocity at the ground is 0. It interpolates between -!! heights and between time slices, but ignores the Y input. -!! -!! 11/07/1994 - Created by M. Buhl from the original TURBINT. -!! 09/25/1997 - Modified by M. Buhl to use f90 constructs and new variable names. Renamed to FF_Interp. -!! 09/23/2009 - Modified by B. Jonkman to use arguments instead of modules to determine time and position. -!! Height is now relative to the ground -!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 -FUNCTION FFWind_Interp(Time, Position, p, GridExceedAllow, GridExtrap, ErrStat, ErrMsg) - - IMPLICIT NONE - - CHARACTER(*), PARAMETER :: RoutineName="FFWind_Interp" - - REAL(DbKi), INTENT(IN ) :: Time !< time (s) - REAL(ReKi), INTENT(IN ) :: Position(3) !< takes the place of XGrnd, YGrnd, ZGrnd - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - LOGICAL, INTENT(IN ) :: GridExceedAllow ! is this point allowed to exceed bounds of wind grid - LOGICAL, INTENT(INOUT) :: GridExtrap ! Extrapolation outside grid is allowed and point lies outside grid - REAL(ReKi) :: FFWind_Interp(3) !< The U, V, W velocities - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< error status - CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message - - ! Local Variables: - - REAL(ReKi) :: TimeShifted - REAL(ReKi),PARAMETER :: Tol = 1.0E-3 ! a tolerance for determining if two reals are the same (for extrapolation) - REAL(ReKi) :: T - REAL(ReKi) :: TGRID - REAL(ReKi) :: Y - REAL(ReKi) :: YGRID - REAL(ReKi) :: Z - REAL(ReKi) :: ZGRID - REAL(ReKi) :: N(8) ! array for holding scaling factors for the interpolation algorithm - REAL(ReKi) :: u(8) ! array for holding the corner values for the interpolation algorithm across a cubic volume - REAL(ReKi) :: M(4) ! array for holding scaling factors for the interpolation algorithm -- 4 point method for tower interp - REAL(ReKi) :: v(4) ! array for holding the corner values for the interpolation algorithm across an area -- 4 point method for tower interp - ! Arrays for scaling and corner factors for interpolation in grid exceed case between tower to ground to grid-bottom - REAL(ReKi) :: NGe(10) ! scaling factors - REAL(ReKi) :: uGe(10) ! the corner values - - INTEGER(IntKi) :: IDIM - INTEGER(IntKi) :: ITHI - INTEGER(IntKi) :: ITLO - INTEGER(IntKi) :: IYHI - INTEGER(IntKi) :: IYLO - INTEGER(IntKi) :: IZHI - INTEGER(IntKi) :: IZLO - - LOGICAL :: AboveGridBottom - - !> If GridExceedAllow is true, values for this point will be interpolated between the value at the edge of the grid - !! and the average value over Y for that (X,Z,T) location. This method is not ideal but should yield relatively - !! reasonable results for wake convection (OLAF points) and Lidar measurements far off the grid. A better method of - !! interpolation above the grid using the wind profile would likely be better, but the resulting impact on the - !! physics of the turbine is expected to be limited. - !! - !! For points above the top of the grid, the value is interpolated between the average value for the top of the grid - !! and the closest (X,Y,Z,T) point (interpolated over half grid height span, then held constant over remainder of Z). - !! - !! For points below the top of the grid, the value is interpolated between the Y averaged value for that (X,Z,T) - !! location and the closest (X,Y,Z,T) point (interpolated over half grid width span, then held constant over all - !! points further out in Y. - !! - !! NOTE: to test the effects of grid exceeded points, run the driver with a grid output larger than the wind grid - !! for a single timestep (set in driver input file IfW_driver.inp) using the command: - !! - !! inflowwind_driver -BoxExceedAllow IfW_driver.inp - !! - !! and plot the resulting surfaces representing the U,V,W at a given YZ plane at time T (results given in - !! output file IfW_driver.WindGrid.out). - INTEGER(IntKi) :: IY2 - REAL(ReKi) :: Z2 ! for points away from tower below grid -- distance from ground to grid bottom (-1 to 1 range) - REAL(ReKi) :: YtZg ! distance from grid to tower along a right angled corner line from grid bottom through point to tower - REAL(ReKi) :: YtZgG ! distance from grid to tower along a right angled corner line from grid bottom through point to tower - LOGICAL :: GridExceedY ! point is beyond bounds of grid in Y. Interpolate to average Z level over one grid width if GridExceedAllow - LOGICAL :: GridExceedZmax ! point is beyond upper bounds of grid in Z. Interpolate to average Z value at top of box over one half grid height if GridExceedAllow - LOGICAL :: GridExceedZmin ! point is below lower bounds of grid in Z. Interpolate to average Z value at top of box over one half grid height if GridExceedAllow - - !------------------------------------------------------------------------------------------------- - ! Initialize variables - !------------------------------------------------------------------------------------------------- - - FFWind_Interp(:) = 0.0_ReKi ! the output velocities (in case p%NFFComp /= 3 or error) - - ErrStat = ErrID_None - ErrMsg = "" - GridExceedY = .false. - GridExceedZmax = .false. - GridExceedZmin = .false. - GridExtrap = .false. - - !------------------------------------------------------------------------------------------------- - ! By definition, wind below the ground is always zero (no turbulence, either). - !------------------------------------------------------------------------------------------------- - IF ( Position(3) <= 0.0_ReKi ) RETURN - - !------------------------------------------------------------------------------------------------- - ! get the bounding limits for T, Z, and Y - !------------------------------------------------------------------------------------------------- - call GetTBounds(); if (ErrStat >= AbortErrLev) return - call GetZBounds(); if (ErrStat >= AbortErrLev) return - if (GridExceedAllow) then - call GetYBoundsGridExceed(); - else - call GetYBounds(); if (ErrStat >= AbortErrLev) return - endif - - - !------------------------------------------------------------------------------------------------- - ! Calculate the value - !------------------------------------------------------------------------------------------------- - IF ( AboveGridBottom ) THEN ! The tower points don't use this - ! get the Y indices amd get interpolation values - call GetInterpWeights3D(); - - if ( GridExtrap ) then ! only true if allowed and beyond grid - - !-------------------------------------------------------- - ! Interpolate from grid edge averaged values at (Z,T) at - ! boundary at half grid width beyond - ! - ! NOTE: above grid top, the interpolate to value of average - ! across top of grid (Y values) at +FFZHWid - if ( GridExceedY ) then - if ( GridExceedZmax ) then - ! Above the grid and beyond +/-Y - ! NOTE: IZLO==IZHI -- top of grid - ! IZHI -- top of grid+FFZHWid - ! IYLO==IYHI -- side of grid point is beyond - do IDIM=1,p%NFFComp ! all the components - u(1) = p%FFAvgData( IZHI, IDIM, ITLO ) - u(2) = p%FFAvgData( IZHI, IDIM, ITLO ) - u(3) = p%FFAvgData( IZLO, IDIM, ITLO ) - u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) - u(5) = p%FFAvgData( IZHI, IDIM, ITHI ) - u(6) = p%FFAvgData( IZHI, IDIM, ITHI ) - u(7) = p%FFAvgData( IZLO, IDIM, ITHI ) - u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) - FFWind_Interp(IDIM) = SUM ( N * u ) - end do !IDIM - else - ! Beyond +/-Y of grid, but within +/-Z - ! NOTE: IYLO==IYHI -- side of grid point is beyond - do IDIM=1,p%NFFComp ! all the components - u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) - u(2) = p%FFAvgData( IZHI, IDIM, ITLO ) - u(3) = p%FFAvgData( IZLO, IDIM, ITLO ) - u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) - u(5) = p%FFData( IZHI, IYLO, IDIM, ITHI ) - u(6) = p%FFAvgData( IZHI, IDIM, ITHI ) - u(7) = p%FFAvgData( IZLO, IDIM, ITHI ) - u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) - FFWind_Interp(IDIM) = SUM ( N * u ) - end do !IDIM - endif - else - ! Above the grid, but within +/-Y - ! NOTE: IZLO -- top of grid - ! IZHI -- top of grid+FFZHWid - do IDIM=1,p%NFFComp ! all the components - u(1) = p%FFAvgData( IZHI, IDIM, ITLO ) - u(2) = p%FFAvgData( IZHI, IDIM, ITLO ) - u(3) = p%FFData( IZLO, IYHI, IDIM, ITLO ) - u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) - u(5) = p%FFAvgData( IZHI, IDIM, ITHI ) - u(6) = p%FFAvgData( IZHI, IDIM, ITHI ) - u(7) = p%FFData( IZLO, IYHI, IDIM, ITHI ) - u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) - FFWind_Interp(IDIM) = SUM ( N * u ) - end do !IDIM - endif - else - !-------------------------------------------------------- - ! Interpolate on the grid itself - DO IDIM=1,p%NFFComp ! all the components - u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) - u(2) = p%FFData( IZHI, IYHI, IDIM, ITLO ) - u(3) = p%FFData( IZLO, IYHI, IDIM, ITLO ) - u(4) = p%FFData( IZLO, IYLO, IDIM, ITLO ) - u(5) = p%FFData( IZHI, IYLO, IDIM, ITHI ) - u(6) = p%FFData( IZHI, IYHI, IDIM, ITHI ) - u(7) = p%FFData( IZLO, IYHI, IDIM, ITHI ) - u(8) = p%FFData( IZLO, IYLO, IDIM, ITHI ) - FFWind_Interp(IDIM) = SUM ( N * u ) - END DO !IDIM - endif - - ELSE - - IF ( GridExtrap .and. GridExceedZmin ) THEN - ! Below bottom of grid requires some special logic depending if tower - ! data exists, and if outside the Y bounds of the grid. - ! - ! Tower influence: - ! Extrapolating between the bottom of the grid, the ground, and the - ! tower is a bit of an exercise in data fabrication. The tower typically - ! is an expoential decline from the bottom of the grid, but may not go - ! to zero at the ground. Beyond the tower, there is no information from - ! the wind file regarding interpolation between the grid and ground, so - ! 1) a linear interpolation is sometimes used when no tower points - ! exist, or - ! 2) the tower values are simply assumed across this region. - ! The problem with 2) is it is not necessarily continuous at the bottom - ! of the grid. This is not historically an issue since the tower is - ! usually the only thing that shows up in that region (blades are still - ! moving within the grid), but may occasionally appear when the tower - ! moves in a floating offshore system. - ! - ! For lidar or free wake propogation, a continuous function is necessary - ! to prevent jittery measurements or tearing of the wake vortices due - ! to dramatic shear. To address this, the tower influence is calculated - ! as across the region as follows: - ! 1) weighting of tower vs. bottom of grid influence based on how - ! close the point is to these two lines. - ! 2) tower influence may exist at grid edge between grid corner and - ! ground, so influence of tower at this imaginary line is used to - ! extrapolate beyond the grid edge in the +/-Y directions. Linear - ! 3) the average value across Y at the bottom of the grid at time T - ! used as a constant value at Z of bottom of grid and linearly - ! interpolated to the ground for abs(y)>2*FFYHWid. - ! 4) linear interpolation is used between 2*FFHWid > abs(y) > 2*FFHWid - ! The above assumptions give continuous wind functions, though not smooth. - ! It is far from ideal, but at least should allow the simulation to run - ! without undue influence of discontinueties in the wind velocities. If - ! this extrapolation is not sufficient, then simply make the grid extend - ! all the way to the ground. - if ( GridExceedY ) then - if (p%NTGrids < 1) then - ! interp between bottom of grid and ground when outside Y bounds of grid and no tower - ZGRID = Position(3)/p%GridBase - Z = 2.0_ReKi * ZGRID - 1.0_ReKi - IZHI = 1 - IZHI = 0 - - ! Get standard interpolation weightings - call GetInterpWeights3D(); - - ! Beyond the left and right bounds of grid. Linear interpolate - ! between: - ! bottom of Yavg bottom corner of grid - ! ground ground - do IDIM=1,p%NFFComp ! all the components - u(1) = p%FFData( 1, IYLO, IDIM, ITLO ) - u(2) = p%FFAvgData( 1, IDIM, ITLO ) - u(3) = 0.0_ReKi ! ground - u(4) = 0.0_ReKi ! ground - u(5) = p%FFData( 1, IYLO, IDIM, ITHI ) - u(6) = p%FFAvgData( 1, IDIM, ITHI ) - u(7) = 0.0_ReKi ! ground - u(8) = 0.0_ReKi ! ground - FFWind_Interp(IDIM) = SUM ( N * u ) - enddo - else ! Tower grid - ! YtZg - distance from grid bottom to tower along a right angled corner - ! line from grid bottom through point to tower. Used to change - ! weighting between grid and tower influece (kind of approximates - ! a spherical weighting, but without considering more points along - ! grid bottom or tower). - ! YtZgG- distance from ground bottom to point along a right angled corner - ! line from ground through point to tower. Used to change - ! weighting between grid and tower influece at +/-p%FFYHWid - ! (similar to YtZg). - ! Z2 - scaled distance between bottom edge of grid and ground (in z) - ! Y - scaled distance between IYLO-IYHI between grid edge and +/-2*p%FFYHWid - ! Z - scaled distance between IZLO-IZHI olong tower line - ! IYLO - grid corner point index - ! IZHI - tower upper point index - ! IZLO - tower lower point index - ! - ! NOTE: there is a slight bug with this formulation. The sum(NGe) should be - ! exactly 1.0, but it is not. The boundaries match the expected values - ! well and give continuous transitions to the other regions, so it is - ! suspected that the ground point coefficient is incorrect. Since the - ! ground point coefficient is multiplied by zero, it doesn't affect - ! the results so I won't spend more time trying to figure it out (ADP). - Z2 = 2.0_ReKi * Position(3)/p%GridBase - 1.0_ReKi - YtZg = 2.0_ReKi * (p%FFYHWid/(p%FFYHWid + (p%GridBase-Position(3)))) - 1.0_ReKi - YtZgG= 2.0_ReKi * (Position(3))/(p%FFYHWid+Position(2)+Position(3)) - 1.0_ReKi - NGe=0.0_ReKi - NGe(1) = ( 1.0_ReKi + Z2)* ( 1.0_ReKi + Y )*( 1.0_ReKi - T )*2.0_ReKi ! bottom of grid average (top right point, hi half) - NGe(2) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! corner of grid (top right point, lo half) - NGe(3) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! Below grid edge with tower effect (bottom right point, hi half) - NGe(4) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! Below grid edge with tower effect (bottom right point, lo half) - NGe(6) = ( 1.0_ReKi + Z2)* ( 1.0_ReKi + Y )*( 1.0_ReKi + T )*2.0_ReKi - NGe(7) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - Y )*( 1.0_ReKi + T ) - NGe(8) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) - NGe(9) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) - if (abs(Position(2)) > 2*p%FFYHWid) then - NGe(5) = ( 1.0_ReKi - Z2)* ( 1.0_ReKi - T )*4.0_ReKi ! ground (bottom left point) - NGe(10) = ( 1.0_ReKi - Z2)* ( 1.0_ReKi + T )*4.0_ReKi - else - ! NOTE: This coefficient is probably incorrect, but gets multiplied by zero so I'm not fixing it. - NGe(5) = ( 1.0_ReKi - Z2)*( 1.0_ReKi-YtZgG)*( 1.0_ReKi + Y )* ( 1.0_ReKi - T ) ! ground (bottom left point) - NGe(10) = ( 1.0_ReKi - Z2)*( 1.0_ReKi-YtZgG)*( 1.0_ReKi + Y )* ( 1.0_ReKi + T ) - endif - NGe = NGe /16.0_ReKi ! normalize - do IDIM=1,p%NFFComp - uGe(1) = p%FFAvgData( 1, IDIM, ITLO ) ! bottom of grid average - uGe(2) = p%FFData( 1, IYLO, IDIM, ITLO ) ! Corner of grid - uGe(3) = p%FFTower( IDIM, IZHI, ITLO ) ! tower line high (bottom point, hi half) - uGe(4) = p%FFTower( IDIM, IZLO, ITLO ) ! Tower line lo (bottom point, lo half) - uGe(5) = 0.0_ReKi ! ground (bottom left point) - uGe(6) = p%FFAvgData( 1, IDIM, ITHI ) - uGe(7) = p%FFData( 1, IYLO, IDIM, ITHI ) - uGe(8) = p%FFTower( IDIM, IZHI, ITHI ) - uGe(9) = p%FFTower( IDIM, IZLO, ITHI ) - uGe(10) = 0.0_ReKi - FFWind_Interp(IDIM) = SUM ( NGe * uGe ) - enddo - endif - else - if (p%NTGrids < 1) then - ! Get standard interpolation weightings - call GetInterpWeights3D(); - - ! Below grid with no tower points defined - do IDIM=1,p%NFFComp ! all the components - u(1) = p%FFData( 1, IYLO, IDIM, ITLO ) - u(2) = p%FFData( 1, IYHI, IDIM, ITLO ) - u(3) = 0.0_ReKi ! ground - u(4) = 0.0_ReKi ! ground - u(5) = p%FFData( 1, IYLO, IDIM, ITHI ) - u(6) = p%FFData( 1, IYHI, IDIM, ITHI ) - u(7) = 0.0_ReKi ! ground - u(8) = 0.0_ReKi ! ground - FFWind_Interp(IDIM) = SUM ( N * u ) - enddo - else ! Tower grid - ! YtZg - distance from grid bottom to tower along a right angled corner - ! line from grid bottom through point to tower. Used to change - ! weighting between grid and tower influece (kind of approximates - ! a spherical weighting, but without considering more points along - ! grid bottom or tower). - ! Z2 - scaled distance between bottom edge of grid and ground (in z) - ! Y - scaled distance between IYLO-IYHI along bottom of grid - ! Z - scaled distance between IZLO-IZHI olong tower line - ! IYHI - grid high y point index - ! IYLO - grid low y point index - ! IZHI - tower upper point index - ! IZLO - tower lower point index - Z2 = 2.0_ReKi * Position(3)/p%GridBase - 1.0_ReKi - YtZg = 2.0_ReKi * (abs(Position(2))/(abs(Position(2)) + (p%GridBase-Position(3)))) - 1.0_ReKi ! on Tower ==-1, on grid bottom == 1 - NGe=0.0_ReKi - NGe(1) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! grid bottom low (top right point, lo half) - NGe(2) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi + Y )*( 1.0_ReKi - T ) ! grid bottom hi (top right point, hi half) - NGe(3) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi + Z )* ( 1.0_ReKi - T )*2.0_ReKi ! tower line high (bottom right point, hi half) - NGe(4) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi - Z )* ( 1.0_ReKi - T )*2.0_ReKi ! Tower line lo (bottom right point, lo half) - NGe(5) = ( 1.0_ReKi - Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - T )*2.0_ReKi ! ground (bottom left point) - NGe(6) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi - Y )*( 1.0_ReKi + T ) - NGe(7) = ( 1.0_ReKi + Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi + Y )*( 1.0_ReKi + T ) - NGe(8) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi + Z )* ( 1.0_ReKi + T )*2.0_ReKi - NGe(9) = ( 1.0_ReKi-YtZg)*( 1.0_ReKi - Z )* ( 1.0_ReKi + T )*2.0_ReKi - NGe(10) = ( 1.0_ReKi - Z2)*( 1.0_ReKi+YtZg)* ( 1.0_ReKi + T )*2.0_ReKi - NGe = NGe / 16.0_ReKi ! normalize - do IDIM=1,p%NFFComp - uGe(1) = p%FFData( 1, IYLO, IDIM, ITLO ) ! grid bottom low (top point, lo half) - uGe(2) = p%FFData( 1, IYHI, IDIM, ITLO ) ! grid bottom hi (top point, hi half) - uGe(3) = p%FFTower( IDIM, IZHI, ITLO ) ! tower line high (bottom point, hi half) - uGe(4) = p%FFTower( IDIM, IZLO, ITLO ) ! Tower line lo (bottom point, lo half) - uGe(5) = 0.0_ReKi ! ground (bottom left point) - uGe(6) = p%FFData( 1, IYLO, IDIM, ITHI ) - uGe(7) = p%FFData( 1, IYHI, IDIM, ITHI ) - uGe(8) = p%FFTower( IDIM, IZHI, ITHI ) - uGe(9) = p%FFTower( IDIM, IZLO, ITHI ) - uGe(10) = 0.0_ReKi - FFWind_Interp(IDIM) = SUM ( NGe * uGe ) - enddo - endif - endif - ELSEIF (p%InterpTower) THEN - - !----------------------------------------------------- - ! Interpolate on the bottom of the grid to the ground - ! ground points set to zero - call GetInterpWeights3D(); - - DO IDIM=1,p%NFFComp ! all the components - u(1) = p%FFData( IZHI, IYLO, IDIM, ITLO ) - u(2) = p%FFData( IZHI, IYHI, IDIM, ITLO ) - u(3) = 0.0_ReKi ! ground - u(4) = 0.0_ReKi ! ground - u(5) = p%FFData( IZHI, IYLO, IDIM, ITHI ) - u(6) = p%FFData( IZHI, IYHI, IDIM, ITHI ) - u(7) = 0.0_ReKi ! ground - u(8) = 0.0_ReKi ! ground - FFWind_Interp(IDIM) = SUM ( N * u ) - END DO !IDIM - ELSE - !----------------------------------------------------- - ! Interpolate on the tower array (no y bounds) - call GetInterpWeightsPlane(); - - DO IDIM=1,p%NFFComp ! all the components - ! Interpolate between the two times using an area interpolation. - - IF (IZHI > p%NTGrids) THEN - v(1) = 0.0_ReKi ! on the ground - v(2) = 0.0_ReKi ! on the ground - ELSE - v(1) = p%FFTower( IDIM, IZHI, ITLO ) - v(2) = p%FFTower( IDIM, IZHI, ITHI ) - END IF - - v(3) = p%FFTower( IDIM, IZLO, ITLO ) - v(4) = p%FFTower( IDIM, IZLO, ITHI ) - - FFWind_Interp(IDIM) = SUM ( M * v ) - END DO !IDIM - END IF ! Interpolate below the grid - ENDIF ! AboveGridBottom - - RETURN - -CONTAINS - - !------------------------------------------------------------------------------------------------- - !> Find the bounding time slices. - !! Perform the time shift. At time=0, a point half the grid width downstream (p%FFYHWid) will index into the zero time slice. - !! If we did not do this, any point downstream of the tower at the beginning of the run would index outside of the array. - !! This all assumes the grid width is at least as large as the rotor. If it isn't, then the interpolation will not work. - SUBROUTINE GetTBounds() - - TimeShifted = TIME + ( p%InitXPosition - Position(1) )*p%InvMFFWS ! in distance, X: InputInfo%Position(1) - p%InitXPosition - TIME*p%MeanFFWS - - IF ( p%Periodic ) THEN ! translate TimeShifted to ( 0 <= TimeShifted < p%TotalTime ) - - TimeShifted = MODULO( TimeShifted, p%TotalTime ) - ! If TimeShifted is a very small negative number, modulo returns the incorrect value due to internal rounding errors. - IF (TimeShifted == p%TotalTime) TimeShifted = 0.0_ReKi - - TGRID = TimeShifted*p%FFRate - ITLO = INT( TGRID ) ! convert REAL to INTEGER (add 1 later because our grids start at 1, not 0) - T = 2.0_ReKi * ( TGRID - REAL(ITLO, ReKi) ) - 1.0_ReKi ! a value between -1 and 1 that indicates a relative position between ITLO and ITHI - - ITLO = ITLO + 1 - IF ( ITLO == p%NFFSteps ) THEN - ITHI = 1 - ELSE - IF (ITLO > p%NFFSteps) ITLO = 1 - ITHI = ITLO + 1 - ENDIF - - ELSE - - TGRID = TimeShifted*p%FFRate - ITLO = INT( TGRID ) ! convert REAL to INTEGER (add 1 later because our grids start at 1, not 0) - T = 2.0_ReKi * ( TGRID - REAL(ITLO, ReKi) ) - 1.0_ReKi ! a value between -1 and 1 that indicates a relative position between ITLO and ITHI - - ITLO = ITLO + 1 ! add one since our grids start at 1, not 0 - ITHI = ITLO + 1 - - IF ( ITLO >= p%NFFSteps .OR. ITLO < 1 ) THEN - IF ( ITLO == p%NFFSteps ) THEN - ITHI = ITLO - IF ( T <= TOL ) THEN ! we're on the last point - T = -1.0_ReKi - ELSE ! We'll extrapolate one dt past the last value in the file - ITLO = ITHI - 1 - ENDIF - ELSE - ErrMsg = ' Error: FF wind array was exhausted at '//TRIM( Num2LStr( REAL( TIME, ReKi ) ) )// & - ' seconds (trying to access data at '//TRIM( Num2LStr( REAL( TimeShifted, ReKi ) ) )//' seconds).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ENDIF - - ENDIF - END SUBROUTINE GetTBounds - - !------------------------------------------------------------------------------------------------- - !> Find the bounding rows for the Z position. [The lower-left corner is (1,1) when looking upwind.] - SUBROUTINE GetZBounds() - - ZGRID = ( Position(3) - p%GridBase )*p%InvFFZD - - IF (ZGRID > -1*TOL) THEN - AboveGridBottom = .TRUE. - - ! Index for start and end slices - IZLO = FLOOR( ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - IZHI = IZLO + 1 - - ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. - ! Subtract 1_IntKi from Z since the indices are starting at 1, not 0 - Z = 2.0_ReKi * (ZGRID - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi - - IF ( IZLO < 1 ) THEN - IF ( IZLO == 0 .AND. Z >= 1.0-TOL/p%InvFFZD ) THEN ! Just below bottom edge, but within tolerance - Z = -1.0_ReKi - IZLO = 1 - ELSEIF ( GridExceedAllow ) THEN - ! calculate new Z between top of grid and half zgrid height above top of grid (range of -1 to 1) - Z = 2.0_ReKi * ( Position(3)/p%GridBase ) - 1.0_ReKi - Z = max(Z,-1.0_ReKi) ! enforce ground boundary - IZLO = 0 ! ground - IZHI = 1 ! Bottom of grid - AboveGridBottom = .FALSE. ! this is below the grid bottom - GridExtrap = .true. - ELSE - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& - TRIM(Num2LStr(Position(3)))//' m is below the grid).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ELSEIF ( IZLO >= p%NZGrids ) THEN - IF ( IZLO == p%NZGrids .AND. Z <= TOL ) THEN - Z = -1.0_ReKi - IZHI = IZLO ! We're right on the last point, which is still okay - ELSEIF ( GridExceedAllow ) THEN - ! calculate new Z between top of grid and half zgrid height above top of grid (range of -1 to 1) - Z = 2.0_ReKi * ( Position(3) - (p%GridBase + 2*p%FFZHWid) ) / p%FFZHWid - 1.0_ReKi - Z = min(Z,1.0_ReKi) ! plateau value at grid width above top of grid - IZLO = p%NZGrids ! Top of grid - IZHI = p%NZGrids ! Top of grid - GridExceedZmax = .true. - GridExtrap = .true. - ELSE - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction (Z='//& - TRIM(Num2LStr(Position(3)))//' m is above the grid).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ENDIF - - ELSE - AboveGridBottom = .FALSE. ! this is below the grid bottom - if ( GridExceedAllow ) then - GridExceedZmin = .true. - GridExtrap = .true. - endif - IF (p%InterpTower) then - ! get Z between ground and bottom of grid - ZGRID = Position(3)/p%GridBase - Z = 2.0_ReKi * ZGRID - 1.0_ReKi - IZHI = 1 - IZLO = 0 - - IF ( ZGRID < 0.0_ReKi ) THEN - ! note: this is already considered at the start of the routine - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & - '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the ground).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ELSE - IF ( p%NTGrids < 1) THEN - IF ( .not. GridExceedAllow ) THEN - ErrMsg = ' FF wind array boundaries violated. Grid too small in Z direction '// & - '(height (Z='//TRIM(Num2LStr(Position(3)))//' m) is below the grid and no tower points are defined).' - ErrStat = ErrID_Fatal - RETURN - ENDIF - ELSE - IZLO = INT( -1.0*ZGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - - IF ( IZLO >= p%NTGrids ) THEN !our dz is the difference between the bottom tower point and the ground - IZLO = p%NTGrids - ! Check that this isn't zero. Value between -1 and 1 corresponding to the relative position. - Z = 1.0_ReKi - 2.0_ReKi * (Position(3) / (p%GridBase - REAL(IZLO - 1_IntKi, ReKi)/p%InvFFZD)) - ELSE - ! Set Z as a value between -1 and 1 for the relative location between IZLO and IZHI. Used in the interpolation. - Z = 2.0_ReKi * (ABS(ZGRID) - REAL(IZLO - 1_IntKi, ReKi)) - 1.0_ReKi - ENDIF - IZHI = IZLO + 1 - ENDIF ! Tower grid - ENDIF ! Interp tower - END IF ! AboveGridBottom - END SUBROUTINE GetZBounds - - !------------------------------------------------------------------------------------------------- - !> Find the bounding columns for the Y position. [The lower-left corner is (1,1) when looking upwind.] - SUBROUTINE GetYBounds() - - YGRID = ( Position(2) + p%FFYHWid )*p%InvFFYD ! really, it's (Position(2) - -1.0*p%FFYHWid) - - IYLO = FLOOR( YGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - IYHI = IYLO + 1 - - ! Set Y as a value between -1 and 1 for the relative location between IYLO and IYHI. Used in the interpolation. - ! Subtract 1_IntKi from IYLO since grids start at index 1, not 0 - Y = 2.0_ReKi * (YGRID - REAL(IYLO - 1_IntKi, ReKi)) - 1.0_ReKi - - IF ( IYLO >= p%NYGrids .OR. IYLO < 1 ) THEN - IF ( IYLO == 0 .AND. Y >= 1.0-TOL ) THEN - Y = -1.0_ReKi - IYLO = 1 - ELSE IF ( IYLO == p%NYGrids .AND. Y <= TOL ) THEN - Y = -1.0_ReKi - IYHI = IYLO ! We're right on the last point, which is still okay - ELSE - ErrMsg = ' FF wind array boundaries violated: Grid too small in Y direction. Y='// & - TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*p%FFYHWid))// & - ', '//TRIM(Num2LStr(p%FFYHWid))//']' - ErrStat = ErrID_Fatal ! we don't return anything - RETURN - ENDIF - ENDIF - END SUBROUTINE GetYBounds - - !------------------------------------------------------------------------------------------------- - !> Find the bounding columns for the Y position. [The lower-left corner is (1,1) when looking upwind.] - !! The logic is slightly different when grid exceedence is allowed. - SUBROUTINE GetYBoundsGridExceed() - YGRID = ( Position(2) + p%FFYHWid )*p%InvFFYD ! really, it's (Position(2) - -1.0*p%FFYHWid) - IYLO = FLOOR( YGRID ) + 1 ! convert REAL to INTEGER, then add one since our grids start at 1, not 0 - IYHI = IYLO + 1 - - ! Set Y as a value between -1 and 1 for the relative location between IYLO and IYHI. Used in the interpolation. - ! Subtract 1_IntKi from IYLO since grids start at index 1, not 0 - Y = 2.0_ReKi * (YGRID - REAL(IYLO - 1_IntKi, ReKi)) - 1.0_ReKi - - ! Using the average across Y as the boundary beyond the grid at +/-2*YHWid - IF ( IYLO <= 0 ) THEN ! Beyond lo side - ! calculate new Y between half ygrid width beyond edge (2*FFYHWid) and the - ! low side of the grid, then scale to -1 to 1 - Y = 2.0_ReKi * ( Position(2) + 2*p%FFYHWid ) / p%FFYHWid - 1.0_ReKi - Y = max(y,-1.0_ReKi) ! plateau value at grid width lo side of grid - IYLO = 1 ! Lo side of grid - IYHI = 1 ! Lo side of grid - Y = -Y ! Flip sign so -1 will be grid edge at all times - GridExceedY = .true. - GridExtrap = .true. - ELSEIF ( IYHI > p%NYGrids ) THEN ! Beyond hi side - Y = 2.0_ReKi * ( Position(2) - p%FFYHWid) / p%FFYHWid - 1.0_ReKi - IYLO = p%NYGrids ! Hi side of grid - IYHI = p%NYGrids ! Hi side of grid - Y = min(Y,1.0_ReKi) ! plateau value at grid width beyond edge - GridExceedY = .true. - GridExtrap = .true. - ENDIF - END SUBROUTINE GetYBoundsGridExceed - - !------------------------------------------------------------------------------------------------- - !> Get normalization values for 3d-linear interpolation on the grid - SUBROUTINE GetInterpWeights3D() - N(1) = ( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! top left - N(2) = ( 1.0_ReKi + Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) ! top right - N(3) = ( 1.0_ReKi - Z )*( 1.0_ReKi + Y )*( 1.0_ReKi - T ) ! bottom right - N(4) = ( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi - T ) ! bottom left - N(5) = ( 1.0_ReKi + Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) - N(6) = ( 1.0_ReKi + Z )*( 1.0_ReKi + Y )*( 1.0_ReKi + T ) - N(7) = ( 1.0_ReKi - Z )*( 1.0_ReKi + Y )*( 1.0_ReKi + T ) - N(8) = ( 1.0_ReKi - Z )*( 1.0_ReKi - Y )*( 1.0_ReKi + T ) - N = N / REAL( SIZE(N), ReKi ) ! normalize - END SUBROUTINE GetInterpWeights3D - - !------------------------------------------------------------------------------------------------- - !> Get normalization values for 3d-linear interpolation on the grid - SUBROUTINE GetInterpWeightsPlane() - M(1) = ( 1.0_ReKi + Z )*( 1.0_ReKi - T ) - M(2) = ( 1.0_ReKi + Z )*( 1.0_ReKi + T ) - M(3) = ( 1.0_ReKi - Z )*( 1.0_ReKi - T ) - M(4) = ( 1.0_ReKi - Z )*( 1.0_ReKi + T ) - M = M / REAL( SIZE(M), ReKi ) ! normalize - END SUBROUTINE GetInterpWeightsPlane -END FUNCTION FFWind_Interp - -!==================================================================================================== -!> This routine is used read scale the full-field turbulence data stored in HAWC format. -SUBROUTINE ScaleTurbulence(InitInp, FFData, ScaleFactors, ErrStat, ErrMsg) - - ! Passed Variables - TYPE(IfW_FFWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization input data passed to the module - REAL(SiKi), INTENT(INOUT) :: FFData(:,:,:,:) !< full-field wind inflow data - REAL(ReKi), INTENT( OUT) :: ScaleFactors(3) !< scaling factors that were used - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - - ! Local Variables: - ! note that the variables used to compute statistics use double precision: - REAL(DbKi) :: v(3) ! instanteanous wind speed at target position - REAL(DbKi) :: vMean(3) ! average wind speeds over time at target position - REAL(DbKi) :: vSum(3) ! sum over time of wind speeds at target position - REAL(DbKi) :: vSum2(3) ! sum of wind speeds squared - REAL(ReKi) :: ActualSigma(3) ! computed standard deviation - - INTEGER :: ic ! Loop counter for wind component - INTEGER :: ix ! Loop counter for x or t - INTEGER :: iy ! Loop counter for y - INTEGER :: iz ! Loop counter for z - - INTEGER :: nc ! number of FF wind components - INTEGER :: nx ! size of x (or t) dimension of turbulence box - INTEGER :: ny ! size of y dimension of turbulence box - INTEGER :: nz ! size of z dimension of turbulence box - - CHARACTER(*), PARAMETER :: RoutineName = 'ScaleTurbulence' - - - - ErrStat = ErrID_None - ErrMsg = "" - - nz = size(FFData,1) - ny = size(FFData,2) - nc = size(FFData,3) - nx = size(FFData,4) - - if ( InitInp%ScaleMethod == ScaleMethod_None ) then - - ! don't scale FFWind: - ScaleFactors = 1.0_ReKi - - else ! ScaleMethod_Direct or ScaleMethod_StdDev - - !.............................. - ! determine the scaling factors: - !.............................. - - if ( InitInp%ScaleMethod == ScaleMethod_Direct ) then - ! Use the scaling factors specified in the input file: - ScaleFactors = InitInp%sf - - else !if ( InitInp%ScaleMethod == ScaleMethod_StdDev ) then - ! compute the scale factor to get requested sigma: - - ! find the center point of the grid (if we don't have an odd number of grid points, we'll pick the point closest to the center) - iz = (nz + 1) / 2 ! integer division - iy = (ny + 1) / 2 ! integer division - - ! compute the actual sigma at the point specified by (iy,iz). (This sigma should be close to 1.) - v = 0.0_ReKi - vSum = 0.0_ReKi - vSum2 = 0.0_ReKi - DO ix=1,nx - v(1:nc) = FFData(iz,iy,:,ix) - - vSum = vSum + v - vSum2 = vSum2 + v**2 - ENDDO ! IX - - vMean = vSum/nx - ActualSigma = SQRT( ABS( (vSum2/nx) - vMean**2 ) ) - - ! check that the ActualSigma isn't 0 - !InitOut%sf = InitInp%SigmaF / ActualSigma ! factor = Target / actual - do ic=1,nc - if ( EqualRealNos( ActualSigma(ic), 0.0_ReKi ) ) then - ScaleFactors(ic) = 0.0_ReKi - if ( .not. EqualRealNos( InitInp%SigmaF(ic), 0.0_ReKi ) ) then - call SetErrStat( ErrID_Fatal,"Computed standard deviation is zero; cannot scale to achieve target non-zero standard deviation.", ErrStat, ErrMsg, RoutineName ) - end if - else - ScaleFactors(ic) = InitInp%SigmaF(ic) / ActualSigma(ic) - end if - end do - - end if - - !.............................. - ! scale the data using our scaling factors: - !.............................. - - do ix=1,nx - do ic = 1,nc - FFData( :, :, ic, ix ) = ScaleFactors(ic) * FFData( :, :, ic, ix ) - end do !IC - end do - - end if - -END SUBROUTINE ScaleTurbulence -!==================================================================================================== -!> This routine is used to add a mean wind profile to the HAWC format turbulence data. -SUBROUTINE AddMeanVelocity(InitInp, GridBase, dz, dy, FFData) - - ! Passed Variables - TYPE(IfW_FFWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization input data passed to the module - REAL(ReKi), INTENT(IN ) :: GridBase !< height of the lowest point on the grid - REAL(ReKi), INTENT(IN ) :: dz !< distance between two zertically consectutive grid points - REAL(ReKi), INTENT(IN ) :: dy !< distance between two horizontal consectutive grid points - REAL(SiKi), INTENT(INOUT) :: FFData(:,:,:,:) !< FF wind-inflow data - - ! Local Variables: - REAL(ReKi) :: Z ! height - REAL(ReKi) :: Y ! distance from centre in horizontal direction - REAL(ReKi) :: U ! mean wind speed - INTEGER(IntKi) :: iz ! loop counter - INTEGER(IntKi) :: iy ! loop counter - INTEGER(IntKi) :: nz ! number of points in the z direction - INTEGER(IntKi) :: ny ! number of points in the z direction - INTEGER(IntKi) :: centre_y ! index of centre in y direction - - - nz = size(FFData,1) - - DO iz = 1,nz - - Z = GridBase + ( iz - 1 )*dz - if (Z <= 0.0_ReKi) cycle - - SELECT CASE ( InitInp%WindProfileType ) - - CASE ( WindProfileType_PL ) - - U = InitInp%URef*( Z / InitInp%RefHt )**InitInp%PLExp ! [IEC 61400-1 6.3.1.2 (10)] - - CASE ( WindProfileType_Log ) - - IF ( .not. EqualRealNos( InitInp%RefHt, InitInp%Z0 ) .and. Z > 0.0_ReKi ) THEN - U = InitInp%URef*( LOG( Z / InitInp%Z0 ) )/( LOG( InitInp%RefHt / InitInp%Z0 ) ) - ELSE - U = 0.0_ReKi - ENDIF - - CASE ( WindProfileType_Constant ) - - U = InitInp%URef - - CASE DEFAULT - - U = 0.0_ReKi - - END SELECT - - IF (InitInp%VLinShr .NE. 0.0_ReKi) THEN ! Add vertical linear shear, if has - U = U + InitInp%URef * InitInp%VLinShr * (Z - InitInp%RefHt) / InitInp%RefLength - ENDIF - - FFData( iz, :, 1, : ) = FFData( iz, :, 1, : ) + U - - END DO ! iz - - IF (InitInp%HLinShr .NE. 0.0_ReKi) THEN ! Add horizontal linear shear, if has - ny = size(FFData,2) - ! find the center point of the grid (if we don't have an odd number of grid points, we'll pick the point closest to the center) - centre_y = (ny + 1) / 2 ! integer division - DO iy = 1,ny - - Y = (iy - centre_y) * dy - - U = InitInp%URef * InitInp%HLinShr * Y / InitInp%RefLength - - FFData( :, iy, 1, : ) = FFData( :, iy, 1, : ) + U - - END DO ! iy - ENDIF ! IF InitInp%HLinShr - - -END SUBROUTINE AddMeanVelocity -!==================================================================================================== -FUNCTION CalculateMeanVelocity(p,z,y) RESULT(u) - - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - REAL(ReKi) , INTENT(IN ) :: Z ! height - REAL(ReKi) , INTENT(IN ) :: y ! lateral location - REAL(ReKi) :: u ! mean wind speed at position (y,z) - - SELECT CASE ( p%WindProfileType ) - - CASE ( WindProfileType_PL ) - - U = p%MeanFFWS*( Z / p%RefHt )**p%PLExp ! [IEC 61400-1 6.3.1.2 (10)] - - CASE ( WindProfileType_Log ) - - IF ( .not. EqualRealNos( p%RefHt, p%Z0 ) .and. Z > 0.0_ReKi ) THEN - U = p%MeanFFWS*( LOG( Z / p%Z0 ) )/( LOG( p%RefHt / p%Z0 ) ) - ELSE - U = 0.0_ReKi - ENDIF - - CASE ( WindProfileType_Constant ) - - U = p%MeanFFWS - - CASE DEFAULT - - U = 0.0_ReKi - - END SELECT - - - IF (p%VLinShr .NE. 0.0_ReKi) THEN ! Add vertical linear shear, if has - U = U + p%MeanFFWS * p%VLinShr * (Z - p%RefHt) / p%RefLength - ENDIF - - - IF (p%HLinShr .NE. 0.0_ReKi) THEN ! Add horizontal linear shear, if has - U = U + p%MeanFFWS * p%HLinShr * y / p%RefLength - ENDIF - -END FUNCTION CalculateMeanVelocity -!==================================================================================================== -!> This routine is used to add a subtract the mean wind speed from turbulence data (so that the added mean can be added later). -!! Note that this does NOT scale using the length of the wind simulation, so there may be differences with the HAWC implementation. -SUBROUTINE SubtractMeanVelocity(FFData) - - ! Passed Variables - REAL(SiKi), INTENT(INOUT) :: FFData(:,:,:,:) !< FF wind-inflow data - - ! Local Variables: - REAL(ReKi) :: MeanVal ! computed mean wind speed - INTEGER(IntKi) :: ic ! loop counter - INTEGER(IntKi) :: iy ! loop counter - INTEGER(IntKi) :: iz ! loop counter - INTEGER(IntKi) :: nt ! number of points in the x (time) direction - - - nt = size(FFData,4) - - DO ic = 1,1 !size(FFData,3) - DO iy = 1,size(FFData,2) - DO iz = 1,size(FFData,1) - meanVal = sum(FFData(iz,iy,ic,:)) / nt - - FFData( iz,iy,ic,: ) = FFData( iz,iy,ic,: ) - meanVal - END DO ! iz - END DO ! iy - END DO ! ic - - -END SUBROUTINE SubtractMeanVelocity -!==================================================================================================== -!> This routine is used to make sure the initInp data is valid. -SUBROUTINE FFWind_ValidateInput(InitInp, nffc, ErrStat, ErrMsg) - - ! Passed Variables - TYPE(IfW_FFWind_InitInputType), INTENT(IN ) :: InitInp !< Initialization input data passed to the module - INTEGER(IntKi), INTENT(IN ) :: nffc !< number of full-field wind components (normally 3) - - ! Error Handling - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< determines if an error has been encountered - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Message about errors - character(*), parameter :: RoutineName = 'FFWind_ValidateInput' - - integer(intki) :: ic ! loop counter - - ErrStat = ErrID_None - ErrMsg = "" - - IF ( InitInp%RefHt < 0.0_ReKi .or. EqualRealNos( InitInp%RefHt, 0.0_ReKi ) ) call SetErrStat( ErrID_Fatal, 'The grid reference height must be larger than 0.', ErrStat, ErrMsg, RoutineName ) - - if ( InitInp%ScaleMethod == ScaleMethod_Direct) then - do ic=1,nffc - if ( InitInp%sf(ic) < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'Turbulence scaling factors must not be negative.', ErrStat, ErrMsg, RoutineName ) - end do - elseif ( InitInp%ScaleMethod == ScaleMethod_StdDev ) then - do ic=1,nffc - if ( InitInp%sigmaf(ic) < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'Turbulence standard deviations must not be negative.', ErrStat, ErrMsg, RoutineName ) - end do -#ifdef UNUSED_INPUTFILE_LINES - if ( InitInp%TStart < 0.0_ReKi ) CALL SetErrStat( ErrID_Fatal, 'TStart for turbulence standard deviation calculations must not be negative.', ErrStat, ErrMsg, RoutineName ) - if ( InitInp%TEnd <= InitInp%TStart ) CALL SetErrStat( ErrID_Fatal, 'TEnd for turbulence standard deviation calculations must be after TStart.', ErrStat, ErrMsg, RoutineName ) -#endif - elseif ( InitInp%ScaleMethod /= ScaleMethod_None ) then - CALL SetErrStat( ErrID_Fatal, 'Turbulence scaling method must be 0 (none), 1 (direct scaling factors), or 2 (target standard deviation).', ErrStat, ErrMsg, RoutineName ) - end if - - - if (InitInp%WindProfileType == WindProfileType_Log) then - if ( InitInp%z0 < 0.0_ReKi .or. EqualRealNos( InitInp%z0, 0.0_ReKi ) ) & - call SetErrStat( ErrID_Fatal, 'The surface roughness length, Z0, must be greater than zero', ErrStat, ErrMsg, RoutineName ) - elseif ( InitInp%WindProfileType < WindProfileType_Constant .or. InitInp%WindProfileType > WindProfileType_PL) then - call SetErrStat( ErrID_Fatal, 'The WindProfile type must be 0 (constant), 1 (logarithmic) or 2 (power law).', ErrStat, ErrMsg, RoutineName ) - end if - - IF ( InitInp%URef < 0.0_ReKi ) call SetErrStat( ErrID_Fatal, 'The reference wind speed must not be negative.', ErrStat, ErrMsg, RoutineName ) - - IF ( EqualRealNos(InitInp%RefLength, 0.0_ReKi) .or. InitInp%RefLength < 0.0_ReKi ) THEN - IF (InitInp%VLinShr /= 0.0_ReKi .OR. InitInp%HLinShr /= 0.0_ReKi) THEN - call SetErrStat( ErrID_Fatal, 'The reference length must be a positive number when vertical or horizontal linear shear is used.', ErrStat, ErrMsg, RoutineName ) - END IF - END IF - -END SUBROUTINE FFWind_ValidateInput -!==================================================================================================== -SUBROUTINE ConvertFFWind_to_HAWC2(FileRootName, p, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - REAL(SiKi) :: delta(3) - - delta(1) = p%MeanFFWS * p%FFDTime - delta(2) = 1.0_SiKi / p%InvFFYD - delta(3) = 1.0_SiKi / p%InvFFZD - - CALL WrBinHAWC(FileRootName, p%FFData(:,:,:,1:p%NFFSteps), delta, ErrStat, ErrMsg) - - IF (.NOT. p%Periodic) THEN - call SetErrStat( ErrID_Severe, 'File converted to HAWC format is not periodic. Jumps may occur in resulting simulation.', & - ErrStat, ErrMsg, 'ConvertFFWind_to_HAWC2') - END IF - -END SUBROUTINE ConvertFFWind_to_HAWC2 -!==================================================================================================== -SUBROUTINE ConvertFFWind_to_Bladed(FileRootName, p, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - REAL(SiKi) :: delta(3) - - delta(1) = p%MeanFFWS * p%FFDTime - delta(2) = 1.0_SiKi / p%InvFFYD - delta(3) = 1.0_SiKi / p%InvFFZD - - CALL WrBinBladed(FileRootName, p%FFData(:,:,:,1:p%NFFSteps), delta, p%MeanFFWS, p%RefHt, p%GridBase, p%Periodic, p%AddMeanAfterInterp, ErrStat, ErrMsg) - -END SUBROUTINE ConvertFFWind_to_Bladed -!================================================================================================================================== -SUBROUTINE WrBinHAWC(FileRootName, FFWind, delta, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN) :: FileRootName !< Name of the file to write the output in - REAL(SiKi), INTENT(IN) :: FFWind(:,:,:,:) !< 4D wind speeds: index 1=z (height), 2=y (lateral), 3=dimension(u,v,w), 4=time or x - REAL(SiKi), INTENT(IN) :: delta(3) !< array containing dx, dy, dz in meters - INTEGER(IntKi), INTENT(OUT):: ErrStat !< Indicates whether an error occurred (see NWTC_Library) - CHARACTER(*), INTENT(OUT):: ErrMsg !< Error message associated with the ErrStat - - ! local variables - CHARACTER(*), PARAMETER :: Comp(3) = (/'u','v','w'/) - INTEGER(IntKi), PARAMETER :: AryDim(3) = (/4, 2, 1/) ! x,y,z dimensions of FFWind array - INTEGER(IntKi) :: nc - INTEGER(IntKi) :: IC, IX, IY, IZ - INTEGER(IntKi) :: UnWind - !REAL(SiKi) :: MeanVal(size(FFWind,1),size(FFWind,2)) - REAL(SiKi) :: MeanVal(size(FFWind,1)) - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'WrBinHAWC' - CHARACTER(1024) :: RootWithoutPathName - - ErrStat = ErrID_None - ErrMsg = "" - - CALL GetNewUnit( UnWind, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - nc = size(FFWind,3) ! check that nc == 3 ???? - - ! need to remove time-average value from DIM=1 - MeanVal = 0.0_SiKi - DO IX = 1,size(FFWind,4) - MeanVal = MeanVal + FFWind(:,1,1,ix) - END DO - MeanVal = MeanVal / size(FFWind,4) - - - ! write the summary file - CALL OpenFOutFile ( UnWind, trim(FileRootName)//'-HAWC.sum', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - WRITE( UnWind, '(A)' ) '; Wind file converted to HAWC format on '//CurDate()//' at '//CurTime() - - WRITE( UnWind, '()' ) - DO IZ = size(FFWind,AryDim(3)),1,-1 - WRITE( UnWind, '(A,I3,A,F15.5)' ) '; mean removed at z(', iz, ') = ', MeanVal(iz) - END DO - - WRITE( UnWind, '(A)' ) 'turb_format 1 ;' -! WRITE( UnWind, '(A)' ) 'center_pos0 0.0 0.0 '//trim(num2lstr( ';' - - WRITE( UnWind, '()' ) - WRITE( UnWind, '(A)' ) 'begin mann;' - - ic = INDEX( FileRootName, '\', BACK=.TRUE. ) - ic = MAX( ic, INDEX( FileRootName, '/', BACK=.TRUE. ) ) - RootWithoutPathName = FileRootName((ic+1):) - - - DO IC = 1,nc - WRITE( UnWind, '(2x,A, T30, A, " ;")' ) 'filename_'//Comp(IC), trim(RootWithoutPathName)//'-HAWC-'//Comp(IC)//'.bin' - END DO - DO IC = 1,nc - WRITE( UnWind, '(2x,A, T30, I8, 1x, F15.5, " ;")' ) 'box_dim_'//Comp(IC), size( FFWind, AryDim(ic) ), delta(ic) - END DO - WRITE( UnWind, '(2x,A)' ) 'dont_scale 1; converter did not rescale turbulence to unit standard deviation' - WRITE( UnWind, '(A)' ) 'end mann;' - CLOSE ( UnWind ) - - - ! write the binary files for each component - - DO IC = 1,nc - - CALL OpenBOutFile ( UnWind, trim(FileRootName)//'-HAWC-'//Comp(ic)//'.bin', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - DO IX = 1,size(FFWind,AryDim(1)) - DO IY = size(FFWind,AryDim(2)),1,-1 - WRITE( UnWind, IOSTAT=ErrStat2 ) FFWind(:,iy,ic,ix) - MeanVal(:) ! note that FFWind is SiKi (4-byte reals, not default kinds) - END DO - END DO - - CLOSE ( UnWind ) - - MeanVal = 0.0_SiKi - - END DO - -END SUBROUTINE WrBinHAWC -!================================================================================================================================== -SUBROUTINE WrBinBladed(FileRootName, FFWind, delta, MeanFFWS, HubHt, GridBase, Periodic, AddMeanAfterInterp, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN) :: FileRootName !< Name of the file to write the output in - REAL(SiKi), INTENT(IN) :: FFWind(:,:,:,:) !< 4D wind speeds: index 1=z (height), 2=y (lateral), 3=dimension(u,v,w), 4=time or x - REAL(SiKi), INTENT(IN) :: delta(3) !< array containing dx, dy, dz in meters - REAL(ReKi), INTENT(IN) :: MeanFFWS !< advection speed (mean wind speed at hub) - REAL(ReKi), INTENT(IN) :: HubHt !< hub height - REAL(ReKi), INTENT(IN) :: GridBase !< height of lowest grid point - LOGICAL, INTENT(IN) :: Periodic !< whether this wind file is periodic - LOGICAL, INTENT(IN) :: AddMeanAfterInterp !< whether this wind file contains a mean longditudinal wind speed - INTEGER(IntKi), INTENT(OUT):: ErrStat !< Indicates whether an error occurred (see NWTC_Library) - CHARACTER(*), INTENT(OUT):: ErrMsg !< Error message associated with the ErrStat - - ! local variables - INTEGER(IntKi), PARAMETER :: AryDim(3) = (/4, 2, 1/) ! x,y,z dimensions of FFWind array - INTEGER(IntKi) :: ic, it, iy, iz - INTEGER(IntKi) :: UnWind - REAL(SiKi) :: MeanVal(size(FFWind,1),size(FFWind,2)) - REAL(SiKi) :: SigmaGrid( size(FFWind,1),size(FFWind,2)) - REAL(SiKi) :: TI(3) !< array containing turbulence intensity (for scaling factors) - REAL(SiKi) :: Sigma(3) !< array containing standard deviations (for scaling factors) - REAL(SiKi) :: Scl(3) !< array containing scaling factors - REAL(SiKi) :: Off(3) !< array containing offsets - REAL(SiKi) :: Tmp - REAL(ReKi) :: MeanFFWS_nonZero !< advection speed (mean wind speed at hub) - - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'WrBinBladed' - - REAL(SiKi), PARAMETER :: Tolerance = 0.0001 ! The largest difference between two numbers that are assumed to be equal - - - ErrStat = ErrID_None - ErrMsg = "" - - !----------------------------------------------------- - ! Calculate the stats - !----------------------------------------------------- - - do ic=3,1,-1 - - ! mean values: - MeanVal = 0.0_SiKi - DO it = 1,size(FFWind,AryDim(1)) - MeanVal = MeanVal + FFWind(:,:,ic,it) - END DO - MeanVal = MeanVal / real( size(FFWind,AryDim(1)), SiKi) - - ! standard deviations (with 1/N scaling factor): - SigmaGrid = 0.0_SiKi - DO it = 1,size(FFWind,4) - SigmaGrid = SigmaGrid + FFWind(:,:,ic,it)**2 - END DO - SigmaGrid = SigmaGrid / size(FFWind,AryDim(1)) - SigmaGrid = SQRT( MAX( SigmaGrid - MeanVal**2, 0.0_SiKi ) ) - - ! now get the average standard deviation for each component: - Sigma(ic) = sum(SigmaGrid)/size(SigmaGrid) ! get the average sigma over the grid - Sigma(ic) = MAX(100.0_SiKi*Tolerance, Sigma(ic)) ! make sure this scaling isn't too small - - end do - - ! We need to take into account the shear across the grid in the sigma calculations for scaling the data, - ! and ensure that 32.767*sigma_u >= |V-UHub| so that we don't get values out of the range of our scaling values - ! in this BLADED-style binary output. Tmp is |V-UHub| - Tmp = MAX( ABS(MAXVAL(FFWind(:,:,1,:))-MeanFFWS), ABS(MINVAL(FFWind(:,:,1,:))-MeanFFWS) ) !Get the range of wind speed values for scaling in BLADED-format .wnd files - Sigma(1) = MAX(Sigma(1),0.05_SiKi*Tmp) - do ic=2,3 - Sigma(ic) = MAX( Sigma(ic), 0.05_SiKi*ABS(MAXVAL(FFWind(:,:,ic,:))), 0.05_SiKi*ABS(MINVAL(FFWind(:,:,ic,:))) ) ! put the abs() after the maxval() and minval() to avoid stack-overflow issues with large wind files - end do - - ! Put normalizing factors into the summary file. The user can use them to - ! tell a simulation program how to rescale the data. - - if ( abs(MeanFFWS) < 0.1_ReKi ) then - MeanFFWS_nonZero = sign( 0.1, MeanFFWS ) - else - MeanFFWS_nonZero = MeanFFWS - end if - - TI = Sigma / MeanFFWS_nonZero - - !----------------------------------------------------- - ! The summary file - !----------------------------------------------------- - CALL GetNewUnit( UnWind, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - CALL OpenFOutFile ( UnWind, trim(FileRootName)//'-Bladed.sum', ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - !The string "TurbSim" needs to be in the 2nd line of the summary file if AeroDyn will read this. - WRITE( UnWind,"( / 'TurbSim - This summary file was generated by ', A, ' on ' , A , ' at ' , A , '.' / )") "NWTC_Library", CurDate(), CurTime() - WRITE( UnWind, '(/)' ) - WRITE( UnWind, '(/)' ) - WRITE( UnWind, '( L10, 2X, "Clockwise rotation when looking downwind?")' ) .FALSE. - WRITE( UnWind, '( F10.3, 2X, "Hub height [m]")' ) HubHt - WRITE( UnWind, '( F10.3, 2X, "Grid height [m]")' ) delta(3)*(size(FFWind,AryDim(3)) - 1) - WRITE( UnWind, '( F10.3, 2X, "Grid width [m]")' ) delta(2)*(size(FFWind,AryDim(2)) - 1) - WRITE( UnWind, '(/"BLADED-style binary scaling parameters:"/)' ) - WRITE( UnWind, '( 2X, "UBar = ", F9.4, " m/s")' ) MeanFFWS_nonZero - WRITE( UnWind, '( 2X, "TI(u) = ", F9.4, " %")' ) 100.0*TI(1) - WRITE( UnWind, '( 2X, "TI(v) = ", F9.4, " %")' ) 100.0*TI(2) - WRITE( UnWind, '( 2X, "TI(w) = ", F9.4, " %")' ) 100.0*TI(3) - WRITE( UnWind, '(/)' ) - WRITE( UnWind, '( 2X, "Height offset = ", F9.4, " m" )' ) HubHt - 0.5*delta(3)*(size(FFWind,AryDim(3)) - 1) - GridBase ! This will be zero for square grids - ! ZGOffset = ( HubHt - delta(3)*(size(FFWind,1) - 1) / 2.0 - Zbottom ) - WRITE( UnWind, '( 2X, "Grid Base = ", F9.4, " m" )' ) GridBase - if (Periodic) then - WRITE (UnWind,'()' ) - WRITE (UnWind,'( A)' ) 'Creating a PERIODIC output file.' - end if - WRITE (UnWind,'( A)' ) 'Creating a BLADED LEFT-HAND RULE output file.' - - - CLOSE (UnWind) - - !----------------------------------------------------- - ! The BINARY file - !----------------------------------------------------- - CALL OpenBOutFile ( UnWind, TRIM(FileRootName)//'-Bladed.wnd', ErrStat, ErrMsg ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - WRITE (UnWind) INT( -99 , B2Ki ) ! -99 = New Bladed format - WRITE (UnWind) INT( 4 , B2Ki ) ! 4 = improved von karman (not used, but needed for next 7 inputs) - WRITE (UnWind) INT( size(FFWind,3) , B4Ki ) ! size(FFWind,3) = 3 = number of wind components - WRITE (UnWind) REAL( 45.0_SiKi , SiKi ) ! Latitude (degrees) (informational, not used in FAST) - WRITE (UnWind) REAL( 0.03_SiKi , SiKi ) ! Roughness length (m) (informational, not used in FAST) - WRITE (UnWind) REAL( HubHt , SiKi ) ! Reference Height (m) (informational, not used in FAST) - WRITE (UnWind) REAL( 100.0*TI(1) , SiKi ) ! Longitudinal turbulence intensity (%) - WRITE (UnWind) REAL( 100.0*TI(2) , SiKi ) ! Lateral turbulence intensity (%) - WRITE (UnWind) REAL( 100.0*TI(3) , SiKi ) ! Vertical turbulence intensity (%) - - WRITE (UnWind) REAL( delta(3) , SiKi ) ! grid spacing in vertical direction, in m - WRITE (UnWind) REAL( delta(2) , SiKi ) ! grid spacing in lateral direction, in m - WRITE (UnWind) REAL( delta(1) , SiKi ) ! grid spacing in longitudinal direciton, in m - WRITE (UnWind) INT( size(FFWind,AryDim(1))/2 , B4Ki ) ! half the number of points in alongwind direction - WRITE (UnWind) REAL( MeanFFWS_nonZero , SiKi ) ! the mean wind speed in m/s - WRITE (UnWind) REAL( 0 , SiKi ) ! the vertical length scale of the longitudinal component in m - WRITE (UnWind) REAL( 0 , SiKi ) ! the lateral length scale of the longitudinal component in m - WRITE (UnWind) REAL( 0 , SiKi ) ! the longitudinal length scale of the longitudinal component in m - WRITE (UnWind) INT( 0 , B4Ki ) ! an unused integer - WRITE (UnWind) INT( 0 , B4Ki ) ! the random number seed - WRITE (UnWind) INT( size(FFWind,AryDim(3)) , B4Ki ) ! the number of grid points vertically - WRITE (UnWind) INT( size(FFWind,AryDim(2)) , B4Ki ) ! the number of grid points laterally - WRITE (UnWind) INT( 0 , B4Ki ) ! the vertical length scale of the lateral component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the lateral length scale of the lateral component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the longitudinal length scale of the lateral component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the vertical length scale of the vertical component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the lateral length scale of the vertical component, not used - WRITE (UnWind) INT( 0 , B4Ki ) ! the longitudinal length scale of the vertical component, not used - - ! Scaling value to convert wind speeds to 16-bit integers - do ic = 1,3 - if (.not. EqualRealNos( Sigma(ic), 0.0_SiKi ) ) then - Scl(ic) = 1000.0/( Sigma(ic) ) - else - Scl(ic) = 1.0_SiKi - end if - end do - Scl(2) = -Scl(2) ! Bladed convention is positive V is pointed along negative Y (IEC turbine coordinate) - - ! Offset value to convert wind speeds to 16-bit integers - IF (AddMeanAfterInterp) THEN ! Note that this will not take into account any shear!!! - Off(1) = 0.0 - ELSE - Off(1) = MeanFFWS * Scl(1) - END IF - Off(2) = 0.0 - Off(3) = 0.0 - - DO it=1,size(FFWind,AryDim(1)) - DO iz=1,size(FFWind,AryDim(3)) ! 1=bottom of grid - DO iy=1,size(FFWind,AryDim(2)) ! 1=left of grid, i.e. y(1) = -GridWidth/2 - - ! Scale velocity for 16-bit integers: - WRITE ( UnWind ) NINT( FFWind(iz,iy,:,it) * Scl - Off , B2Ki ) ! scale to int16 - - ENDDO !IY - ENDDO !IZ - ENDDO !IT - - CLOSE( UnWind ) - - -END SUBROUTINE WrBinBladed -!==================================================================================================== -SUBROUTINE ConvertFFWind_toVTK(FileRootName, p, ErrStat, ErrMsg) - CHARACTER(*), INTENT(IN ) :: FileRootName !< RootName for output files - TYPE(IfW_FFWind_ParameterType), INTENT(IN ) :: p !< Parameters - - INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation - CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - - ! Local variables - CHARACTER(1024) :: RootPathName - CHARACTER(1024) :: FileName - INTEGER :: UnWind - INTEGER :: i - INTEGER :: iy - INTEGER :: iz - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'ConvertFFWind_toVTK' - - - CALL GetPath ( FileRootName, RootPathName ) - CALL GetNewUnit( UnWind, ErrStat, ErrMsg ) - - do i = 1,p%NFFSteps - - ! Create the output vtk file with naming /vtk/DisYZ.t.vtk - - RootPathName = trim(RootPathName)//PathSep//"vtk" - call MkDir( trim(RootPathName) ) ! make this directory if it doesn't already exist - - !FileName = trim(RootPathName)//PathSep//"vtk"//PathSep//"DisYZ.t"//trim(num2lstr(i))//".vtp" - FileName = trim(RootPathName)//PathSep//"DisYZ.t"//trim(num2lstr(i))//".vtp" - - ! see WrVTK_SP_header - CALL OpenFOutFile ( UnWind, TRIM(FileName), ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - if (ErrStat >= AbortErrLev) return - - WRITE(UnWind,'(A)') '# vtk DataFile Version 3.0' - WRITE(UnWind,'(A)') "InflowWind YZ Slice at T= "//trim(num2lstr((i-1)*p%FFDTime))//" s" - WRITE(UnWind,'(A)') 'ASCII' - WRITE(UnWind,'(A)') 'DATASET STRUCTURED_POINTS' - - ! Note: gridVals must be stored such that the left-most dimension is X and the right-most dimension is Z - ! see WrVTK_SP_vectors3D() - WRITE(UnWind,'(A,3(i5,1X))') 'DIMENSIONS ', 1, p%NYGrids, p%NZGrids - WRITE(UnWind,'(A,3(f10.2,1X))') 'ORIGIN ' , p%InitXPosition, -p%FFYHWid, p%GridBase - WRITE(UnWind,'(A,3(f10.2,1X))') 'SPACING ' , 0.0_ReKi, 1.0_SiKi / p%InvFFYD, 1.0_SiKi / p%InvFFZD - WRITE(UnWind,'(A,i5)') 'POINT_DATA ', p%NYGrids*p%NZGrids - WRITE(UnWind,'(A)') 'VECTORS DisYZ float' - - DO iz=1,p%NZGrids - DO iy=1,p%NYGrids - WRITE(UnWind,'(3(f10.2,1X))') p%FFData(iz,iy,:,i) - END DO - END DO - - CLOSE(UnWind) - - end do - - -END SUBROUTINE ConvertFFWind_toVTK - - -!==================================================================================================== -!> This subroutine generates the mean wind vector timeseries for each height above the ground. This -!! is essentially compressing the Y dimension of the wind box leaving a Z-T plane of vectors. The -!! resulting dimensions will be (NZGrids, NYGrids, NFFComp, NFFSteps) -subroutine GenMeanGridProfileTimeSeries( p, ErrStat, ErrMsg ) - type(IfW_FFWind_ParameterType), intent(inout) :: p !< Parameters - integer(IntKi), intent( out) :: ErrStat !< Error status of the operation - character(*), intent( out) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - ! Local variables - integer :: i - integer :: iy - integer :: iz - integer :: it - - INTEGER(IntKi) :: ErrStat2 - CHARACTER(ErrMsgLen) :: ErrMsg2 - CHARACTER(*), PARAMETER :: RoutineName = 'GenMeanProfileTimeSeries' - - ErrStat = ErrID_None - ErrMsg = "" - - if ( .not. p%BoxExceedAllowF ) return - if ( p%BoxExceedAllowIdx <= 0_IntKi ) return ! Index too low, so skip - if ( .not. allocated( p%FFData ) ) then - ErrStat = ErrID_Fatal - ErrMSg = "Call before data has been read or allocated." - return - endif - - ! Allocate array - if ( .not. allocated( p%FFAvgData ) ) then - CALL AllocAry( p%FFAvgData, p%NZGrids, p%NFFComp, p%NFFSteps, & - 'Full-field average wind profile timeseries data array.', ErrStat2, ErrMsg2 ) - if (Failed()) return - p%FFAvgData = 0.0_SiKi - endif - - - ! Populate array based on FFData (we don't consider any tower info -- we can get that from the tower interp later) - ! NOTE: this looping structure may be a bit slow. We are averaging across an intermediate dimension - do it=1,p%NFFSteps - do i=1,p%NFFComp - do iz=1,p%NZGrids - do iy=1,p%NYGrids - p%FFAvgData(iz,i,it) = p%FFAvgData(iz,i,it) + p%FFData(iz,iy,i,it) - enddo - p%FFAvgData(iz,i,it) = p%FFAvgData(iz,i,it) / real(p%NYGrids, SiKi) - enddo - enddo - enddo - -contains - logical function Failed() - CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - Failed = ErrStat >= AbortErrLev - end function Failed - -end subroutine GenMeanGridProfileTimeSeries -!==================================================================================================== - -END MODULE IfW_FFWind_Base diff --git a/modules/inflowwind/src/IfW_FFWind_Base.txt b/modules/inflowwind/src/IfW_FFWind_Base.txt deleted file mode 100644 index aade2e109a..0000000000 --- a/modules/inflowwind/src/IfW_FFWind_Base.txt +++ /dev/null @@ -1,66 +0,0 @@ -################################################################################################################################### -# Registry for IfW_BladedFFWind, creates MODULE IfW_BladedFFWind_Types -# Module IfW_BladedFFWind_Types contains all of the user-defined types needed in IfW_BladedFFWind. It also contains copy, destroy, pack, and -# unpack routines associated with each defined data types. -################################################################################################################################### -# Entries are of the form -# keyword -################################################################################################################################### - - -typedef IfW_FFWind_Base/IfW_FFWind InitInputType IntKi ScaleMethod - 0 - "Turbulence scaling method [0=none, 1=direct scaling, 2= calculate scaling factor based on a desired standard deviation]" - -typedef ^ ^ ReKi SF 3 0 - "Turbulence scaling factor for each direction [ScaleMethod=1]" - -typedef ^ ^ ReKi SigmaF 3 0 - "Turbulence standard deviation to calculate scaling from in each direction [ScaleMethod=2]" - -#typedef ^ ^ ReKi TStart - 0 - "" - -#typedef ^ ^ ReKi TEnd - 0 - "" - -typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - -typedef ^ ^ ReKi RefHt - 0 - "Reference (hub) height of the grid" meters -typedef ^ ^ ReKi URef - 0 - "Mean u-component wind speed at the reference height" meters -typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - -typedef ^ ^ ReKi VLinShr - 0 - "Vertical linear wind shear coefficient (used for vertical linear wind profile type only)" - -typedef ^ ^ ReKi HLinShr - 0 - "Horizontal linear wind shear coefficient (used for horizontal wind profile type only)" - -typedef ^ ^ ReKi RefLength - 1.0_ReKi - "Reference (rotor) length of the grid (used for horizontal wind profile type only)" - -typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - -typedef ^ ^ ReKi XOffset - 0 - "distance offset for FF wind files" m -typedef ^ ^ IntKi BoxExceedAllowIdx - - - "Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim)" - -typedef ^ ^ LOGICAL BoxExceedAllowF - - - "Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim)" - - - -# ..... Parameters ................................................................................................................ -# Define parameters here: -# Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType Logical Periodic - .FALSE. - "Flag to indicate if the wind file is periodic" - -typedef ^ ParameterType Logical InterpTower - .FALSE. - "Flag to indicate if we should interpolate wind speeds below the tower" - -typedef ^ ^ SiKi FFData :::: - - "Array of FF data" - -typedef ^ ^ SiKi FFTower ::: - - "Array of data along tower, below FF array" - -typedef ^ ^ SiKi FFAvgData ::: - - "Average velocity profile by Z and time" - -typedef ^ ^ ReKi FFDTime - 0 - "Delta time" seconds -typedef ^ ^ ReKi FFRate - 0 - "Data rate (1/FFDTime)" Hertz -typedef ^ ^ ReKi FFYHWid - 0 - "Half the grid width" meters -typedef ^ ^ ReKi FFZHWid - 0 - "Half the grid height" meters -typedef ^ ^ ReKi RefHt - 0 - "Reference (hub) height of the grid" meters -typedef ^ ^ ReKi GridBase - 0 - "the height of the bottom of the grid" meters -typedef ^ ^ ReKi InitXPosition - 0 - "the initial x position of grid (distance in FF is offset)" meters -typedef ^ ^ ReKi InvFFYD - 0 - "reciprocal of delta y" 1/meters -typedef ^ ^ ReKi InvFFZD - 0 - "reciprocal of delta z" 1/meters -typedef ^ ^ ReKi InvMFFWS - 0 - "reciprocal of mean wind speed (MeanFFWS)" seconds/meter -typedef ^ ^ ReKi MeanFFWS - 0 - "Mean wind speed (as defined in FF file), not necessarily of the portion used" meters/second -typedef ^ ^ ReKi TotalTime - 0 - "The total time of the simulation" seconds -typedef ^ ^ IntKi NFFComp - 3 - "Number of wind components" - -typedef ^ ^ IntKi NFFSteps - 0 - "Number of time steps in the FF array" - -typedef ^ ^ IntKi NYGrids - 0 - "Number of points in the lateral (y) direction of the grids" - -typedef ^ ^ IntKi NZGrids - 0 - "Number of points in the vertical (z) direction of the grids" - -typedef ^ ^ IntKi NTGrids - 0 - "Number of points in the vertical (z) direction on the tower (below the grids)" - -typedef ^ ^ IntKi WindFileFormat - - - "Binary file format description number" - -typedef ^ ^ Logical AddMeanAfterInterp - .FALSE. - "Add the mean wind speed after interpolating at a given height?" - -typedef ^ ^ IntKi WindProfileType - -1 - "Wind profile type (0=constant;1=logarithmic;2=power law)" - -typedef ^ ^ ReKi PLExp - 0 - "Power law exponent (used for PL wind profile type only)" - -typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - -typedef ^ ^ ReKi VLinShr - 0 - "Vertical linear wind shear coefficient (used for vertical linear wind profile type only)" - -typedef ^ ^ ReKi HLinShr - 0 - "Horizontal linear wind shear coefficient (used for horizontal wind profile type only)" - -typedef ^ ^ ReKi RefLength - 1.0_ReKi - "Reference (rotor) length of the grid (used for horizontal wind profile type only)" - -typedef ^ ^ LOGICAL BoxExceedAllowF - .FALSE. - "Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim)" - -typedef ^ ^ IntKi BoxExceedAllowIdx - -1 - "Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim)" - - -# ..... MiscVar ................................................................................................................... -typedef ^ MiscVarType LOGICAL BoxExceedWarned - .FALSE. - "Has a warning been issued for points extrapolated beyond FFWind grid" - diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index 9980f82ab1..bef1ad04c3 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -58,12 +58,16 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A real(ReKi), allocatable :: Position(:, :) integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg + ! Uniform Field type(UniformField_Interp) :: UFopVel, UFopAcc + ! Grid3D Field real(ReKi) :: Xi(3) real(ReKi) :: VelCell(8, 3), AccCell(8, 3) logical :: Is3D + logical :: GridExceedAllow ! is this point allowed to exceed bounds of wind grid + logical :: GridExtrap ! did this point fall outside the wind box and get extrapolated? ErrStat = ErrID_None ErrMsg = "" @@ -178,9 +182,14 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A cycle end if - ! Calculate grid cells for interpolation - call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), .true., & - VelCell, AccCell, Xi, Is3D, TmpErrStat, TmpErrMsg) + ! Is this point allowed beyond the bounds of the wind box? + GridExceedAllow = FF%Grid3D%BoxExceedAllowF .and. (i >= FF%Grid3D%BoxExceedAllowIdx) + + ! Calculate grid cells for interpolation, returns velocity and acceleration + ! components at corners of grid cell containing time and position. Also + ! returns interpolation values Xi. + call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), .true., GridExceedAllow, & + VelCell, AccCell, Xi, Is3D, GridExtrap, TmpErrStat, TmpErrMsg) if (TmpErrStat >= AbortErrLev) then call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) return @@ -209,9 +218,12 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A cycle end if + ! is this point allowed beyond the bounds of the wind box? + GridExceedAllow = FF%Grid3D%BoxExceedAllowF .and. (i >= FF%Grid3D%BoxExceedAllowIdx) + ! Calculate grid cells for interpolation - call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), FF%VelInterpCubic, & - VelCell, AccCell, Xi, Is3D, TmpErrStat, TmpErrMsg) + call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), FF%VelInterpCubic, GridExceedAllow, & + VelCell, AccCell, Xi, Is3D, GridExtrap, TmpErrStat, TmpErrMsg) if (TmpErrStat >= AbortErrLev) then call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) return @@ -726,149 +738,382 @@ subroutine IfW_UniformWind_GetOP(UF, t, InterpCubic, OP_out) end subroutine -subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, VelCell, AccCell, Xi, Is3D, ErrStat, ErrMsg) - - type(Grid3DFieldType), intent(in) :: G3D !< 3D Grid-Field data - real(DbKi), intent(in) :: Time !< time (s) - real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value - logical, intent(in) :: CalcAccel !< flag to populat AccCell - real(ReKi), intent(out) :: VelCell(8, 3) !< - real(ReKi), intent(out) :: AccCell(8, 3) !< - real(ReKi), intent(out) :: Xi(3) !< isoparametric coord of position in cell (y,z,t) [-1, +1] - logical, intent(out) :: Is3D !< - integer(IntKi), intent(out) :: ErrStat !< error status - character(*), intent(out) :: ErrMsg !< error message - - character(*), parameter :: RoutineName = "Grid3DField_GetSmoothInterp" - integer(IntKi) :: IY_Lo, IY_Hi - integer(IntKi) :: IZ_Lo, IZ_Hi - integer(IntKi) :: IT_Lo, IT_Hi - logical :: OnGrid - real(ReKi) :: TimeShifted +subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & + VelCell, AccCell, Xi, Is3D, Extrapolated, ErrStat, ErrMsg) + + type(Grid3DFieldType), intent(in) :: G3D !< 3D Grid-Field data + real(DbKi), intent(in) :: Time !< time (s) + real(ReKi), intent(in) :: Position(3) !< position X,Y,Z to get value + logical, intent(in) :: CalcAccel !< flag to populat AccCell + logical, intent(in) :: AllowExtrap !< is this point allowed to exceed bounds of wind grid + real(ReKi), intent(out) :: VelCell(8, 3) !< Velocity components at corners of grid cell + real(ReKi), intent(out) :: AccCell(8, 3) !< Acceleration components at corners of grid cell + real(ReKi), intent(out) :: Xi(3) !< isoparametric coord of position in cell (y,z,t) [-1, +1] + logical, intent(out) :: Is3D !< flag indicating if interpolation is 3D or 2D + logical, intent(out) :: Extrapolated !< Extrapolation outside grid is allowed and point lies outside grid + integer(IntKi), intent(out) :: ErrStat !< error status + character(*), intent(out) :: ErrMsg !< error message + + character(*), parameter :: RoutineName = "Grid3DField_GetCell" + integer(IntKi), parameter :: ExtrapNone = 0 + integer(IntKi), parameter :: ExtrapYmin = 1 + integer(IntKi), parameter :: ExtrapYmax = 2 + integer(IntKi), parameter :: ExtrapZmin = 4 + integer(IntKi), parameter :: ExtrapZmax = 8 + integer(IntKi) :: AllExtrap + integer(IntKi) :: IY_Lo, IY_Hi + integer(IntKi) :: IZ_Lo, IZ_Hi + integer(IntKi) :: IT_Lo, IT_Hi + logical :: InGrid ErrStat = ErrID_None ErrMsg = "" + ! Initialize to no extrapolation (modified in bounds routines) + AllExtrap = ExtrapNone + !---------------------------------------------------------------------------- ! Find grid bounds in Time and Z !---------------------------------------------------------------------------- ! Get grid time bounds - call Grid3DField_GetBoundsT(Position(1), Xi(3)) + call GetBoundsT(Position(1), Xi(3)) if (ErrStat >= AbortErrLev) return ! Get grid Z bounds - call Grid3DField_GetBoundsZ(Position(3), Xi(2)) + call GetBoundsZ(Position(3), Xi(2)) + if (ErrStat >= AbortErrLev) return + + ! Get grid Y bounds + call GetBoundsY(Position(2), Xi(1)) if (ErrStat >= AbortErrLev) return + ! Set flag indicating if extrapolation occured + Extrapolated = AllExtrap /= ExtrapNone + !---------------------------------------------------------------------------- - ! Extract cells from grids + ! Extract interpolation cells from grids based on poisiont !---------------------------------------------------------------------------- - if (OnGrid) then - - ! Get grid Y bounds - call Grid3DField_GetBoundsY(Position(2), Xi(1)) - if (ErrStat >= AbortErrLev) return + ! If position is inside grid + if (InGrid) then + ! Set flag to use 3D interpolation Is3D = .true. - ! Get velocities from the grid - VelCell(1, :) = G3D%Vel(:, IY_Lo, IZ_Lo, IT_Lo) - VelCell(2, :) = G3D%Vel(:, IY_Hi, IZ_Lo, IT_Lo) - VelCell(3, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Lo) - VelCell(4, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Lo) - VelCell(5, :) = G3D%Vel(:, IY_Lo, IZ_Lo, IT_Hi) - VelCell(6, :) = G3D%Vel(:, IY_Hi, IZ_Lo, IT_Hi) - VelCell(7, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Hi) - VelCell(8, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Hi) - - ! Get accelerations from the grid - if (CalcAccel) then - AccCell(1, :) = G3D%Acc(:, IY_Lo, IZ_Lo, IT_Lo) - AccCell(2, :) = G3D%Acc(:, IY_Hi, IZ_Lo, IT_Lo) - AccCell(3, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Lo) - AccCell(4, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Lo) - AccCell(5, :) = G3D%Acc(:, IY_Lo, IZ_Lo, IT_Hi) - AccCell(6, :) = G3D%Acc(:, IY_Hi, IZ_Lo, IT_Hi) - AccCell(7, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Hi) - AccCell(8, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Hi) - end if - - else if (G3D%InterpTower) then - - ! Get grid Y bounds - call Grid3DField_GetBoundsY(Position(2), Xi(1)) - if (ErrStat >= AbortErrLev) return - - Is3D = .true. + ! Interpolate within grid (or top, left, right if extrapolation enabled) + call GetCellInGrid(VelCell, G3D%Vel, G3D%VelAvg) - ! Get velocities from the grid - VelCell(1, :) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Lo) - VelCell(2, :) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Lo) - VelCell(3, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Lo) - VelCell(4, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Lo) - VelCell(5, :) = 0.0_ReKi ! GF%Vel(:, IY_Lo, IZ_Lo, IT_Hi) - VelCell(6, :) = 0.0_ReKi ! GF%Vel(:, IY_Hi, IZ_Lo, IT_Hi) - VelCell(7, :) = G3D%Vel(:, IY_Lo, IZ_Hi, IT_Hi) - VelCell(8, :) = G3D%Vel(:, IY_Hi, IZ_Hi, IT_Hi) - - ! Get accelerations from the grid + ! If acceleration requested, get cell values if (CalcAccel) then - AccCell(1, :) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Lo) - AccCell(2, :) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Lo) - AccCell(3, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Lo) - AccCell(4, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Lo) - AccCell(5, :) = 0.0_ReKi ! GF%Acc(:, IY_Lo, IZ_Lo, IT_Hi) - AccCell(6, :) = 0.0_ReKi ! GF%Acc(:, IY_Hi, IZ_Lo, IT_Hi) - AccCell(7, :) = G3D%Acc(:, IY_Lo, IZ_Hi, IT_Hi) - AccCell(8, :) = G3D%Acc(:, IY_Hi, IZ_Hi, IT_Hi) + call GetCellInGrid(AccCell, G3D%Acc, G3D%AccAvg) end if - else + else if (G3D%NTGrids > 0) then + ! Interpolation is 2D Is3D = .false. - ! In tower grid - if (IZ_HI <= G3D%NTGrids) then - VelCell(1, :) = G3D%VelTower(:, IZ_LO, IT_LO) - VelCell(2, :) = G3D%VelTower(:, IZ_HI, IT_LO) - VelCell(3, :) = G3D%VelTower(:, IZ_LO, IT_HI) - VelCell(4, :) = G3D%VelTower(:, IZ_HI, IT_HI) + ! Tower grids present and position is below main grid + if (.not. AllowExtrap) then + + ! Get cell without extrapolation + call GetCellInTowerNoExtrap(VelCell, G3D%VelTower) + ! If acceleration requested, get cell values if (CalcAccel) then - AccCell(1, :) = G3D%AccTower(:, IZ_LO, IT_LO) - AccCell(2, :) = G3D%AccTower(:, IZ_HI, IT_LO) - AccCell(3, :) = G3D%AccTower(:, IZ_LO, IT_HI) - AccCell(4, :) = G3D%AccTower(:, IZ_HI, IT_HI) + call GetCellInTowerNoExtrap(AccCell, G3D%AccTower) end if - else ! Between tower grid and ground + else - VelCell(1, :) = G3D%VelTower(:, IZ_LO, IT_LO) - VelCell(2, :) = 0.0_ReKi - VelCell(3, :) = G3D%VelTower(:, IZ_LO, IT_HI) - VelCell(4, :) = 0.0_ReKi + ! Get cell with extrapolation + call GetCellInTower(VelCell, G3D%Vel, G3D%VelAvg, G3D%VelTower) + ! If acceleration requested, get cell values if (CalcAccel) then - AccCell(1, :) = G3D%AccTower(:, IZ_LO, IT_LO) - AccCell(2, :) = 0.0_ReKi - AccCell(3, :) = G3D%AccTower(:, IZ_LO, IT_HI) - AccCell(4, :) = 0.0_ReKi + call GetCellInTower(AccCell, G3D%Acc, G3D%AccAvg, G3D%AccTower) end if end if + else + + ! Set flag to use 3D interpolation + Is3D = .true. + + ! Tower interpolation without tower grids + call GetCellBelowGrid(VelCell, G3D%Vel, G3D%VelAvg) + + ! If acceleration requested, get cell values + if (CalcAccel) then + call GetCellBelowGrid(AccCell, G3D%Acc, G3D%AccAvg) + end if + end if contains - subroutine Grid3DField_GetBoundsY(PosY, DY) + subroutine GetCellInGrid(cell, grid, gridAvg) + + real(ReKi), intent(out) :: cell(8, 3) + real(SiKi), intent(in) :: grid(:, :, :, :) + real(SiKi), intent(in) :: gridAvg(:, :, :) + + ! Select based on extrapolation flags + select case (AllExtrap) + + case (ExtrapNone) ! No extrapolation + + cell(1, :) = grid(:, IY_Lo, IZ_Lo, IT_Lo) + cell(2, :) = grid(:, IY_Hi, IZ_Lo, IT_Lo) + cell(3, :) = grid(:, IY_Lo, IZ_Hi, IT_Lo) + cell(4, :) = grid(:, IY_Hi, IZ_Hi, IT_Lo) + cell(5, :) = grid(:, IY_Lo, IZ_Lo, IT_Hi) + cell(6, :) = grid(:, IY_Hi, IZ_Lo, IT_Hi) + cell(7, :) = grid(:, IY_Lo, IZ_Hi, IT_Hi) + cell(8, :) = grid(:, IY_Hi, IZ_Hi, IT_Hi) + + case (ior(ExtrapZmax, ExtrapYmax)) ! Extrapolate top right corner + + cell(1, :) = grid(:, IY_Lo, IZ_Lo, IT_Lo) + cell(2, :) = gridAvg(:, IZ_Lo, IT_Lo) + cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(5, :) = grid(:, IY_Lo, IZ_Lo, IT_Hi) + cell(6, :) = gridAvg(:, IZ_Lo, IT_Hi) + cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) + cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) + + case (ior(ExtrapZmax, ExtrapYmin))! Extrapolate top left corner + + cell(1, :) = gridAvg(:, IZ_Lo, IT_Lo) + cell(2, :) = grid(:, IY_Hi, IZ_Lo, IT_Lo) + cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(5, :) = gridAvg(:, IZ_Lo, IT_Hi) + cell(6, :) = grid(:, IY_Hi, IZ_Lo, IT_Hi) + cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) + cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) + + case (ExtrapZmax) ! Extrapolate above grid only + + cell(1, :) = grid(:, IY_Lo, IZ_Lo, IT_Lo) + cell(2, :) = grid(:, IY_Hi, IZ_Lo, IT_Lo) + cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(5, :) = grid(:, IY_Lo, IZ_Lo, IT_Hi) + cell(6, :) = grid(:, IY_Hi, IZ_Lo, IT_Hi) + cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) + cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) + + case (ExtrapYmax) ! Extrapolate to the right of grid only + + cell(1, :) = grid(:, IY_Lo, IZ_Lo, IT_Lo) + cell(2, :) = gridAvg(:, IZ_Lo, IT_Lo) + cell(3, :) = grid(:, IY_Lo, IZ_Hi, IT_Lo) + cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(5, :) = grid(:, IY_Lo, IZ_Lo, IT_Hi) + cell(6, :) = gridAvg(:, IZ_Lo, IT_Hi) + cell(7, :) = grid(:, IY_Lo, IZ_Hi, IT_Hi) + cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) + + case (ExtrapYmin) ! Extrapolate to the left of grid only + + cell(1, :) = gridAvg(:, IZ_Lo, IT_Lo) + cell(2, :) = grid(:, IY_Hi, IZ_Lo, IT_Lo) + cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(4, :) = grid(:, IY_Hi, IZ_Hi, IT_Lo) + cell(5, :) = gridAvg(:, IZ_Lo, IT_Hi) + cell(6, :) = grid(:, IY_Hi, IZ_Lo, IT_Hi) + cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) + cell(8, :) = grid(:, IY_Hi, IZ_Hi, IT_Hi) + + end select + + end subroutine + + subroutine GetCellBelowGrid(cell, grid, gridAvg) + + real(ReKi), intent(out) :: cell(8, 3) + real(SiKi), intent(in) :: grid(:, :, :, :) + real(SiKi), intent(in) :: gridAvg(:, :, :) + + ! Select based on extrapolation flags + select case (AllExtrap) + + case (ExtrapNone) + + cell(1, :) = 0.0_ReKi ! Ground + cell(2, :) = 0.0_ReKi ! Ground + cell(3, :) = grid(:, IY_Lo, IZ_Hi, IT_Lo) + cell(4, :) = grid(:, IY_Hi, IZ_Hi, IT_Lo) + cell(5, :) = 0.0_ReKi ! Ground + cell(6, :) = 0.0_ReKi ! Ground + cell(7, :) = grid(:, IY_Lo, IZ_Hi, IT_Hi) + cell(8, :) = grid(:, IY_Hi, IZ_Hi, IT_Hi) + + case (ExtrapYmin) ! Extrap to bottom left of grid + + cell(1, :) = 0.0_ReKi ! Ground + cell(2, :) = 0.0_ReKi ! Ground + cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(4, :) = grid(:, IY_Hi, IZ_Hi, IT_Lo) + cell(5, :) = 0.0_ReKi ! Ground + cell(6, :) = 0.0_ReKi ! Ground + cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) + cell(8, :) = grid(:, IY_Hi, IZ_Hi, IT_Hi) + + case (ExtrapYmax) ! Extrap to bottom right of grid + + cell(1, :) = 0.0_ReKi ! Ground + cell(2, :) = 0.0_ReKi ! Ground + cell(3, :) = grid(:, IY_Lo, IZ_Hi, IT_Lo) + cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) + cell(5, :) = 0.0_ReKi ! Ground + cell(6, :) = 0.0_ReKi ! Ground + cell(7, :) = grid(:, IY_Lo, IZ_Hi, IT_Hi) + cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) + + end select + + end subroutine + + subroutine GetCellInTowerNoExtrap(cell, tower) + + real(ReKi), intent(out) :: cell(8, 3) + real(SiKi), intent(in) :: tower(:, :, :) + + if (IZ_HI <= G3D%NTGrids) then ! In tower grid - real(ReKi), intent(in) :: PosY - real(ReKi), intent(out) :: DY + cell(1, :) = tower(:, IZ_LO, IT_LO) + cell(2, :) = tower(:, IZ_HI, IT_LO) + cell(3, :) = tower(:, IZ_LO, IT_HI) + cell(4, :) = tower(:, IZ_HI, IT_HI) - real(ReKi) :: Y_Grid + else ! Between tower grid and ground + + cell(1, :) = tower(:, IZ_LO, IT_LO) + cell(2, :) = 0.0_ReKi + cell(3, :) = tower(:, IZ_LO, IT_HI) + cell(4, :) = 0.0_ReKi + + end if + + end subroutine + + subroutine GetCellInTower(cell, grid, gridAvg, tower) + + real(ReKi), intent(out) :: cell(8, 3) + real(SiKi), intent(in) :: grid(:, :, :, :) + real(SiKi), intent(in) :: gridAvg(:, :, :) + real(SiKi), intent(in) :: tower(:, :, :) + + real(ReKi) :: GridVal(3, 2) + real(ReKi) :: TowerVal(3, 2) + real(ReKi) :: vc(2, 3, 2) + real(ReKi) :: N(2) + real(ReKi) :: Xv(3), Yv(3), Wv(3), Px, Py + real(ReKi) :: denom + integer(IntKi) :: ic, it + + if (abs(Position(2)) >= 2.0_ReKi*G3D%YHWid) then ! Extrapolation allowed and Y beyond interp + + ! Interp between ground and bottom of grid average + Xi(2) = 2.0_ReKi*Position(3)/G3D%GridBase - 1.0_ReKi + cell(1, :) = 0.0_ReKi + cell(2, :) = gridAvg(:, 1, IT_LO) + cell(3, :) = 0.0_ReKi + cell(4, :) = gridAvg(:, 1, IT_HI) + + else ! Extrapolation allowed and Y within interp range + + ! Distance from tower (Y) + Px = Position(2) + Xv(1) = 0.0_ReKi ! Tower + Xv(2) = Position(2) ! Grid bottom + Xv(3) = sign(2.0*G3D%YHWid, Position(2)) ! Ground + + ! Elevation from ground (Z) + Py = Position(3) + Yv(1) = Position(3) ! Tower + Yv(2) = G3D%GridBase ! Grid bottom + Yv(3) = 0.0_ReKi ! Ground + + ! Barycentric weights + denom = ((Yv(2) - Yv(3))*(Xv(1) - Xv(3)) + & + (Xv(3) - Xv(2))*(Yv(1) - Yv(3))) + Wv(1) = ((Yv(2) - Yv(3))*(Px - Xv(3)) + & + (Xv(3) - Xv(2))*(Py - Yv(3)))/denom + Wv(2) = ((Yv(3) - Yv(1))*(Px - Xv(3)) + & + (Xv(1) - Xv(3))*(Py - Yv(3)))/denom + + ! Interpolate grid + N(1) = (1.0_ReKi - Xi(1))/2.0_ReKi + N(2) = (1.0_ReKi + Xi(1))/2.0_ReKi + + select case (AllExtrap) + case (ExtrapNone) + vc(1, :, 1) = grid(:, IY_Lo, 1, IT_Lo) + vc(2, :, 1) = grid(:, IY_Hi, 1, IT_Lo) + vc(1, :, 2) = grid(:, IY_Lo, 1, IT_Hi) + vc(2, :, 2) = grid(:, IY_Hi, 1, IT_Hi) + case (ExtrapYmin) + vc(1, :, 1) = gridAvg(:, 1, IT_Lo) + vc(2, :, 1) = grid(:, IY_Lo, 1, IT_Lo) + vc(1, :, 2) = gridAvg(:, 1, IT_Hi) + vc(2, :, 2) = grid(:, IY_Lo, 1, IT_Hi) + case (ExtrapYmax) + vc(1, :, 1) = grid(:, IY_Hi, 1, IT_Lo) + vc(2, :, 1) = gridAvg(:, 1, IT_Lo) + vc(1, :, 2) = grid(:, IY_Hi, 1, IT_Hi) + vc(2, :, 2) = gridAvg(:, 1, IT_Hi) + end select + + do it = 1, 2 + do ic = 1, 3 + GridVal(ic, it) = dot_product(vc(:, ic, it), N) + end do + end do + + ! Interpolate tower + N(1) = (1.0_ReKi - Xi(2))/2.0_ReKi + N(2) = (1.0_ReKi + Xi(2))/2.0_ReKi + + if (IZ_HI <= G3D%NTGrids) then + vc(1, :, 1) = tower(:, IZ_Lo, IT_Lo) + vc(2, :, 1) = tower(:, IZ_Hi, IT_Lo) + vc(1, :, 2) = tower(:, IZ_Lo, IT_Hi) + vc(2, :, 2) = tower(:, IZ_Hi, IT_Hi) + else + vc(1, :, 1) = tower(:, IZ_Lo, IT_Lo) + vc(2, :, 1) = 0.0_ReKi + vc(1, :, 2) = tower(:, IZ_Lo, IT_Hi) + vc(2, :, 2) = 0.0_ReKi + end if + + do it = 1, 2 + do ic = 1, 3 + TowerVal(ic, it) = dot_product(vc(:, ic, it), N) + end do + end do + + ! Populate cell + cell(1, :) = Wv(1)*TowerVal(:, 1) + Wv(2)*GridVal(:, 1) + cell(2, :) = cell(1, :) + cell(3, :) = Wv(1)*TowerVal(:, 2) + Wv(2)*GridVal(:, 2) + cell(4, :) = cell(3, :) + + end if + + end subroutine + + subroutine GetBoundsY(PosY, DY) + + real(ReKi), intent(in) :: PosY + real(ReKi), intent(out) :: DY + + real(ReKi) :: Y_Grid ! Calculate position on Y grid Y_Grid = (PosY + G3D%YHWid)*G3D%InvDY + 1 @@ -890,22 +1135,36 @@ subroutine Grid3DField_GetBoundsY(PosY, DY) IY_LO = G3D%NYGrids - 1 IY_HI = G3D%NYGrids DY = 1.0_ReKi + else if (AllowExtrap) then + if (IY_LO <= 0) then + ! Clamp value at grid width below the low side of grid + DY = 2.0_ReKi*max(PosY/G3D%YHWid + 2.0_ReKi, 0.0_Reki) - 1.0_ReKi + IY_LO = 1 + IY_HI = 1 + AllExtrap = ior(AllExtrap, ExtrapYmin) + else if (IY_LO >= G3D%NYGrids) then + ! Clamp value at grid width above the high side of grid + DY = 2.0_ReKi*min(PosY/G3D%YHWid - 1.0_ReKi, 1.0_Reki) - 1.0_ReKi + IY_LO = G3D%NYGrids + IY_HI = G3D%NYGrids + AllExtrap = ior(AllExtrap, ExtrapYmax) + end if else ! Position outside call SetErrStat(ErrID_Fatal, ' GF wind array boundaries violated: Grid too small in Y direction. Y='// & - TRIM(Num2LStr(Position(2)))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*G3D%YHWid))// & + TRIM(Num2LStr(PosY))//'; Y boundaries = ['//TRIM(Num2LStr(-1.0*G3D%YHWid))// & ', '//TRIM(Num2LStr(G3D%YHWid))//']', & ErrStat, ErrMsg, RoutineName) end if end subroutine - subroutine Grid3DField_GetBoundsZ(PosZ, DZ) + subroutine GetBoundsZ(PosZ, DZ) - real(ReKi), intent(in) :: PosZ - real(ReKi), intent(out) :: DZ + real(ReKi), intent(in) :: PosZ + real(ReKi), intent(out) :: DZ - real(ReKi) :: Z_GRID + real(ReKi) :: Z_GRID ! Calculate position on Z grid Z_GRID = (PosZ - G3D%GridBase)*G3D%InvDZ + 1 @@ -917,25 +1176,29 @@ subroutine Grid3DField_GetBoundsZ(PosZ, DZ) ! Position location within interval [-1,1] DZ = Z_GRID - aint(Z_GRID) - ! If indices are within grid, set on grid to true + ! If indices are within grid, set in grid to true if (IZ_LO >= 1 .and. IZ_HI <= G3D%NZGrids) then - OnGrid = .true. + InGrid = .true. DZ = 2.0_ReKi*DZ - 1.0_ReKi - else if (IZ_LO < 1) then + return + end if + + ! If below grid + if (IZ_LO < 1) then if (IZ_LO == 0 .and. DZ >= 1.0_ReKi - GridTol) then - OnGrid = .true. + InGrid = .true. IZ_LO = 1 IZ_HI = 2 DZ = -1.0_ReKi else if (G3D%InterpTower) then ! Interp from bottom of grid to ground (zero velocity) - OnGrid = .false. + InGrid = .false. IZ_LO = 0 IZ_HI = 1 DZ = 2.0_ReKi*(PosZ/G3D%GridBase) - 1.0_ReKi else if (G3D%NTGrids > 0) then ! Interpolate with tower grid - OnGrid = .false. + InGrid = .false. ! Tower grid is reversed (lowest index is top of tower) IZ_LO = int(-(Z_GRID - 1)) + 1 if (IZ_LO >= G3D%NTGrids) then @@ -947,37 +1210,56 @@ subroutine Grid3DField_GetBoundsZ(PosZ, DZ) DZ = 2.0_ReKi*(real(2 - IZ_LO, ReKi) - Z_GRID) - 1.0_ReKi end if IZ_HI = IZ_LO + 1 + else if (AllowExtrap) then + InGrid = .true. + IZ_LO = 1 + IZ_HI = 1 + DZ = 2.0_ReKi*max(PosZ/G3D%GridBase, 0.0_Reki) - 1.0_ReKi + AllExtrap = ior(AllExtrap, ExtrapZmin) else ! Position below grid - call SetErrStat(ErrID_Fatal, ' GF wind array boundaries violated. '// & + call SetErrStat(ErrID_Fatal, ' G3D wind array boundaries violated. '// & 'Grid too small in Z direction '// & '(height (Z='//TRIM(Num2LStr(Position(3)))// & ' m) is below the grid and no tower points are defined).', & ErrStat, ErrMsg, RoutineName) end if - else if (IZ_HI > G3D%NZGrids) then ! Above Grid + return + end if + + ! If above grid + if (IZ_HI > G3D%NZGrids) then if (IZ_HI == G3D%NZGrids + 1 .and. DZ <= GridTol) then - OnGrid = .true. + InGrid = .true. IZ_LO = G3D%NZGrids - 1 IZ_HI = G3D%NZGrids DZ = 1.0_ReKi + else if (AllowExtrap) then + InGrid = .true. + IZ_LO = G3D%NZGrids + IZ_HI = G3D%NZGrids + ! Calculate interpolation, limit to value at grid width above top of grid + DZ = 2.0_ReKi*min((Position(3) - (G3D%GridBase + 2*G3D%ZHWid))/G3D%ZHWid, 1.0_ReKi) - 1.0_ReKi + AllExtrap = ior(AllExtrap, ExtrapZmax) else ! Position above grid - call SetErrStat(ErrID_Fatal, ' GF wind array boundaries violated. '// & + call SetErrStat(ErrID_Fatal, ' G3D wind array boundaries violated. '// & 'Grid too small in Z direction '// & '(Z='//TRIM(Num2LStr(Position(3)))//' m is above grid.)', & ErrStat, ErrMsg, RoutineName) end if + return end if end subroutine - subroutine Grid3DField_GetBoundsT(PosX, DT) + subroutine GetBoundsT(PosX, DT) - real(ReKi), intent(in) :: PosX - real(ReKi), intent(out) :: DT + real(ReKi), intent(in) :: PosX + real(ReKi), intent(out) :: DT - real(ReKi) :: T_GRID + real(ReKi) :: TimeShifted + real(ReKi) :: T_GRID ! Perform the time shift. At time=0, a point half the grid width downstream ! (p%YHWid) will index into the zero time slice. If we did not do this, @@ -985,13 +1267,13 @@ subroutine Grid3DField_GetBoundsT(PosX, DT) ! index outside of the array. This all assumes the grid width is at least as ! large as the rotor. If it isn't, then the interpolation will not work. - ! in distance, X: InputInfo%PosX - p%InitXPosition - TIME*p%MeanWS + ! In distance, X: InputInfo%PosX - p%InitXPosition - TIME*p%MeanWS TimeShifted = real(Time, ReKi) + (G3D%InitXPosition - PosX)*G3D%InvMWS ! If field is periodic if (G3D%Periodic) then TimeShifted = MODULO(TimeShifted, G3D%TotalTime) - ! If TimeShifted is a very small negative number, + ! If TimeShifted is a very small negative number, ! modulo returns the incorrect value due to internal rounding errors. ! See bug report #471 if (TimeShifted == G3D%TotalTime) TimeShifted = 0.0_ReKi @@ -1272,6 +1554,52 @@ subroutine CalcCubicSplineDeriv(n, h, y, dy) end subroutine +!> This subroutine generates the mean wind vector timeseries for each height above the ground. This +!! is essentially compressing the Y dimension of the wind box leaving a Z-T plane of vectors. The +!! resulting dimensions will be (NZGrids, NYGrids, NFFComp, NFFSteps) +subroutine IfW_Grid3DField_CalcVelAvgProfile(G3D, CalcAccel, ErrStat, ErrMsg) + + type(Grid3DFieldType), intent(inout) :: G3D !< Parameters + logical, intent(inout) :: CalcAccel !< Flag to calculate acceleration + integer(IntKi), intent(out) :: ErrStat !< Error status of the operation + character(*), intent(out) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + character(*), parameter :: RoutineName = 'IfW_Grid3DField_CalcVelAvgProfile' + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + + ErrStat = ErrID_None + ErrMsg = "" + + ! Allocate velocity array + if (.not. allocated(G3D%VelAvg)) then + call AllocAry(G3D%VelAvg, G3D%NComp, G3D%NZGrids, G3D%NSteps, & + 'Full-field average wind velocity timeseries data array.', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + G3D%VelAvg = 0.0_SiKi + end if + + ! Calculate average velocity for each component across grid (Y) + G3D%VelAvg = sum(G3D%Vel, dim=2)/G3D%NYGrids + + ! If acceleration calculation not requested, return + if (.not. CalcAccel) return + + ! Allocate acceleration array + if (.not. allocated(G3D%AccAvg)) then + call AllocAry(G3D%AccAvg, G3D%NComp, G3D%NZGrids, G3D%NSteps, & + 'Full-field average wind acceleration timeseries data array.', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + G3D%AccAvg = 0.0_SiKi + end if + + ! Calculate average acceleration for each component across grid (Y) + G3D%AccAvg = sum(G3D%Acc, dim=2)/G3D%NYGrids + +end subroutine + subroutine Grid4DField_GetVel(G4D, Time, Position, Velocity, ErrStat, ErrMsg) type(Grid4DFieldType), intent(in) :: G4D !< 4D grid-field data @@ -1610,7 +1938,6 @@ subroutine Grid3D_to_Uniform(G3D, UF, ErrStat, ErrMsg, SmoothingRadius) real(ReKi) :: meanVel(3) real(ReKi) :: meanWindDir real(ReKi) :: u_p1, z_p1 - real(ReKi) :: u_ref, z_ref real(ReKi), parameter :: HubPositionX = 0.0_ReKi real(ReKi) :: radius ! length of time to use for smoothing uniform wind data, seconds integer(IntKi) :: ErrStat2 @@ -1685,17 +2012,18 @@ subroutine Grid3D_to_Uniform(G3D, UF, ErrStat, ErrMsg, SmoothingRadius) transformMat(2, 3) = 0.0_R8Ki transformMat(3, 3) = cos(UF%AngleV(1)) - do i = 1, size(Vel, 4) + do ic = 1, size(Vel, 4) do iy = 1, size(Vel, 2) do iz = 1, size(Vel, 1) - Vel(iz, iy, :, i) = matmul(transformMat, G3D%Vel(:, iy, iz, i)) + Vel(iz, iy, :, ic) = real(matmul(transformMat, G3D%Vel(:, iy, iz, i)), SiKi) end do end do end do ! make sure we have the correct mean, or the direction will also be off here if (G3D%AddMeanAfterInterp) then - Vel(iz_ref, iy_ref, 1, :) = Vel(iz_ref, iy_ref, 1, :) + CalculateMeanVelocity(G3D, UF%RefHeight, 0.0_ReKi) + Vel(iz_ref, iy_ref, 1, :) = Vel(iz_ref, iy_ref, 1, :) + & + real(CalculateMeanVelocity(G3D, UF%RefHeight, 0.0_ReKi), SiKi) end if meanVel = 0.0_ReKi diff --git a/modules/inflowwind/src/IfW_FlowField.txt b/modules/inflowwind/src/IfW_FlowField.txt index b9b8fb5289..2641f2eb1a 100644 --- a/modules/inflowwind/src/IfW_FlowField.txt +++ b/modules/inflowwind/src/IfW_FlowField.txt @@ -66,6 +66,8 @@ typedef ^ ^ SiKi Vel typedef ^ ^ SiKi Acc :::: - - "Array of field accelerations" - typedef ^ ^ SiKi VelTower ::: - - "Array of tower velocities" - typedef ^ ^ SiKi AccTower ::: - - "Array of tower accelerations" - +typedef ^ ^ SiKi VelAvg ::: - - "Average velocity profile by Z and time" - +typedef ^ ^ SiKi AccAvg ::: - - "Average acceleration profile by Z and time" - typedef ^ ^ ReKi DTime - 0 - "Delta time" seconds typedef ^ ^ ReKi Rate - 0 - "Data rate (1/FFDTime)" Hertz typedef ^ ^ ReKi YHWid - 0 - "Half the grid width" meters @@ -86,7 +88,6 @@ typedef ^ ^ ReKi PLExp typedef ^ ^ ReKi Z0 - 0 - "Surface roughness length (used for LOG wind profile type only)" - typedef ^ ^ ReKi VLinShr - 0 - "Vertical linear wind shear coefficient (used for vertical linear wind profile type only)" - typedef ^ ^ ReKi HLinShr - 0 - "Horizontal linear wind shear coefficient (used for horizontal wind profile type only)" - -typedef ^ ^ SiKi VelAvg ::: - - "Average velocity profile by Z and time" - typedef ^ ^ LOGICAL BoxExceedAllowF - .FALSE. - "Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim)" - typedef ^ ^ IntKi BoxExceedAllowIdx - -1 - "Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim)" - diff --git a/modules/inflowwind/src/IfW_FlowField_Types.f90 b/modules/inflowwind/src/IfW_FlowField_Types.f90 index 2d19f7a842..6b17858306 100644 --- a/modules/inflowwind/src/IfW_FlowField_Types.f90 +++ b/modules/inflowwind/src/IfW_FlowField_Types.f90 @@ -100,6 +100,8 @@ MODULE IfW_FlowField_Types REAL(SiKi) , DIMENSION(:,:,:,:), ALLOCATABLE :: Acc !< Array of field accelerations [-] REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: VelTower !< Array of tower velocities [-] REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: AccTower !< Array of tower accelerations [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: VelAvg !< Average velocity profile by Z and time [-] + REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: AccAvg !< Average acceleration profile by Z and time [-] REAL(ReKi) :: DTime = 0 !< Delta time [seconds] REAL(ReKi) :: Rate = 0 !< Data rate (1/FFDTime) [Hertz] REAL(ReKi) :: YHWid = 0 !< Half the grid width [meters] @@ -120,6 +122,8 @@ MODULE IfW_FlowField_Types REAL(ReKi) :: Z0 = 0 !< Surface roughness length (used for LOG wind profile type only) [-] REAL(ReKi) :: VLinShr = 0 !< Vertical linear wind shear coefficient (used for vertical linear wind profile type only) [-] REAL(ReKi) :: HLinShr = 0 !< Horizontal linear wind shear coefficient (used for horizontal wind profile type only) [-] + LOGICAL :: BoxExceedAllowF = .FALSE. !< Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim) [-] + INTEGER(IntKi) :: BoxExceedAllowIdx = -1 !< Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim) [-] END TYPE Grid3DFieldType ! ======================= ! ========= Grid4DFieldType ======= @@ -1563,6 +1567,38 @@ SUBROUTINE IfW_FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DF END IF END IF DstGrid3DFieldTypeData%AccTower = SrcGrid3DFieldTypeData%AccTower +ENDIF +IF (ALLOCATED(SrcGrid3DFieldTypeData%VelAvg)) THEN + i1_l = LBOUND(SrcGrid3DFieldTypeData%VelAvg,1) + i1_u = UBOUND(SrcGrid3DFieldTypeData%VelAvg,1) + i2_l = LBOUND(SrcGrid3DFieldTypeData%VelAvg,2) + i2_u = UBOUND(SrcGrid3DFieldTypeData%VelAvg,2) + i3_l = LBOUND(SrcGrid3DFieldTypeData%VelAvg,3) + i3_u = UBOUND(SrcGrid3DFieldTypeData%VelAvg,3) + IF (.NOT. ALLOCATED(DstGrid3DFieldTypeData%VelAvg)) THEN + ALLOCATE(DstGrid3DFieldTypeData%VelAvg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGrid3DFieldTypeData%VelAvg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstGrid3DFieldTypeData%VelAvg = SrcGrid3DFieldTypeData%VelAvg +ENDIF +IF (ALLOCATED(SrcGrid3DFieldTypeData%AccAvg)) THEN + i1_l = LBOUND(SrcGrid3DFieldTypeData%AccAvg,1) + i1_u = UBOUND(SrcGrid3DFieldTypeData%AccAvg,1) + i2_l = LBOUND(SrcGrid3DFieldTypeData%AccAvg,2) + i2_u = UBOUND(SrcGrid3DFieldTypeData%AccAvg,2) + i3_l = LBOUND(SrcGrid3DFieldTypeData%AccAvg,3) + i3_u = UBOUND(SrcGrid3DFieldTypeData%AccAvg,3) + IF (.NOT. ALLOCATED(DstGrid3DFieldTypeData%AccAvg)) THEN + ALLOCATE(DstGrid3DFieldTypeData%AccAvg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstGrid3DFieldTypeData%AccAvg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstGrid3DFieldTypeData%AccAvg = SrcGrid3DFieldTypeData%AccAvg ENDIF DstGrid3DFieldTypeData%DTime = SrcGrid3DFieldTypeData%DTime DstGrid3DFieldTypeData%Rate = SrcGrid3DFieldTypeData%Rate @@ -1584,6 +1620,8 @@ SUBROUTINE IfW_FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DF DstGrid3DFieldTypeData%Z0 = SrcGrid3DFieldTypeData%Z0 DstGrid3DFieldTypeData%VLinShr = SrcGrid3DFieldTypeData%VLinShr DstGrid3DFieldTypeData%HLinShr = SrcGrid3DFieldTypeData%HLinShr + DstGrid3DFieldTypeData%BoxExceedAllowF = SrcGrid3DFieldTypeData%BoxExceedAllowF + DstGrid3DFieldTypeData%BoxExceedAllowIdx = SrcGrid3DFieldTypeData%BoxExceedAllowIdx END SUBROUTINE IfW_FlowField_CopyGrid3DFieldType SUBROUTINE IfW_FlowField_DestroyGrid3DFieldType( Grid3DFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -1618,6 +1656,12 @@ SUBROUTINE IfW_FlowField_DestroyGrid3DFieldType( Grid3DFieldTypeData, ErrStat, E ENDIF IF (ALLOCATED(Grid3DFieldTypeData%AccTower)) THEN DEALLOCATE(Grid3DFieldTypeData%AccTower) +ENDIF +IF (ALLOCATED(Grid3DFieldTypeData%VelAvg)) THEN + DEALLOCATE(Grid3DFieldTypeData%VelAvg) +ENDIF +IF (ALLOCATED(Grid3DFieldTypeData%AccAvg)) THEN + DEALLOCATE(Grid3DFieldTypeData%AccAvg) ENDIF END SUBROUTINE IfW_FlowField_DestroyGrid3DFieldType @@ -1682,6 +1726,16 @@ SUBROUTINE IfW_FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata IF ( ALLOCATED(InData%AccTower) ) THEN Int_BufSz = Int_BufSz + 2*3 ! AccTower upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%AccTower) ! AccTower + END IF + Int_BufSz = Int_BufSz + 1 ! VelAvg allocated yes/no + IF ( ALLOCATED(InData%VelAvg) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! VelAvg upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%VelAvg) ! VelAvg + END IF + Int_BufSz = Int_BufSz + 1 ! AccAvg allocated yes/no + IF ( ALLOCATED(InData%AccAvg) ) THEN + Int_BufSz = Int_BufSz + 2*3 ! AccAvg upper/lower bounds for each dimension + Re_BufSz = Re_BufSz + SIZE(InData%AccAvg) ! AccAvg END IF Re_BufSz = Re_BufSz + 1 ! DTime Re_BufSz = Re_BufSz + 1 ! Rate @@ -1703,6 +1757,8 @@ SUBROUTINE IfW_FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata Re_BufSz = Re_BufSz + 1 ! Z0 Re_BufSz = Re_BufSz + 1 ! VLinShr Re_BufSz = Re_BufSz + 1 ! HLinShr + Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowF + Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowIdx IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -1853,6 +1909,56 @@ SUBROUTINE IfW_FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata END DO END DO END DO + END IF + IF ( .NOT. ALLOCATED(InData%VelAvg) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelAvg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelAvg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelAvg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelAvg,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%VelAvg,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VelAvg,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%VelAvg,3), UBOUND(InData%VelAvg,3) + DO i2 = LBOUND(InData%VelAvg,2), UBOUND(InData%VelAvg,2) + DO i1 = LBOUND(InData%VelAvg,1), UBOUND(InData%VelAvg,1) + ReKiBuf(Re_Xferred) = InData%VelAvg(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( .NOT. ALLOCATED(InData%AccAvg) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AccAvg,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AccAvg,1) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AccAvg,2) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AccAvg,2) + Int_Xferred = Int_Xferred + 2 + IntKiBuf( Int_Xferred ) = LBOUND(InData%AccAvg,3) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%AccAvg,3) + Int_Xferred = Int_Xferred + 2 + + DO i3 = LBOUND(InData%AccAvg,3), UBOUND(InData%AccAvg,3) + DO i2 = LBOUND(InData%AccAvg,2), UBOUND(InData%AccAvg,2) + DO i1 = LBOUND(InData%AccAvg,1), UBOUND(InData%AccAvg,1) + ReKiBuf(Re_Xferred) = InData%AccAvg(i1,i2,i3) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO END IF ReKiBuf(Re_Xferred) = InData%DTime Re_Xferred = Re_Xferred + 1 @@ -1894,6 +2000,10 @@ SUBROUTINE IfW_FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%HLinShr Re_Xferred = Re_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedAllowF, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = InData%BoxExceedAllowIdx + Int_Xferred = Int_Xferred + 1 END SUBROUTINE IfW_FlowField_PackGrid3DFieldType SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -2061,6 +2171,62 @@ SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outd END DO END DO END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VelAvg not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%VelAvg)) DEALLOCATE(OutData%VelAvg) + ALLOCATE(OutData%VelAvg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VelAvg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%VelAvg,3), UBOUND(OutData%VelAvg,3) + DO i2 = LBOUND(OutData%VelAvg,2), UBOUND(OutData%VelAvg,2) + DO i1 = LBOUND(OutData%VelAvg,1), UBOUND(OutData%VelAvg,1) + OutData%VelAvg(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO + END IF + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AccAvg not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i2_l = IntKiBuf( Int_Xferred ) + i2_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + i3_l = IntKiBuf( Int_Xferred ) + i3_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%AccAvg)) DEALLOCATE(OutData%AccAvg) + ALLOCATE(OutData%AccAvg(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%AccAvg.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i3 = LBOUND(OutData%AccAvg,3), UBOUND(OutData%AccAvg,3) + DO i2 = LBOUND(OutData%AccAvg,2), UBOUND(OutData%AccAvg,2) + DO i1 = LBOUND(OutData%AccAvg,1), UBOUND(OutData%AccAvg,1) + OutData%AccAvg(i1,i2,i3) = REAL(ReKiBuf(Re_Xferred), SiKi) + Re_Xferred = Re_Xferred + 1 + END DO + END DO + END DO END IF OutData%DTime = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 @@ -2102,6 +2268,10 @@ SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outd Re_Xferred = Re_Xferred + 1 OutData%HLinShr = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 + OutData%BoxExceedAllowF = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedAllowF) + Int_Xferred = Int_Xferred + 1 + OutData%BoxExceedAllowIdx = IntKiBuf(Int_Xferred) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType SUBROUTINE IfW_FlowField_CopyGrid4DFieldType( SrcGrid4DFieldTypeData, DstGrid4DFieldTypeData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 34ddd32b2b..05a7b22adc 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -38,50 +38,57 @@ ! limitations under the License. ! !********************************************************************************************************************************** -module InflowWind +MODULE InflowWind -use NWTC_Library -use InflowWind_Types -use InflowWind_Subs -use InflowWind_IO_Types -use InflowWind_IO -use IfW_FlowField -use Lidar ! module for obtaining sensor data + USE NWTC_Library + USE InflowWind_Types + USE InflowWind_Subs + USE InflowWind_IO_Types + USE InflowWind_IO + USE IfW_FlowField -implicit none -private + USE Lidar ! module for obtaining sensor data + + IMPLICIT NONE + PRIVATE -type(ProgDesc), parameter :: IfW_Ver = ProgDesc('InflowWind', '', '') -integer, parameter :: NumExtendedInputs = 3 !: V, VShr, PropDir + TYPE(ProgDesc), PARAMETER :: IfW_Ver = ProgDesc( 'InflowWind', '', '' ) + integer, parameter :: NumExtendedInputs = 3 !: V, VShr, PropDir -! ..... Public Subroutines ................................................................................................... -public :: InflowWind_Init !< Initialization routine -public :: InflowWind_CalcOutput !< Calculate the wind velocities -public :: InflowWind_End !< Ending routine (includes clean up) -! These routines satisfy the framework, but do nothing at present. -public :: InflowWind_UpdateStates !< Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete states -public :: InflowWind_CalcConstrStateResidual !< Tight coupling routine for returning the constraint state residual -public :: InflowWind_CalcContStateDeriv !< Tight coupling routine for computing derivatives of continuous states -public :: InflowWind_UpdateDiscState !< Tight coupling routine for updating discrete states -! These routines compute Jacobians; only dYdu is defined. -public :: InflowWind_JacobianPInput !< Routine to compute the Jacobians of the output(Y), continuous - (X), discrete - + ! ..... Public Subroutines ................................................................................................... + + PUBLIC :: InflowWind_Init !< Initialization routine + PUBLIC :: InflowWind_CalcOutput !< Calculate the wind velocities + PUBLIC :: InflowWind_End !< Ending routine (includes clean up) + + ! These routines satisfy the framework, but do nothing at present. + PUBLIC :: InflowWind_UpdateStates !< Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete states + PUBLIC :: InflowWind_CalcConstrStateResidual !< Tight coupling routine for returning the constraint state residual + PUBLIC :: InflowWind_CalcContStateDeriv !< Tight coupling routine for computing derivatives of continuous states + PUBLIC :: InflowWind_UpdateDiscState !< Tight coupling routine for updating discrete states + + + ! These routines compute Jacobians; only dYdu is defined. + PUBLIC :: InflowWind_JacobianPInput !< Routine to compute the Jacobians of the output(Y), continuous - (X), discrete - !! (Xd), and constraint - state(Z) functions all with respect to the inputs(u) -public :: InflowWind_JacobianPContState !< Routine to compute the Jacobians of the output(Y), continuous - (X), discrete - + PUBLIC :: InflowWind_JacobianPContState !< Routine to compute the Jacobians of the output(Y), continuous - (X), discrete - !! (Xd), and constraint - state(Z) functions all with respect to the continuous !! states(x) -public :: InflowWind_JacobianPDiscState !< Routine to compute the Jacobians of the output(Y), continuous - (X), discrete - + PUBLIC :: InflowWind_JacobianPDiscState !< Routine to compute the Jacobians of the output(Y), continuous - (X), discrete - !! (Xd), and constraint - state(Z) functions all with respect to the discrete !! states(xd) -public :: InflowWind_JacobianPConstrState !< Routine to compute the Jacobians of the output(Y), continuous - (X), discrete - + PUBLIC :: InflowWind_JacobianPConstrState !< Routine to compute the Jacobians of the output(Y), continuous - (X), discrete - !! (Xd), and constraint - state(Z) functions all with respect to the constraint !! states(z) -public :: InflowWind_GetOP !< Routine to pack the operating point values (for linearization) into arrays + PUBLIC :: InflowWind_GetOP !< Routine to pack the operating point values (for linearization) into arrays + -contains + +CONTAINS !==================================================================================================== !> This routine is called at the start of the simulation to perform initialization steps. !! The parameters are set here and not changed during the simulation. @@ -89,80 +96,81 @@ module InflowWind !! Since this module acts as an interface to other modules, on some things are set before initiating !! calls to the lower modules. !---------------------------------------------------------------------------------------------------- -subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & - y, m, TimeInterval, InitOutData, ErrStat, ErrMsg) +SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & + y, m, TimeInterval, InitOutData, ErrStat, ErrMsg ) ! Initialization data and guesses - type(InflowWind_InitInputType), intent(IN) :: InitInp !< Input data for initialization - type(InflowWind_InputType), intent(OUT) :: InputGuess !< An initial guess for the input; the input mesh must be defined - type(InflowWind_ParameterType), intent(OUT) :: p !< Parameters - type(InflowWind_ContinuousStateType), intent(OUT) :: ContStates !< Initial continuous states - type(InflowWind_DiscreteStateType), intent(OUT) :: DiscStates !< Initial discrete states - type(InflowWind_ConstraintStateType), intent(OUT) :: ConstrStateGuess !< Initial guess of the constraint states - type(InflowWind_OtherStateType), intent(OUT) :: OtherStates !< Initial other/optimization states - type(InflowWind_OutputType), intent(OUT) :: y !< Initial output (outputs are not calculated; only the output mesh is initialized) - type(InflowWind_MiscVarType), intent(OUT) :: m !< Misc variables for optimization (not copied in glue code) - real(DbKi), intent(IN) :: TimeInterval !< Coupling time interval in seconds: InflowWind does not change this. - type(InflowWind_InitOutputType), intent(OUT) :: InitOutData !< Initial output data -- Names, units, and version info. - integer(IntKi), intent(OUT) :: ErrStat !< Error status of the operation - character(*), intent(OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + TYPE(InflowWind_InitInputType), INTENT(IN ) :: InitInp !< Input data for initialization + TYPE(InflowWind_InputType), INTENT( OUT) :: InputGuess !< An initial guess for the input; the input mesh must be defined + TYPE(InflowWind_ParameterType), INTENT( OUT) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT( OUT) :: ContStates !< Initial continuous states + TYPE(InflowWind_DiscreteStateType), INTENT( OUT) :: DiscStates !< Initial discrete states + TYPE(InflowWind_ConstraintStateType), INTENT( OUT) :: ConstrStateGuess !< Initial guess of the constraint states + TYPE(InflowWind_OtherStateType), INTENT( OUT) :: OtherStates !< Initial other/optimization states + TYPE(InflowWind_OutputType), INTENT( OUT) :: y !< Initial output (outputs are not calculated; only the output mesh is initialized) + TYPE(InflowWind_MiscVarType), INTENT( OUT) :: m !< Misc variables for optimization (not copied in glue code) + REAL(DbKi), INTENT(IN ) :: TimeInterval !< Coupling time interval in seconds: InflowWind does not change this. + TYPE(InflowWind_InitOutputType), INTENT( OUT) :: InitOutData !< Initial output data -- Names, units, and version info. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None ! Local variables - character(*), parameter :: RoutineName = "InflowWind_Init" + CHARACTER(*), PARAMETER :: RoutineName="InflowWind_Init" - type(InflowWind_InputFile) :: InputFileData !< Data from input file + TYPE(InflowWind_InputFile) :: InputFileData !< Data from input file - type(Steady_InitInputType) :: Steady_InitInput - type(Uniform_InitInputType) :: Uniform_InitInput - type(TurbSim_InitInputType) :: TurbSim_InitInput - type(Bladed_InitInputType) :: Bladed_InitInput - type(Bladed_InitOutputType) :: Bladed_InitOutput - type(HAWC_InitInputType) :: HAWC_InitInput - type(User_InitInputType) :: User_InitInput - type(Grid4D_InitInputType) :: Grid4D_InitInput - type(Points_InitInputType) :: Points_InitInput + Type(Steady_InitInputType) :: Steady_InitInput + Type(Uniform_InitInputType) :: Uniform_InitInput + Type(TurbSim_InitInputType) :: TurbSim_InitInput + Type(Bladed_InitInputType) :: Bladed_InitInput + Type(Bladed_InitOutputType) :: Bladed_InitOutput + Type(HAWC_InitInputType) :: HAWC_InitInput + Type(User_InitInputType) :: User_InitInput + Type(Grid4D_InitInputType) :: Grid4D_InitInput + Type(Points_InitInputType) :: Points_InitInput - type(WindFileDat) :: FileDat + Type(WindFileDat) :: FileDat + ! TYPE(InflowWind_IO_InitInputType) :: FlowField_InitData !< initialization info ! TYPE(InflowWind_IO_InitOutputType) :: FlowField_InitOutData !< initialization output info - type(FileInfoType) :: InFileInfo !< The derived type for holding the full input file for parsing -- we may pass this in the future - character(1024) :: PriPath + TYPE(FileInfoType) :: InFileInfo !< The derived type for holding the full input file for parsing -- we may pass this in the future + CHARACTER(1024) :: PriPath - integer(IntKi) :: I, j !< Generic counter - integer(IntKi) :: Lin_indx !< Generic counter - integer(IntKi) :: SumFileUnit !< Unit number for the summary file - character(256) :: SumFileName !< Name of the summary file - character(256) :: EchoFileName !< Name of the summary file - character(1), parameter :: UVW(3) = (/'U', 'V', 'W'/) - character(1), parameter :: XYZ(3) = (/'X', 'Y', 'Z'/) - integer(IntKi) :: TmpErrStat - character(ErrMsgLen) :: TmpErrMsg !< temporary error message + INTEGER(IntKi) :: I, j !< Generic counter + INTEGER(IntKi) :: Lin_indx !< Generic counter + INTEGER(IntKi) :: SumFileUnit !< Unit number for the summary file + CHARACTER(256) :: SumFileName !< Name of the summary file + CHARACTER(256) :: EchoFileName !< Name of the summary file + CHARACTER(1), PARAMETER :: UVW(3) = (/'U','V','W'/) + CHARACTER(1), PARAMETER :: XYZ(3) = (/'X','Y','Z'/) + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg !< temporary error message !---------------------------------------------------------------------------------------------- ! Initialize variables and check to see if this module has been initialized before. !---------------------------------------------------------------------------------------------- - ErrStat = ErrID_None - ErrMsg = "" - SumFileUnit = -1_IntKi ! set at beginning in case of error + ErrStat = ErrID_None + ErrMsg = "" + SumFileUnit = -1_IntKi ! set at beginning in case of error ! Set a few variables. - p%DT = TimeInterval ! InflowWind does not require a specific time interval, so this is never changed. - call NWTC_Init() - call DispNVD(IfW_Ver) + p%DT = TimeInterval ! InflowWind does not require a specific time interval, so this is never changed. + CALL NWTC_Init() + CALL DispNVD( IfW_Ver ) !---------------------------------------------------------------------------------------------- ! Read the input file !---------------------------------------------------------------------------------------------- ! Set the names of the files based on the inputfilename - p%RootFileName = InitInp%RootName - if (LEN_TRIM(p%RootFileName) == 0) call GetRoot(InitInp%InputFileName, p%RootFileName) - EchoFileName = TRIM(p%RootFileName)//".ech" - SumFileName = TRIM(p%RootFileName)//".sum" + p%RootFileName = InitInp%RootName + IF (LEN_TRIM(p%RootFileName) == 0) CALL GetRoot( InitInp%InputFileName, p%RootFileName ) + EchoFileName = TRIM(p%RootFileName)//".ech" + SumFileName = TRIM(p%RootFileName)//".sum" ! these values (and others hard-coded in lidar_init) should be set in the input file, too InputFileData%SensorType = InitInp%lidar%SensorType @@ -171,89 +179,89 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const InputFileData%LidRadialVel = InitInp%lidar%LidRadialVel ! Parse all the InflowWind related input files and populate the *_InitDataType derived types - call GetPath(InitInp%InputFileName, PriPath) - - if (InitInp%UseInputFile) then - call ProcessComFile(InitInp%InputFileName, InFileInfo, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - else - call NWTC_Library_CopyFileInfoType(InitInp%PassedFileData, InFileInfo, MESH_NEWCOPY, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - end if - - call InflowWind_ParseInputFileInfo(InputFileData, InFileInfo, PriPath, InitInp%InputFileName, EchoFileName, & - InitInp%FixedWindFileRootName, InitInp%TurbineID, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + CALL GetPath( InitInp%InputFileName, PriPath ) + + IF ( InitInp%UseInputFile ) THEN + CALL ProcessComFile( InitInp%InputFileName, InFileInfo, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + ELSE + CALL NWTC_Library_CopyFileInfoType( InitInp%PassedFileData, InFileInfo, MESH_NEWCOPY, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + ENDIF + + CALL InflowWind_ParseInputFileInfo( InputFileData, InFileInfo, PriPath, InitInp%InputFileName, EchoFileName, & + InitInp%FixedWindFileRootName, InitInp%TurbineID, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF ! If wind is Grid4D from FAST.Farm, set input file values - if (InitInp%Use4Dext) then - InputFileData%WindType = FDext_WindNumber + IF (InitInp%Use4Dext) then + InputFileData%WindType = FDext_WindNumber InputFileData%PropagationDir = 0.0_ReKi ! wind is in XYZ coordinates (already rotated if necessary), so don't rotate it again InputFileData%VFlowAngle = 0.0_ReKi InputFileData%VelInterpCubic = .false. - end if + END IF ! initialize sensor data - call Lidar_Init(InitInp, InputGuess, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & - y, m, TimeInterval, InitOutData, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - + CALL Lidar_Init( InitInp, InputGuess, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & + y, m, TimeInterval, InitOutData, TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + ! Validate the InflowWind input file information - call InflowWind_ValidateInput(InitInp, InputFileData, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - + CALL InflowWind_ValidateInput( InitInp, InputFileData, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + ! If a summary file was requested, open it and write preliminary data. - if (InputFileData%SumPrint) then - call InflowWind_OpenSumFile(SumFileUnit, SumFileName, IfW_Ver, InputFileData%WindType, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - end if + IF ( InputFileData%SumPrint ) THEN + CALL InflowWind_OpenSumFile( SumFileUnit, SumFileName, IfW_Ver, InputFileData%WindType, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF + ENDIF ! Allocate the array for passing points - call AllocAry(InputGuess%PositionXYZ, 3, InitInp%NumWindPoints, "Array of positions at which to find wind velocities", TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( InputGuess%PositionXYZ, 3, InitInp%NumWindPoints, "Array of positions at which to find wind velocities", TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) InputGuess%PositionXYZ = 0.0_ReKi InputGuess%HubPosition = 0.0_ReKi - call Eye(InputGuess%HubOrientation, TmpErrStat, TmpErrMsg) + CALL Eye(InputGuess%HubOrientation,TmpErrStat,TmpErrMsg) ! Allocate the array for passing velocities out - call AllocAry(y%VelocityUVW, 3, InitInp%NumWindPoints, "Array of wind velocities returned by InflowWind", TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + CALL AllocAry( y%VelocityUVW, 3, InitInp%NumWindPoints, "Array of wind velocities returned by InflowWind", TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF (ErrStat>= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF y%VelocityUVW = 0.0_ReKi ! If requested, allocate the array for passing accelerations out - if (InitInp%OutputAccel) then - call AllocAry(y%AccelUVW, 3, InitInp%NumWindPoints, "Array of wind accelerations returned by InflowWind", TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + IF ( InitInp%OutputAccel ) THEN + CALL AllocAry( y%AccelUVW, 3, InitInp%NumWindPoints, "Array of wind accelerations returned by InflowWind", TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF (ErrStat>= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF y%AccelUVW = 0.0_ReKi - end if + ENDIF !---------------------------------------------------------------------------- ! Set flow field input data based on wind type @@ -261,7 +269,7 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const InitOutData%WindFileInfo%MWS = HUGE(InitOutData%WindFileInfo%MWS) - select case (InputFileData%WindType) + select case(InputFileData%WindType) case (Steady_WindNumber) @@ -275,7 +283,7 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const if (ErrStat >= AbortErrLev) then call Cleanup() return - end if + endif case (Uniform_WindNumber) @@ -292,7 +300,7 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const if (ErrStat >= AbortErrLev) then call Cleanup() return - end if + endif case (TSFF_WindNumber) @@ -304,50 +312,50 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const if (ErrStat >= AbortErrLev) then call Cleanup() return - end if + endif case (BladedFF_WindNumber) Bladed_InitInput%TurbineID = InitInp%TurbineID - if (InitInp%FixedWindFileRootName) then ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data - if (InitInp%TurbineID == 0) then ! .TRUE. for the FAST.Farm low-resolution domain + IF ( InitInp%FixedWindFileRootName ) THEN ! .TRUE. when FAST.Farm uses multiple instances of InflowWind for ambient wind data + IF ( InitInp%TurbineID == 0 ) THEN ! .TRUE. for the FAST.Farm low-resolution domain InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'Low' - else ! FAST.Farm high-resolution domain(s) + ELSE ! FAST.Farm high-resolution domain(s) InputFileData%BladedFF_FileName = TRIM(InputFileData%BladedFF_FileName)//TRIM(PathSep)//'HighT'//TRIM(Num2Lstr(InitInp%TurbineID)) - end if - end if - Bladed_InitInput%WindType = BladedFF_WindNumber - Bladed_InitInput%WindFileName = TRIM(InputFileData%BladedFF_FileName)//'.wnd' - Bladed_InitInput%TowerFileExist = InputFileData%BladedFF_TowerFile - Bladed_InitInput%NativeBladedFmt = .false. + ENDIF + ENDIF + Bladed_InitInput%WindType = BladedFF_WindNumber + Bladed_InitInput%WindFileName = TRIM(InputFileData%BladedFF_FileName)//'.wnd' + Bladed_InitInput%TowerFileExist = InputFileData%BladedFF_TowerFile + Bladed_InitInput%NativeBladedFmt = .false. p%FlowField%FieldType = Grid3D_FieldType - call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() return - end if - + endif + case (BladedFF_Shr_WindNumber) - Bladed_InitInput%WindType = BladedFF_Shr_WindNumber - Bladed_InitInput%TurbineID = InitInp%TurbineID - Bladed_InitInput%WindFileName = InputFileData%BladedFF_FileName - Bladed_InitInput%TowerFileExist = .false. - Bladed_InitInput%NativeBladedFmt = .true. + Bladed_InitInput%WindType = BladedFF_Shr_WindNumber + Bladed_InitInput%TurbineID = InitInp%TurbineID + Bladed_InitInput%WindFileName = InputFileData%BladedFF_FileName + Bladed_InitInput%TowerFileExist = .false. + Bladed_InitInput%NativeBladedFmt = .true. p%FlowField%FieldType = Grid3D_FieldType - call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() return - end if + endif ! Overwrite the values of PropagationDir and VFlowAngle with values from the native Bladed file InputFileData%PropagationDir = Bladed_InitOutput%PropagationDir - InputFileData%VFlowAngle = Bladed_InitOutput%VFlowAngle + InputFileData%VFlowAngle = Bladed_InitOutput%VFlowAngle case (HAWC_WindNumber) @@ -376,7 +384,7 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const if (ErrStat >= AbortErrLev) then call Cleanup() return - end if + endif case (User_WindNumber) @@ -386,7 +394,7 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const if (ErrStat >= AbortErrLev) then call Cleanup() return - end if + endif case (FDext_WindNumber) @@ -395,13 +403,13 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const if (ErrStat >= AbortErrLev) then call Cleanup() return - end if + endif - ! case (Point_WindNumber) + ! case (Point_WindNumber) - ! p%FlowField%FieldType = Point_FieldType + ! p%FlowField%FieldType = Point_FieldType - case default + case default call SetErrStat(ErrID_Fatal, ' Undefined wind type.', ErrStat, ErrMsg, RoutineName) return end select @@ -424,6 +432,13 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const p%FlowField%VelInterpCubic = .false. end if + ! Set box exceed flag and index + p%FlowField%Grid3D%BoxExceedAllowF = InitInp%BoxExceedAllowF + p%FlowField%Grid3D%BoxExceedAllowIdx = huge(1_IntKi) + if (InitInp%BoxExceedAllowF .and. (InitInp%BoxExceedAllowIdx <= InitInp%NumWindPoints)) then + p%FlowField%Grid3D%BoxExceedAllowIdx = InitInp%BoxExceedAllowIdx + end if + ! Select based on field type select case (p%FlowField%FieldType) case (Uniform_FieldType) @@ -445,11 +460,9 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const p%FlowField%AccFieldValid = .true. end if - ! Set box exceedence averaging grid - p%FlowField%G3D%BoxExceedAllowF = InitInp%BoxExceedAllowF - p%FlowField%G3D%BoxExceedAllowIdx = InitInp%BoxExceedAllowIdx - if (p%FlowField%G3D%BoxExceedAllowF) then - call GenMeanGridProfileTimeSeries(p%FlowField%G3D, TmpErrStat, TmpErrMsg) + ! Calculate field average if box is allowed to be exceeded + if (p%FlowField%Grid3D%BoxExceedAllowF .and. p%FlowField%Grid3D%BoxExceedAllowIdx > 0) then + call IfW_Grid3DField_CalcVelAvgProfile(p%FlowField%Grid3D, p%FlowField%AccFieldValid, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return end if @@ -462,54 +475,54 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const end if if (p%FlowField%VelInterpCubic) then call WrScr(' Cubic velocity interpolation not implemented for WindType '// & - num2LStr(InputFileData%WindType)) + num2LStr(InputFileData%WindType)) p%FlowField%VelInterpCubic = .false. end if end select !---------------------------------------------------------------------------- ! Set the p and OtherStates for InflowWind using the input file information. - ! (set this after initializing modules so that we can use PropagationDir + ! (set this after initializing modules so that we can use PropagationDir ! and VFlowAng from native-Bladed files !---------------------------------------------------------------------------- - call InflowWind_SetParameters(InitInp, InputFileData, p, m, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - + CALL InflowWind_SetParameters( InitInp, InputFileData, p, m, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + ! Allocate arrays for the WriteOutput - call AllocAry(y%WriteOutput, p%NumOuts, 'WriteOutput', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + CALL AllocAry( y%WriteOutput, p%NumOuts, 'WriteOutput', TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF y%WriteOutput = 0.0_ReKi - - call AllocAry(InitOutData%WriteOutputHdr, p%NumOuts, 'WriteOutputHdr', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - call AllocAry(InitOutData%WriteOutputUnt, p%NumOuts, 'WriteOutputUnt', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + + CALL AllocAry( InitOutData%WriteOutputHdr, p%NumOuts, 'WriteOutputHdr', TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF + + CALL AllocAry( InitOutData%WriteOutputUnt, p%NumOuts, 'WriteOutputUnt', TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + ENDIF InitOutData%WriteOutputHdr = p%OutParam(1:p%NumOuts)%Name - InitOutData%WriteOutputUnt = p%OutParam(1:p%NumOuts)%Units + InitOutData%WriteOutputUnt = p%OutParam(1:p%NumOuts)%Units !---------------------------------------------------------------------------- ! Linearization !---------------------------------------------------------------------------- - + ! allocate and fill variables for linearization if (InitInp%Linearize) then @@ -524,84 +537,85 @@ subroutine InflowWind_Init(InitInp, InputGuess, p, ContStates, DiscStates, Const end if ! also need to add InputGuess%HubOrientation to the u%Linear items - call AllocAry(InitOutData%LinNames_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'LinNames_u', TmpErrStat, TmpErrMsg) ! add hub position, orientation(3) + extended inputs - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - call AllocAry(InitOutData%RotFrame_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'RotFrame_u', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - call AllocAry(InitOutData%IsLoad_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'IsLoad_u', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - call AllocAry(InitOutData%LinNames_y, InitInp%NumWindPoints*3 + size(y%DiskVel) + p%NumOuts, 'LinNames_y', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - call AllocAry(InitOutData%RotFrame_y, InitInp%NumWindPoints*3 + size(y%DiskVel) + p%NumOuts, 'RotFrame_y', TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - do i = 1, InitInp%NumWindPoints - do j = 1, 3 - InitOutData%LinNames_y((i - 1)*3 + j) = UVW(j)//'-component inflow velocity at node '//trim(num2lstr(i))//', m/s' - InitOutData%LinNames_u((i - 1)*3 + j) = XYZ(j)//'-component position of node '//trim(num2lstr(i))//', m' + CALL AllocAry(InitOutData%LinNames_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'LinNames_u', TmpErrStat, TmpErrMsg) ! add hub position, orientation(3) + extended inputs + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOutData%RotFrame_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'RotFrame_u', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOutData%IsLoad_u, InitInp%NumWindPoints*3 + size(InputGuess%HubPosition) + 3 + NumExtendedInputs, 'IsLoad_u', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOutData%LinNames_y, InitInp%NumWindPoints*3 + size(y%DiskVel) + p%NumOuts, 'LinNames_y', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + CALL AllocAry(InitOutData%RotFrame_y, InitInp%NumWindPoints*3 + size(y%DiskVel) + p%NumOuts, 'RotFrame_y', TmpErrStat, TmpErrMsg) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + ENDIF + + do i=1,InitInp%NumWindPoints + do j=1,3 + InitOutData%LinNames_y((i-1)*3+j) = UVW(j)//'-component inflow velocity at node '//trim(num2lstr(i))//', m/s' + InitOutData%LinNames_u((i-1)*3+j) = XYZ(j)//'-component position of node '//trim(num2lstr(i))//', m' end do end do ! hub position Lin_Indx = InitInp%NumWindPoints*3 - do j = 1, 3 - InitOutData%LinNames_y(Lin_Indx + j) = 'average '//UVW(j)//'-component rotor-disk velocity, m/s' - InitOutData%LinNames_u(Lin_Indx + j) = XYZ(j)//'-component position of moving hub, m' + do j=1,3 + InitOutData%LinNames_y(Lin_Indx+j) = 'average '//UVW(j)//'-component rotor-disk velocity, m/s' + InitOutData%LinNames_u(Lin_Indx+j) = XYZ(j)//'-component position of moving hub, m' end do Lin_Indx = Lin_Indx + 3 - + ! hub orientation angles - do j = 1, 3 - InitOutData%LinNames_u(Lin_Indx + j) = XYZ(j)//' orientation of moving hub, rad' + do j=1,3 + InitOutData%LinNames_u(Lin_Indx+j) = XYZ(j)//' orientation of moving hub, rad' end do Lin_Indx = Lin_Indx + 3 - + InitOutData%LinNames_u(Lin_Indx + 1) = 'Extended input: horizontal wind speed (steady/uniform wind), m/s' InitOutData%LinNames_u(Lin_Indx + 2) = 'Extended input: vertical power-law shear exponent, -' - InitOutData%LinNames_u(Lin_Indx + 3) = 'Extended input: propagation direction, rad' - - do i = 1, p%NumOuts - InitOutData%LinNames_y(i + 3*InitInp%NumWindPoints + size(y%DiskVel)) = trim(p%OutParam(i)%Name)//', '//p%OutParam(i)%Units + InitOutData%LinNames_u(Lin_Indx + 3) = 'Extended input: propagation direction, rad' + + do i=1,p%NumOuts + InitOutData%LinNames_y(i+3*InitInp%NumWindPoints+size(y%DiskVel)) = trim(p%OutParam(i)%Name)//', '//p%OutParam(i)%Units end do ! IfW inputs and outputs are in the global, not rotating frame - InitOutData%RotFrame_u = .false. - InitOutData%RotFrame_y = .false. + InitOutData%RotFrame_u = .false. + InitOutData%RotFrame_y = .false. InitOutData%IsLoad_u = .false. ! IfW inputs for linearization are not loads - + end if - + ! Set the version information in InitOutData InitOutData%Ver = IfW_Ver - call CleanUp() + CALL CleanUp() -contains +CONTAINS - subroutine CleanUp() + SUBROUTINE CleanUp() ! add in stuff that we need to dispose of here - call InflowWind_DestroyInputFile(InputFileData, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + CALL InflowWind_DestroyInputFile( InputFileData, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) ! Ignore error messages from InFileInfo destruction - call NWTC_Library_DestroyFileInfoType(InFileInfo, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + call NWTC_Library_DestroyFileInfoType( InFileInfo, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) - ! Close the summary file if we were writing one - if (SumFileUnit > 0) then - call InflowWind_CloseSumFile(SumFileUnit, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - end if + ! Close the summary file if we were writing one + IF ( SumFileUnit > 0 ) THEN + CALL InflowWind_CloseSumFile( SumFileUnit, TmpErrStat, TmpErrMsg ) + CALL SetErrStat(TmpErrStat,TmpErrMsg,ErrStat,ErrMsg,RoutineName) + ENDIF - end subroutine CleanUp + END SUBROUTINE CleanUp + +END SUBROUTINE InflowWind_Init -end subroutine InflowWind_Init !==================================================================================================== !> This routine takes an input dataset of type InputType which contains a position array of dimensions 3*n. It then calculates @@ -618,248 +632,263 @@ end subroutine InflowWind_Init !! array is then rotated by p%PropagationDir so that it now corresponds the the global coordinate UVW values for wind !! with that direction. !---------------------------------------------------------------------------------------------------- -subroutine InflowWind_CalcOutput(Time, InputData, p, & - ContStates, DiscStates, ConstrStates, & ! Framework required states -- empty in this case. - OtherStates, OutputData, m, ErrStat, ErrMsg) - - character(*), parameter :: RoutineName = "InflowWind_CalcOutput" - - real(DbKi), intent(IN) :: Time !< Current simulation time in seconds - type(InflowWind_InputType), intent(IN) :: InputData !< Inputs at Time - type(InflowWind_ParameterType), intent(IN) :: p !< Parameters - type(InflowWind_ContinuousStateType), intent(IN) :: ContStates !< Continuous states at Time - type(InflowWind_DiscreteStateType), intent(IN) :: DiscStates !< Discrete states at Time - type(InflowWind_ConstraintStateType), intent(IN) :: ConstrStates !< Constraint states at Time - type(InflowWind_OtherStateType), intent(IN) :: OtherStates !< Other/optimization states at Time - type(InflowWind_OutputType), intent(INOUT) :: OutputData !< Outputs computed at Time (IN for mesh reasons and data allocation) - type(InflowWind_MiscVarType), intent(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - integer(IntKi), intent(OUT) :: ErrStat !< Error status of the operation - character(*), intent(OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - - ! Local variables - integer(IntKi) :: i - ! Temporary variables for error handling - integer(IntKi) :: TmpErrStat - character(ErrMsgLen) :: TmpErrMsg ! temporary error message - - ErrStat = ErrID_None - ErrMsg = "" - - ! Allocate the velocity array to get out - if (.not. ALLOCATED(OutputData%VelocityUVW)) then - call AllocAry(OutputData%VelocityUVW, 3, SIZE(InputData%PositionXYZ, DIM=2), & - "Velocity array returned from IfW_CalcOutput", TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return - elseif (SIZE(InputData%PositionXYZ, DIM=2) /= SIZE(OutputData%VelocityUVW, DIM=2)) then - call SetErrStat(ErrID_Fatal, " Programming error: Position and Velocity arrays are not sized the same.", & - ErrStat, ErrMsg, RoutineName) - end if +SUBROUTINE InflowWind_CalcOutput( Time, InputData, p, & + ContStates, DiscStates, ConstrStates, & ! Framework required states -- empty in this case. + OtherStates, OutputData, m, ErrStat, ErrMsg ) + + CHARACTER(*), PARAMETER :: RoutineName="InflowWind_CalcOutput" + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(InflowWind_InputType), INTENT(IN ) :: InputData !< Inputs at Time + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: ContStates !< Continuous states at Time + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: DiscStates !< Discrete states at Time + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: ConstrStates !< Constraint states at Time + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherStates !< Other/optimization states at Time + TYPE(InflowWind_OutputType), INTENT(INOUT) :: OutputData !< Outputs computed at Time (IN for mesh reasons and data allocation) + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + ! Local variables + INTEGER(IntKi) :: i + ! Temporary variables for error handling + INTEGER(IntKi) :: TmpErrStat + CHARACTER(ErrMsgLen) :: TmpErrMsg ! temporary error message + + ErrStat = ErrID_None + ErrMsg = "" + + ! Allocate the velocity array to get out + IF ( .NOT. ALLOCATED(OutputData%VelocityUVW) ) THEN + CALL AllocAry( OutputData%VelocityUVW, 3, SIZE(InputData%PositionXYZ,DIM=2), & + "Velocity array returned from IfW_CalcOutput", TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + ELSEIF ( SIZE(InputData%PositionXYZ,DIM=2) /= SIZE(OutputData%VelocityUVW,DIM=2) ) THEN + CALL SetErrStat( ErrID_Fatal," Programming error: Position and Velocity arrays are not sized the same.", & + ErrStat, ErrMsg, RoutineName) + ENDIF !----------------------------- ! Outputs: OutputData%VelocityUVW !----------------------------- - call CalculateOutput(Time, InputData, p, ContStates, DiscStates, ConstrStates, & - OtherStates, OutputData, m, .true., TmpErrStat, TmpErrMsg) + CALL CalculateOutput( Time, InputData, p, ContStates, DiscStates, ConstrStates, & + OtherStates, OutputData, m, .TRUE., TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) !----------------------------- ! Output: OutputData%DiskVel !----------------------------- - call InflowWind_GetSpatialAverage(Time, InputData, p, ContStates, DiscStates, ConstrStates, & - OtherStates, m, OutputData%DiskVel, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - + CALL InflowWind_GetSpatialAverage( Time, InputData, p, ContStates, DiscStates, ConstrStates, & + OtherStates, m, OutputData%DiskVel, TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + !----------------------------- ! Output: OutputData%HubVel !----------------------------- - call InflowWind_GetHubValues(Time, InputData, p, ContStates, DiscStates, ConstrStates, & - OtherStates, m, OutputData%HubVel, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - + CALL InflowWind_GetHubValues( Time, InputData, p, ContStates, DiscStates, ConstrStates, & + OtherStates, m, OutputData%HubVel, TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + !----------------------------- ! Outputs: OutputData%lidar%LidSpeed and OutputData%lidar%WtTrunc !----------------------------- - - ! return sensor values - if (p%lidar%SensorType /= SensorType_None) then - - call Lidar_CalcOutput(Time, InputData, p, & - ContStates, DiscStates, ConstrStates, OtherStates, & - OutputData, m, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - - end if - + + ! return sensor values + IF (p%lidar%SensorType /= SensorType_None) THEN + + CALL Lidar_CalcOutput(Time, InputData, p, & + ContStates, DiscStates, ConstrStates, OtherStates, & + OutputData, m, TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + + END IF + + !----------------------------- ! Outputs: OutputData%WriteOutput from m%AllOuts and OutputData%lidar%LidSpeed !----------------------------- - call SetAllOuts(p, OutputData, m, TmpErrStat, TmpErrMsg) - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + CALL SetAllOuts( p, OutputData, m, TmpErrStat, TmpErrMsg ) + CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) + + ! Map to the outputs + DO I = 1,p%NumOuts ! Loop through all selected output channels + OutputData%WriteOutput(I) = p%OutParam(I)%SignM * m%AllOuts( p%OutParam(I)%Indx ) + ENDDO ! I - All selected output channels + + +END SUBROUTINE InflowWind_CalcOutput - ! Map to the outputs - do I = 1, p%NumOuts ! Loop through all selected output channels - OutputData%WriteOutput(I) = p%OutParam(I)%SignM*m%AllOuts(p%OutParam(I)%Indx) - end do ! I - All selected output channels -end subroutine InflowWind_CalcOutput !==================================================================================================== !> Clean up the allocated variables and close all open files. Reset the initialization flag so !! that we have to reinitialize before calling the routines again. -subroutine InflowWind_End(InputData, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & - y, m, ErrStat, ErrMsg) - - type(InflowWind_InputType), intent(INOUT) :: InputData !< Input data for initialization - type(InflowWind_ParameterType), intent(INOUT) :: p !< Parameters - type(InflowWind_ContinuousStateType), intent(INOUT) :: ContStates !< Continuous states - type(InflowWind_DiscreteStateType), intent(INOUT) :: DiscStates !< Discrete states - type(InflowWind_ConstraintStateType), intent(INOUT) :: ConstrStateGuess !< Guess of the constraint states - type(InflowWind_OtherStateType), intent(INOUT) :: OtherStates !< Other/optimization states - type(InflowWind_OutputType), intent(INOUT) :: y !< Output data - type(InflowWind_MiscVarType), intent(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - integer(IntKi), intent(OUT) :: ErrStat !< error status - character(*), intent(OUT) :: ErrMsg !< error message - - character(*), parameter :: RoutineName = "InflowWind_End" +SUBROUTINE InflowWind_End( InputData, p, ContStates, DiscStates, ConstrStateGuess, OtherStates, & + y, m, ErrStat, ErrMsg ) + + TYPE(InflowWind_InputType), INTENT(INOUT) :: InputData !< Input data for initialization + TYPE(InflowWind_ParameterType), INTENT(INOUT) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(INOUT) :: ContStates !< Continuous states + TYPE(InflowWind_DiscreteStateType), INTENT(INOUT) :: DiscStates !< Discrete states + TYPE(InflowWind_ConstraintStateType), INTENT(INOUT) :: ConstrStateGuess !< Guess of the constraint states + TYPE(InflowWind_OtherStateType), INTENT(INOUT) :: OtherStates !< Other/optimization states + TYPE(InflowWind_OutputType), INTENT(INOUT) :: y !< Output data + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + INTEGER( IntKi ), INTENT( OUT) :: ErrStat !< error status + CHARACTER(*), INTENT( OUT) :: ErrMsg !< error message + + CHARACTER(*), PARAMETER :: RoutineName="InflowWind_End" ErrStat = ErrID_None ErrMsg = "" ! Reset the wind type so that the initialization routine must be called - p%WindType = Undef_WindNumber + p%WindType = Undef_WindNumber ! Destroy all inflow wind derived types - call InflowWind_DestroyInput(InputData, ErrStat, ErrMsg) - call InflowWind_DestroyParam(p, ErrStat, ErrMsg, DeallocatePointers=.true.) - call InflowWind_DestroyContState(ContStates, ErrStat, ErrMsg) - call InflowWind_DestroyDiscState(DiscStates, ErrStat, ErrMsg) - call InflowWind_DestroyConstrState(ConstrStateGuess, ErrStat, ErrMsg) - call InflowWind_DestroyOtherState(OtherStates, ErrStat, ErrMsg) - call InflowWind_DestroyOutput(y, ErrStat, ErrMsg) - call InflowWind_DestroyMisc(m, ErrStat, ErrMsg) + CALL InflowWind_DestroyInput( InputData, ErrStat, ErrMsg ) + CALL InflowWind_DestroyParam( p, ErrStat, ErrMsg, DeallocatePointers=.true. ) + CALL InflowWind_DestroyContState( ContStates, ErrStat, ErrMsg ) + CALL InflowWind_DestroyDiscState( DiscStates, ErrStat, ErrMsg ) + CALL InflowWind_DestroyConstrState( ConstrStateGuess, ErrStat, ErrMsg ) + CALL InflowWind_DestroyOtherState( OtherStates, ErrStat, ErrMsg ) + CALL InflowWind_DestroyOutput( y, ErrStat, ErrMsg ) + CALL InflowWind_DestroyMisc( m, ErrStat, ErrMsg ) + +END SUBROUTINE InflowWind_End -end subroutine InflowWind_End !==================================================================================================== ! The following routines were added to satisfy the framework, but do nothing useful. !==================================================================================================== -!> This is a loose coupling routine for solving constraint states, integrating continuous states, and updating discrete and other +!> This is a loose coupling routine for solving constraint states, integrating continuous states, and updating discrete and other !! states. Continuous, constraint, discrete, and other states are updated to values at t + Interval. -subroutine InflowWind_UpdateStates(t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg) - - real(DbKi), intent(IN) :: t !< Current simulation time in seconds - integer(IntKi), intent(IN) :: n !< Current step of the simulation: t = n*Interval - type(InflowWind_InputType), intent(INOUT) :: Inputs(:) !< Inputs at InputTimes (output only for mesh record-keeping in ExtrapInterp routine) - real(DbKi), intent(IN) :: InputTimes(:) !< Times in seconds associated with Inputs - type(InflowWind_ParameterType), intent(IN) :: p !< Parameters - type(InflowWind_ContinuousStateType), intent(INOUT) :: x !< Input: Continuous states at t; +SUBROUTINE InflowWind_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + INTEGER(IntKi), INTENT(IN ) :: n !< Current step of the simulation: t = n*Interval + TYPE(InflowWind_InputType), INTENT(INOUT) :: Inputs(:) !< Inputs at InputTimes (output only for mesh record-keeping in ExtrapInterp routine) + REAL(DbKi), INTENT(IN ) :: InputTimes(:) !< Times in seconds associated with Inputs + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(INOUT) :: x !< Input: Continuous states at t; !! Output: Continuous states at t + Interval - type(InflowWind_DiscreteStateType), intent(INOUT) :: xd !< Input: Discrete states at t; + TYPE(InflowWind_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at t; !! Output: Discrete states at t + Interval - type(InflowWind_ConstraintStateType), intent(INOUT) :: z !< Input: Constraint states at t; + TYPE(InflowWind_ConstraintStateType), INTENT(INOUT) :: z !< Input: Constraint states at t; !! Output: Constraint states at t + Interval - type(InflowWind_OtherStateType), intent(INOUT) :: OtherState !< Other states: Other states at t; + TYPE(InflowWind_OtherStateType), INTENT(INOUT) :: OtherState !< Other states: Other states at t; !! Output: Other states at t + Interval - type(InflowWind_MiscVarType), intent(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - integer(IntKi), intent(OUT) :: ErrStat !< Error status of the operation - character(*), intent(OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + - ! Initialize ErrStat + ! Initialize ErrStat ErrStat = ErrID_None - ErrMsg = "" + ErrMsg = "" - x%DummyContState = 0.0_ReKi - xd%DummyDiscState = 0.0_ReKi - z%DummyConstrState = 0.0_ReKi + x%DummyContState = 0.0_ReKi + xd%DummyDiscState = 0.0_ReKi + z%DummyConstrState = 0.0_ReKi + + RETURN - return -end subroutine InflowWind_UpdateStates +END SUBROUTINE InflowWind_UpdateStates !---------------------------------------------------------------------------------------------------------------------------------- !> Tight coupling routine for computing derivatives of continuous states -subroutine InflowWind_CalcContStateDeriv(Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg) +SUBROUTINE InflowWind_CalcContStateDeriv( Time, u, p, x, xd, z, OtherState, m, dxdt, ErrStat, ErrMsg ) !.................................................................................................................................. - real(DbKi), intent(IN) :: Time !< Current simulation time in seconds - type(InflowWind_InputType), intent(IN) :: u !< Inputs at Time - type(InflowWind_ParameterType), intent(IN) :: p !< Parameters - type(InflowWind_ContinuousStateType), intent(IN) :: x !< Continuous states at Time - type(InflowWind_DiscreteStateType), intent(IN) :: xd !< Discrete states at Time - type(InflowWind_ConstraintStateType), intent(IN) :: z !< Constraint states at Time - type(InflowWind_OtherStateType), intent(IN) :: OtherState !< Other states at Time - type(InflowWind_MiscVarType), intent(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - type(InflowWind_ContinuousStateType), intent(OUT) :: dxdt !< Continuous state derivatives at Time - integer(IntKi), intent(OUT) :: ErrStat !< Error status of the operation - character(*), intent(OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(InflowWind_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(InflowWind_ContinuousStateType), INTENT( OUT) :: dxdt !< Continuous state derivatives at Time + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + - ! Initialize ErrStat + ! Initialize ErrStat ErrStat = ErrID_None - ErrMsg = "" + ErrMsg = "" + - ! Compute the first time derivatives of the continuous states here: + ! Compute the first time derivatives of the continuous states here: dxdt%DummyContState = 0.0_ReKi -end subroutine InflowWind_CalcContStateDeriv + +END SUBROUTINE InflowWind_CalcContStateDeriv !---------------------------------------------------------------------------------------------------------------------------------- !> Tight coupling routine for updating discrete states -subroutine InflowWind_UpdateDiscState(Time, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg) +SUBROUTINE InflowWind_UpdateDiscState( Time, u, p, x, xd, z, OtherState, m, ErrStat, ErrMsg ) - real(DbKi), intent(IN) :: Time !< Current simulation time in seconds - type(InflowWind_InputType), intent(IN) :: u !< Inputs at Time - type(InflowWind_ParameterType), intent(IN) :: p !< Parameters - type(InflowWind_ContinuousStateType), intent(IN) :: x !< Continuous states at Time - type(InflowWind_DiscreteStateType), intent(INOUT) :: xd !< Input: Discrete states at Time; + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(InflowWind_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(InflowWind_DiscreteStateType), INTENT(INOUT) :: xd !< Input: Discrete states at Time; !! Output: Discrete states at Time + Interval - type(InflowWind_ConstraintStateType), intent(IN) :: z !< Constraint states at Time - type(InflowWind_OtherStateType), intent(IN) :: OtherState !< Other states at Time - type(InflowWind_MiscVarType), intent(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - integer(IntKi), intent(OUT) :: ErrStat !< Error status of the operation - character(*), intent(OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + - ! Initialize ErrStat + ! Initialize ErrStat ErrStat = ErrID_None - ErrMsg = "" + ErrMsg = "" + - ! Update discrete states here: + ! Update discrete states here: ! StateData%DiscState = -end subroutine InflowWind_UpdateDiscState +END SUBROUTINE InflowWind_UpdateDiscState !---------------------------------------------------------------------------------------------------------------------------------- !> Tight coupling routine for solving for the residual of the constraint state equations -subroutine InflowWind_CalcConstrStateResidual(Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg) - - real(DbKi), intent(IN) :: Time !< Current simulation time in seconds - type(InflowWind_InputType), intent(IN) :: u !< Inputs at Time - type(InflowWind_ParameterType), intent(IN) :: p !< Parameters - type(InflowWind_ContinuousStateType), intent(IN) :: x !< Continuous states at Time - type(InflowWind_DiscreteStateType), intent(IN) :: xd !< Discrete states at Time - type(InflowWind_ConstraintStateType), intent(IN) :: z !< Constraint states at Time (possibly a guess) - type(InflowWind_OtherStateType), intent(IN) :: OtherState !< Other states at Time - type(InflowWind_MiscVarType), intent(INOUT) :: m !< Misc variables for optimization (not copied in glue code) - type(InflowWind_ConstraintStateType), intent(OUT) :: z_residual !< Residual of the constraint state equations using +SUBROUTINE InflowWind_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_residual, ErrStat, ErrMsg ) + + REAL(DbKi), INTENT(IN ) :: Time !< Current simulation time in seconds + TYPE(InflowWind_InputType), INTENT(IN ) :: u !< Inputs at Time + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at Time + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at Time + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at Time (possibly a guess) + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherState !< Other states at Time + TYPE(InflowWind_MiscVarType), INTENT(INOUT) :: m !< Misc variables for optimization (not copied in glue code) + TYPE(InflowWind_ConstraintStateType), INTENT( OUT) :: z_residual !< Residual of the constraint state equations using !! the input values described above - integer(IntKi), intent(OUT) :: ErrStat !< Error status of the operation - character(*), intent(OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! Initialize ErrStat + + ! Initialize ErrStat ErrStat = ErrID_None - ErrMsg = "" + ErrMsg = "" - ! Solve for the constraint states here: + + ! Solve for the constraint states here: z_residual%DummyConstrState = 0 -end subroutine InflowWind_CalcConstrStateResidual +END SUBROUTINE InflowWind_CalcConstrStateResidual !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! ###### The following four routines are Jacobian routines for linearization capabilities ####### @@ -867,38 +896,39 @@ end subroutine InflowWind_CalcConstrStateResidual !---------------------------------------------------------------------------------------------------------------------------------- !> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions !! with respect to the inputs (u). The partial derivatives dY/du, dX/du, dXd/du, and dZ/du are returned. -subroutine InflowWind_JacobianPInput(t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdu, dXdu, dXddu, dZdu) +SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdu, dXdu, dXddu, dZdu ) !.................................................................................................................................. - real(DbKi), intent(IN) :: t !< Time in seconds at operating point - type(InflowWind_InputType), intent(IN) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) - type(InflowWind_ParameterType), intent(IN) :: p !< Parameters - type(InflowWind_ContinuousStateType), intent(IN) :: x !< Continuous states at operating point - type(InflowWind_DiscreteStateType), intent(IN) :: xd !< Discrete states at operating point - type(InflowWind_ConstraintStateType), intent(IN) :: z !< Constraint states at operating point - type(InflowWind_OtherStateType), intent(IN) :: OtherState !< Other states at operating point - type(InflowWind_OutputType), intent(IN) :: y !< Output (change to inout if a mesh copy is required); - !! Output fields are not used by this routine, but type is - !! available here so that mesh parameter information (i.e., + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(InflowWind_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(InflowWind_OutputType), INTENT(IN ) :: y !< Output (change to inout if a mesh copy is required); + !! Output fields are not used by this routine, but type is + !! available here so that mesh parameter information (i.e., !! connectivity) does not have to be recalculated for dYdu. - type(InflowWind_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 - real(R8Ki), allocatable, optional, intent(INOUT) :: dYdu(:, :) !< Partial derivatives of output functions (Y) + TYPE(InflowWind_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 + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dYdu(:,:) !< Partial derivatives of output functions (Y) !! with respect to inputs (u) [intent in to avoid deallocation] - real(R8Ki), allocatable, optional, intent(INOUT) :: dXdu(:, :) !< Partial derivatives of continuous state functions (X) + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdu(:,:) !< Partial derivatives of continuous state functions (X) !! with respect to inputs (u) [intent in to avoid deallocation] - real(R8Ki), allocatable, optional, intent(INOUT) :: dXddu(:, :) !< Partial derivatives of discrete state functions (Xd) + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddu(:,:) !< Partial derivatives of discrete state functions (Xd) !! with respect to inputs (u) [intent in to avoid deallocation] - real(R8Ki), allocatable, optional, intent(INOUT) :: dZdu(:, :) !< Partial derivatives of constraint state functions (Z) + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdu(:,:) !< Partial derivatives of constraint state functions (Z) !! with respect to inputs (u) [intent in to avoid deallocation] - - ! local variables: - integer(IntKi) :: ErrStat2 - character(ErrMsgLen) :: ErrMsg2 ! temporary error message - character(*), parameter :: RoutineName = 'InflowWind_JacobianPInput' - - real(R8Ki) :: local_dYdu(3, 3 + NumExtendedInputs) + + ! local variables: + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 ! temporary error message + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_JacobianPInput' + + + REAL(R8Ki) :: local_dYdu(3,3+NumExtendedInputs) integer :: i, n integer :: i_start, i_end ! indices for input/output start and end integer :: node, comp @@ -906,174 +936,562 @@ subroutine InflowWind_JacobianPInput(t, u, p, x, xd, z, OtherState, y, m, ErrSta integer :: n_outputs integer :: i_ExtendedInput_start integer :: i_WriteOutput - - ! Initialize ErrStat + + + ! Initialize ErrStat ErrStat = ErrID_None - ErrMsg = '' + ErrMsg = '' - if (PRESENT(dYdu)) then - n_outputs = SIZE(u%PositionXYZ) + p%NumOuts + size(y%DiskVel) - n_inputs = SIZE(u%PositionXYZ) + size(u%HubPosition) + 3 + NumExtendedInputs ! need to add 3 for u%HubOrientation - i_ExtendedInput_start = n_inputs - NumExtendedInputs + 1 ! index for extended inputs starts 2 from end (encompasses 3 values: V, VShr, PropDir) - i_WriteOutput = n_outputs - p%NumOuts ! index for where write outputs begin is i_WriteOutput + 1 + IF ( PRESENT( dYdu ) ) THEN + n_outputs = SIZE(u%PositionXYZ)+p%NumOuts + size(y%DiskVel) + n_inputs = SIZE(u%PositionXYZ)+size(u%HubPosition) + 3 + NumExtendedInputs ! need to add 3 for u%HubOrientation + i_ExtendedInput_start = n_inputs - NumExtendedInputs + 1 ! index for extended inputs starts 2 from end (encompasses 3 values: V, VShr, PropDir) + i_WriteOutput = n_outputs - p%NumOuts ! index for where write outputs begin is i_WriteOutput + 1 + ! Calculate the partial derivative of the output functions (Y) with respect to the inputs (u) here: - - ! outputs are all velocities at all positions plus the WriteOutput values - ! + + ! outputs are all velocities at all positions plus the WriteOutput values + ! if (.not. ALLOCATED(dYdu)) then - call AllocAry(dYdu, n_outputs, n_inputs, 'dYdu', ErrStat2, ErrMsg2) - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + CALL AllocAry( dYdu, n_outputs, n_inputs, 'dYdu', ErrStat2, ErrMsg2 ) + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) end if - - select case (p%WindType) - case (Steady_WindNumber, Uniform_WindNumber) - - ! note that we are including the propagation direction in the analytical derivative calculated - ! inside IfW_UniformWind_JacobianPInput, so no need to transform input position vectors first - - dYdu = 0.0_R8Ki ! initialize all non-diagonal entries to zero (position of node effects the output of only that node) - - n = SIZE(u%PositionXYZ, 2) - ! these are the positions used in the module coupling - do i = 1, n + + + SELECT CASE ( p%WindType ) + CASE (Steady_WindNumber, Uniform_WindNumber) + + ! note that we are including the propagation direction in the analytical derivative calculated + ! inside IfW_UniformWind_JacobianPInput, so no need to transform input position vectors first + + dYdu = 0.0_R8Ki ! initialize all non-diagonal entries to zero (position of node effects the output of only that node) + + n = SIZE(u%PositionXYZ,2) + ! these are the positions used in the module coupling + do i=1,n ! note that p%FlowField%RotToWind(1,1) = cos(p%PropagationDir) and p%FlowField%RotToWind(2,1) = sin(p%PropagationDir), which are the ! values we need to compute the jacobian. -!!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput(p%FlowField%Uniform, t, u%PositionXYZ(:, i), p%FlowField%RotToWind(1, 1), p%FlowField%RotToWind(2, 1), local_dYdu) - - i_end = 3*i - i_start = i_end - 2 - - dYdu(i_start:i_end, i_start:i_end) = local_dYdu(:, 1:3) - - dYdu(i_start:i_end, i_ExtendedInput_start:) = local_dYdu(:, 4:6) ! extended inputs - +!!!FIX ME with the propagation values!!!! + call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, u%PositionXYZ(:,i), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) + + i_end = 3*i + i_start= i_end - 2 + + dYdu(i_start:i_end,i_start:i_end) = local_dYdu(:,1:3) + + dYdu(i_start:i_end, i_ExtendedInput_start:) = local_dYdu(:,4:6) ! extended inputs + end do - + + ! see InflowWind_GetSpatialAverage(): - + ! location of y%DiskAvg i_start = 3*n + 1 - i_end = i_start + 2 - - dYdu(i_start:i_end, :) = 0.0_R8Ki ! initialize because we're going to create averages - - do i = 1, IfW_NumPtsAvg - m%u_Avg%PositionXYZ(:, i) = matmul(u%HubOrientation, p%PositionAvg(:, i)) + u%HubPosition -!!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput(p%FlowField%Uniform, t, m%u_Avg%PositionXYZ(:, i), p%FlowField%RotToWind(1, 1), p%FlowField%RotToWind(2, 1), local_dYdu) - + i_end = i_start + 2 + + dYdu(i_start:i_end,:) = 0.0_R8Ki ! initialize because we're going to create averages + + do i=1,IfW_NumPtsAvg + m%u_Avg%PositionXYZ(:,i) = matmul(u%HubOrientation,p%PositionAvg(:,i)) + u%HubPosition +!!!FIX ME with the propagation values!!!! + call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, m%u_Avg%PositionXYZ(:,i), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) + ! y%DiskAvg has the same index as u%HubPosition ! Also note that partial_(m%u_Avg%PositionXYZ) / partial_(u%HubPosition) is identity, so we can skip that part of the chain rule for these derivatives: - dYdu(i_start:i_end, i_start:i_end) = dYdu(i_start:i_end, i_start:i_end) + local_dYdu(:, 1:3) - dYdu(i_start:i_end, i_ExtendedInput_start:) = dYdu(i_start:i_end, i_ExtendedInput_start:) + local_dYdu(:, 4:6) ! extended inputs + dYdu(i_start:i_end,i_start:i_end) = dYdu(i_start:i_end, i_start:i_end) + local_dYdu(:,1:3) + dYdu(i_start:i_end, i_ExtendedInput_start:) = dYdu(i_start:i_end, i_ExtendedInput_start:) + local_dYdu(:,4:6) ! extended inputs end do - dYdu(i_start:i_end, i_start:i_end) = dYdu(i_start:i_end, i_start:i_end)/real(IfW_NumPtsAvg, R8Ki) - dYdu(i_start:i_end, i_ExtendedInput_start:) = dYdu(i_start:i_end, i_ExtendedInput_start:)/real(IfW_NumPtsAvg, R8Ki) + dYdu(i_start:i_end,i_start:i_end) = dYdu(i_start:i_end, i_start:i_end) / REAL(IfW_NumPtsAvg,R8Ki) + dYdu(i_start:i_end,i_ExtendedInput_start:) = dYdu(i_start:i_end, i_ExtendedInput_start:) / REAL(IfW_NumPtsAvg,R8Ki) !FIX ME: ! need to calculate dXYZdHubOrient = partial_(m%u_Avg%PositionXYZ) / partial_(u%HubOrientation) !dYdu(i_start:i_end,(i_start+3):(i_end+3)) = matmul( dYdu(i_start:i_end,i_start:i_end), dXYZdHubOrient ) - ! these are the InflowWind WriteOutput velocities (and note that we may not have all of the components of each point) + + ! these are the InflowWind WriteOutput velocities (and note that we may not have all of the components of each point) ! they do not depend on the inputs, so the derivatives w.r.t. X, Y, Z are all zero - do i = 1, p%NumOuts - node = p%OutParamLinIndx(1, i) ! output node - comp = p%OutParamLinIndx(2, i) ! component of output node + do i=1, p%NumOuts + node = p%OutParamLinIndx(1,i) ! output node + comp = p%OutParamLinIndx(2,i) ! component of output node if (node > 0) then -!!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput(p%FlowField%Uniform, t, p%WindViXYZ(:, node), p%FlowField%RotToWind(1, 1), p%FlowField%RotToWind(2, 1), local_dYdu) +!!!FIX ME with the propagation values!!!! + call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, p%WindViXYZ(:,node), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) else local_dYdu = 0.0_R8Ki comp = 1 end if - - dYdu(i_WriteOutput + i, i_ExtendedInput_start:) = p%OutParam(i)%SignM*local_dYdu(comp, 4:6) + + dYdu(i_WriteOutput+i, i_ExtendedInput_start:) = p%OutParam(i)%SignM * local_dYdu( comp , 4:6) end do - case DEFAULT + CASE DEFAULT - end select + END SELECT + + END IF - end if + IF ( PRESENT( dXdu ) ) THEN + if (allocated(dXdu)) deallocate(dXdu) + END IF - if (PRESENT(dXdu)) then - if (allocated(dXdu)) deallocate (dXdu) - end if + IF ( PRESENT( dXddu ) ) THEN + if (allocated(dXddu)) deallocate(dXddu) + END IF - if (PRESENT(dXddu)) then - if (allocated(dXddu)) deallocate (dXddu) - end if + IF ( PRESENT( dZdu ) ) THEN + if (allocated(dZdu)) deallocate(dZdu) + END IF - if (PRESENT(dZdu)) then - if (allocated(dZdu)) deallocate (dZdu) - end if -end subroutine InflowWind_JacobianPInput +END SUBROUTINE InflowWind_JacobianPInput !.................................................................................................................................. -!> Routine to compute the Jacobians of the output (Y) function with respect to the inputs (u). The partial +!> Routine to compute the Jacobians of the output (Y) function with respect to the inputs (u). The partial !! derivative dY/du is returned. This submodule does not follow the modularization framework. -subroutine IfW_UniformWind_JacobianPInput(UF, t, Position, CosPropDir, SinPropDir, dYdu) - use IfW_FlowField, only: UniformField_InterpLinear, UniformField_InterpCubic - - type(UniformFieldType), intent(IN) :: UF !< Uniform field derived type - real(DbKi), intent(IN) :: t !< Current simulation time in seconds - real(ReKi), intent(IN) :: Position(3) !< XYZ Position at which to find velocity (operating point) - real(ReKi), intent(IN) :: CosPropDir !< cosine of InflowWind propagation direction - real(ReKi), intent(IN) :: SinPropDir !< sine of InflowWind propagation direction - real(R8Ki), intent(INOUT) :: dYdu(3, 6) !< Partial derivatives of output functions (Y) with respect to the inputs (u) - - type(UniformField_Interp) :: op ! interpolated values of InterpParams - real(R8Ki) :: RotatePosition(3) !< rotated position - real(R8Ki) :: dVhdx ! temporary value to hold partial v_h partial X - real(R8Ki) :: dVhdy ! temporary value to hold partial v_h partial Y - real(R8Ki) :: dVhdz ! temporary value to hold partial v_h partial Z - real(R8Ki) :: tmp_du ! temporary value to hold calculations that are part of multiple components - real(R8Ki) :: tmp_dv ! temporary value to hold calculations that are part of multiple components - real(R8Ki) :: dVhdPD ! temporary value to hold partial v_h partial propagation direction - real(R8Ki) :: dVhdV ! temporary value to hold partial v_h partial V - real(R8Ki) :: Vh ! temporary value to hold v_h - real(R8Ki) :: dVhdVShr ! temporary value to hold partial v_h partial VShr - real(R8Ki) :: zr - - if (Position(3) < 0.0_ReKi .or. EqualRealNos(Position(3), 0.0_ReKi)) then +SUBROUTINE IfW_UniformWind_JacobianPInput(UF, t, Position, CosPropDir, SinPropDir, dYdu) + USE IfW_FlowField, only : UniformField_InterpLinear, UniformField_InterpCubic + + TYPE(UniformFieldType), INTENT(IN ) :: UF !< Uniform field derived type + REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds + REAL(ReKi), INTENT(IN ) :: Position(3) !< XYZ Position at which to find velocity (operating point) + REAL(ReKi), INTENT(IN ) :: CosPropDir !< cosine of InflowWind propagation direction + REAL(ReKi), INTENT(IN ) :: SinPropDir !< sine of InflowWind propagation direction + REAL(R8Ki), INTENT(INOUT) :: dYdu(3,6) !< Partial derivatives of output functions (Y) with respect to the inputs (u) + + TYPE(UniformField_Interp) :: op ! interpolated values of InterpParams + REAL(R8Ki) :: RotatePosition(3) !< rotated position + REAL(R8Ki) :: dVhdx ! temporary value to hold partial v_h partial X + REAL(R8Ki) :: dVhdy ! temporary value to hold partial v_h partial Y + REAL(R8Ki) :: dVhdz ! temporary value to hold partial v_h partial Z + REAL(R8Ki) :: tmp_du ! temporary value to hold calculations that are part of multiple components + REAL(R8Ki) :: tmp_dv ! temporary value to hold calculations that are part of multiple components + REAL(R8Ki) :: dVhdPD ! temporary value to hold partial v_h partial propagation direction + REAL(R8Ki) :: dVhdV ! temporary value to hold partial v_h partial V + REAL(R8Ki) :: Vh ! temporary value to hold v_h + REAL(R8Ki) :: dVhdVShr ! temporary value to hold partial v_h partial VShr + REAL(R8Ki) :: zr + + if ( Position(3) < 0.0_ReKi .or. EqualRealNos(Position(3), 0.0_ReKi)) then dYdu = 0.0_R8Ki return - end if - + end if + !------------------------------------------------------------------------------------------------- !> 1. Interpolate uniform field to get values at operating point !------------------------------------------------------------------------------------------------- op = UniformField_InterpLinear(UF, t) - + RotatePosition(1) = Position(1)*cosPropDir - Position(2)*sinPropDir RotatePosition(2) = Position(1)*sinPropDir + Position(2)*cosPropDir RotatePosition(3) = Position(3) - + !------------------------------------------------------------------------------------------------- - !> 2. Calculate $ rac{\partial Y_{Output \, Equations}}{\partial u_{inputs}} = egin{bmatrix} - !! rac{\partial Vt_u}{\partial X} & rac{\partial Vt_u}{\partial Y} & rac{\partial Vt_u}{\partial Z} !! rac{\partial Vt_v}{\partial X} & rac{\partial Vt_v}{\partial Y} & rac{\partial Vt_v}{\partial Z} !! rac{\partial Vt_w}{\partial X} & rac{\partial Vt_w}{\partial Y} & rac{\partial Vt_w}{\partial Z} !! nd{bmatrix} $ + !> 2. Calculate \f$ \frac{\partial Y_{Output \, Equations}}{\partial u_{inputs}} = \begin{bmatrix} + !! \frac{\partial Vt_u}{\partial X} & \frac{\partial Vt_u}{\partial Y} & \frac{\partial Vt_u}{\partial Z} \\ + !! \frac{\partial Vt_v}{\partial X} & \frac{\partial Vt_v}{\partial Y} & \frac{\partial Vt_v}{\partial Z} \\ + !! \frac{\partial Vt_w}{\partial X} & \frac{\partial Vt_w}{\partial Y} & \frac{\partial Vt_w}{\partial Z} \\ + !! \end{bmatrix} \f$ !------------------------------------------------------------------------------------------------- zr = RotatePosition(3)/UF%RefHeight - tmp_du = op%VelH*op%ShrH/UF%RefLength*CosPropDir - dVhdx = tmp_du*op%SinAngleH - dVhdy = tmp_du*op%CosAngleH - dVhdz = op%VelH*(op%ShrV/UF%RefHeight*zr**(op%ShrV - 1.0_R8Ki) + op%LinShrV/UF%RefLength) + tmp_du = op%VelH * op%ShrH / UF%RefLength * CosPropDir + dVhdx = tmp_du * op%SinAngleH + dVhdy = tmp_du * op%CosAngleH + dVhdz = op%VelH * ( op%ShrV / UF%RefHeight * zr**(op%ShrV-1.0_R8Ki) + op%LinShrV/UF%RefLength) + + dVhdV = ( ( RotatePosition(3)/UF%RefHeight ) ** op%ShrV & ! power-law wind shear + + ( op%ShrH * ( RotatePosition(2) * op%CosAngleH + RotatePosition(1) * op%SinAngleH ) & ! horizontal linear shear + + op%LinShrV * ( RotatePosition(3) - UF%RefHeight ) )/UF%RefLength ) ! vertical linear shear + Vh = op%VelH * dVhdV + op%VelGust + + dVhdVShr = op%VelH * zr**op%ShrV * log(zr) + dVhdPD = op%VelH * op%ShrH / UF%RefLength * ( RotatePosition(1) * op%CosAngleH - RotatePosition(2) * op%SinAngleH ) + + tmp_du = CosPropDir*op%CosAngleH - SinPropDir*op%SinAngleH + tmp_dv = -SinPropDir*op%CosAngleH - CosPropDir*op%SinAngleH + + !> \f$ \frac{\partial Vt_u}{\partial X} = \left[\cos(PropagationDir)\cos(Delta) - \sin(PropagationDir)\sin(Delta) \right] + !! V \, \frac{H_{LinShr}}{RefWid} \, \sin(Delta) \cos(PropagationDir) \f$ + dYdu(1,1) = tmp_du*dVhdx + !> \f$ \frac{\partial Vt_v}{\partial X} = \left[-\sin(PropagationDir)\cos(Delta) - \cos(PropagationDir)\sin(Delta) \right] + !! V \, \frac{H_{LinShr}}{RefWid} \, \sin(Delta) \cos(PropagationDir) \f$ + dYdu(2,1) = tmp_dv*dVhdx + !> \f$ \frac{\partial Vt_w}{\partial X} = 0 \f$ + dYdu(3,1) = 0.0_R8Ki + + !> \f$ \frac{\partial Vt_u}{\partial Y} = \left[\cos(PropagationDir)\cos(Delta) - \sin(PropagationDir)\sin(Delta) \right] + !! V \, \frac{H_{LinShr}}{RefWid} \, \cos(Delta) \cos(PropagationDir) \f$ + dYdu(1,2) = tmp_du*dVhdy + !> \f$ \frac{\partial Vt_v}{\partial Y} = \left[-\sin(PropagationDir)\cos(Delta) - \cos(PropagationDir)\sin(Delta) \right] + !! V \, \frac{H_{LinShr}}{RefWid} \, \cos(Delta) \cos(PropagationDir) \f$ + dYdu(2,2) = tmp_dv*dVhdy + !> \f$ \frac{\partial Vt_w}{\partial Y} = 0 \f$ + dYdu(3,2) = 0.0_R8Ki + + !> \f$ \frac{\partial Vt_u}{\partial Z} = \left[\cos(PropagationDir)\cos(Delta) - \sin(PropagationDir)\sin(Delta) \right] + !! V \, \left[ \frac{V_{shr}}{Z_{ref}} \left( \frac{Z}{Z_{ref}} \right) ^ {V_{shr}-1} + \frac{V_{LinShr}}{RefWid} \right] \f$ + dYdu(1,3) = tmp_du*dVhdz + !> \f$ \frac{\partial Vt_v}{\partial Z} = \left[-\sin(PropagationDir)\cos(Delta) - \cos(PropagationDir)\sin(Delta) \right] + !! V \, \left[ \frac{V_{shr}}{Z_{ref}} \left( \frac{Z}{Z_{ref}} \right) ^ {V_{shr}-1} + \frac{V_{LinShr}}{RefWid} \right] \f$ + dYdu(2,3) = tmp_dv*dVhdz + !> \f$ \frac{\partial Vt_w}{\partial Z} = 0 \f$ + dYdu(3,3) = 0.0_R8Ki + + ! \f$ \frac{\partial Vt_u}{\partial V} = \f$ + dYdu(1,4) = tmp_du*dVhdV + ! \f$ \frac{\partial Vt_v}{\partial V} = \f$ + dYdu(2,4) = tmp_dv*dVhdV + !> \f$ \frac{\partial Vt_w}{\partial V} = 0 \f$ + dYdu(3,4) = 0.0_R8Ki + + ! \f$ \frac{\partial Vt_u}{\partial VShr} = \f$ + dYdu(1,5) = tmp_du*dVhdVShr + ! \f$ \frac{\partial Vt_v}{\partial VShr} = \f$ + dYdu(2,5) = tmp_dv*dVhdVShr + !> \f$ \frac{\partial Vt_w}{\partial VShr} = 0 \f$ + dYdu(3,5) = 0.0_R8Ki + + ! \f$ \frac{\partial Vt_u}{\partial PropDir} = \f$ + dYdu(1,6) = tmp_dv*Vh + tmp_du*dVhdPD + ! \f$ \frac{\partial Vt_v}{\partial PropDir} = \f$ + dYdu(2,6) = -tmp_du*Vh + tmp_dv*dVhdPD + !> \f$ \frac{\partial Vt_w}{\partial PropDir} = 0 \f$ + dYdu(3,6) = 0.0_R8Ki + +END SUBROUTINE IfW_UniformWind_JacobianPInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions +!! with respect to the continuous states (x). The partial derivatives dY/dx, dX/dx, dXd/dx, and dZ/dx are returned. +SUBROUTINE InflowWind_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdx, dXdx, dXddx, dZdx ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(InflowWind_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(InflowWind_OutputType), INTENT(IN ) :: y !< Output (change to inout if a mesh copy is required); + !! Output fields are not used by this routine, but type is + !! available here so that mesh parameter information (i.e., + !! connectivity) does not have to be recalculated for dYdx. + TYPE(InflowWind_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 + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dYdx(:,:) !< Partial derivatives of output functions + !! (Y) with respect to the continuous + !! states (x) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdx(:,:) !< Partial derivatives of continuous state + !! functions (X) with respect to + !! the continuous states (x) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddx(:,:) !< Partial derivatives of discrete state + !! functions (Xd) with respect to + !! the continuous states (x) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdx(:,:) !< Partial derivatives of constraint state + !! functions (Z) with respect to + !! the continuous states (x) [intent in to avoid deallocation] + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + + IF ( PRESENT( dYdx ) ) THEN + + ! Calculate the partial derivative of the output functions (Y) with respect to the continuous states (x) here: + + ! allocate and set dYdx + + END IF + + IF ( PRESENT( dXdx ) ) THEN + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the continuous states (x) here: + + ! allocate and set dXdx + + END IF + + IF ( PRESENT( dXddx ) ) THEN + + ! Calculate the partial derivative of the discrete state functions (Xd) with respect to the continuous states (x) here: + + ! allocate and set dXddx + + END IF + + IF ( PRESENT( dZdx ) ) THEN + + + ! Calculate the partial derivative of the constraint state functions (Z) with respect to the continuous states (x) here: + + ! allocate and set dZdx + + END IF + + +END SUBROUTINE InflowWind_JacobianPContState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions +!! with respect to the discrete states (xd). The partial derivatives dY/dxd, dX/dxd, dXd/dxd, and dZ/dxd are returned. +SUBROUTINE InflowWind_JacobianPDiscState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdxd, dXdxd, dXddxd, dZdxd ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(InflowWind_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(InflowWind_OutputType), INTENT(IN ) :: y !< Output (change to inout if a mesh copy is required); + !! Output fields are not used by this routine, but type is + !! available here so that mesh parameter information (i.e., + !! connectivity) does not have to be recalculated for dYdxd. + TYPE(InflowWind_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 + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dYdxd(:,:) !< Partial derivatives of output functions + !! (Y) with respect to the discrete + !! states (xd) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdxd(:,:) !< Partial derivatives of continuous state + !! functions (X) with respect to the + !! discrete states (xd) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddxd(:,:) !< Partial derivatives of discrete state + !! functions (Xd) with respect to the + !! discrete states (xd) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdxd(:,:) !< Partial derivatives of constraint state + !! functions (Z) with respect to the + !! discrete states (xd) [intent in to avoid deallocation] + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + + IF ( PRESENT( dYdxd ) ) THEN + + ! Calculate the partial derivative of the output functions (Y) with respect to the discrete states (xd) here: + + ! allocate and set dYdxd + + END IF + + IF ( PRESENT( dXdxd ) ) THEN + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the discrete states (xd) here: + + ! allocate and set dXdxd + + END IF + + IF ( PRESENT( dXddxd ) ) THEN + + ! Calculate the partial derivative of the discrete state functions (Xd) with respect to the discrete states (xd) here: + + ! allocate and set dXddxd + + END IF + + IF ( PRESENT( dZdxd ) ) THEN + + ! Calculate the partial derivative of the constraint state functions (Z) with respect to the discrete states (xd) here: + + ! allocate and set dZdxd + + END IF + + +END SUBROUTINE InflowWind_JacobianPDiscState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to compute the Jacobians of the output (Y), continuous- (X), discrete- (Xd), and constraint-state (Z) functions +!! with respect to the constraint states (z). The partial derivatives dY/dz, dX/dz, dXd/dz, and dZ/dz are returned. +SUBROUTINE InflowWind_JacobianPConstrState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, dYdz, dXdz, dXddz, dZdz ) +!.................................................................................................................................. + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(InflowWind_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(InflowWind_OutputType), INTENT(IN ) :: y !< Output (change to inout if a mesh copy is required); + !! Output fields are not used by this routine, but type is + !! available here so that mesh parameter information (i.e., + !! connectivity) does not have to be recalculated for dYdz. + TYPE(InflowWind_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 + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dYdz(:,:) !< Partial derivatives of output + !! functions (Y) with respect to the + !! constraint states (z) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXdz(:,:) !< Partial derivatives of continuous + !! state functions (X) with respect to + !! the constraint states (z) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dXddz(:,:) !< Partial derivatives of discrete state + !! functions (Xd) with respect to the + !! constraint states (z) [intent in to avoid deallocation] + REAL(R8Ki), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dZdz(:,:) !< Partial derivatives of constraint + !! state functions (Z) with respect to + !! the constraint states (z) [intent in to avoid deallocation] + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + IF ( PRESENT( dYdz ) ) THEN + + ! Calculate the partial derivative of the output functions (Y) with respect to the constraint states (z) here: + + ! allocate and set dYdz + + END IF + + IF ( PRESENT( dXdz ) ) THEN + + ! Calculate the partial derivative of the continuous state functions (X) with respect to the constraint states (z) here: + + ! allocate and set dXdz + + END IF + + IF ( PRESENT( dXddz ) ) THEN + + ! Calculate the partial derivative of the discrete state functions (Xd) with respect to the constraint states (z) here: + + ! allocate and set dXddz + + END IF + + IF ( PRESENT( dZdz ) ) THEN + + ! Calculate the partial derivative of the constraint state functions (Z) with respect to the constraint states (z) here: + + ! allocate and set dZdz + + END IF + + +END SUBROUTINE InflowWind_JacobianPConstrState +!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +!> Routine to pack the data structures representing the operating points into arrays for linearization. +SUBROUTINE InflowWind_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg, u_op, y_op, x_op, dx_op, xd_op, z_op ) + + REAL(DbKi), INTENT(IN ) :: t !< Time in seconds at operating point + TYPE(InflowWind_InputType), INTENT(IN ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + TYPE(InflowWind_ParameterType), INTENT(IN ) :: p !< Parameters + TYPE(InflowWind_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at operating point + TYPE(InflowWind_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at operating point + TYPE(InflowWind_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at operating point + TYPE(InflowWind_OtherStateType), INTENT(IN ) :: OtherState !< Other states at operating point + TYPE(InflowWind_OutputType), INTENT(IN ) :: y !< Output at operating point + TYPE(InflowWind_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 + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: u_op(:) !< values of linearized inputs + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: y_op(:) !< values of linearized outputs + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: x_op(:) !< values of linearized continuous states + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: dx_op(:) !< values of first time derivatives of linearized continuous states + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: xd_op(:) !< values of linearized discrete states + REAL(ReKi), ALLOCATABLE, OPTIONAL, INTENT(INOUT) :: z_op(:) !< values of linearized constraint states + + + INTEGER(IntKi) :: index, i, j + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'InflowWind_GetOP' + + + ! Initialize ErrStat + + ErrStat = ErrID_None + ErrMsg = '' + + IF ( PRESENT( u_op ) ) THEN + if (.not. allocated(u_op)) then + call AllocAry(u_op, size(u%PositionXYZ) + size(u%HubPosition) + 3 + NumExtendedInputs, 'u_op', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + + index = 0 + do i=1,size(u%PositionXYZ,2) + do j=1,size(u%PositionXYZ,1) + index = index + 1 !(i-1)*size(u%PositionXYZ,1)+j + u_op(index) = u%PositionXYZ(j,i) + end do + end do + + do i=1,3 + index = index + 1 + u_op(index) = u%HubPosition(i) + end do + + u_op((index+1):(index+3)) = EulerExtract(u%HubOrientation) + index = index + 3 + + call IfW_UniformWind_GetOP( p%FlowField%Uniform, t, p%FlowField%VelInterpCubic, u_op(index+1:index+2) ) + u_op(index + 3) = p%FlowField%PropagationDir + + END IF + + IF ( PRESENT( y_op ) ) THEN + if (.not. allocated(y_op)) then + call AllocAry(y_op, size(u%PositionXYZ)+p%NumOuts+3, 'y_op', ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) + if (ErrStat >= AbortErrLev) return + end if + + index = 0 + do i=1,size(u%PositionXYZ,2) + do j=1,size(u%PositionXYZ,1) + index = index + 1 !(i-1)*size(u%PositionXYZ,1)+j + y_op(index) = y%VelocityUVW(j,i) + end do + end do + + do j=1,size(y%DiskVel) + index = index + 1 + y_op(index) = y%DiskVel(j) + end do + + do i=1,p%NumOuts + y_op(i+index) = y%WriteOutput( i ) + end do + + END IF + + IF ( PRESENT( x_op ) ) THEN + + END IF + + IF ( PRESENT( dx_op ) ) THEN + + END IF + + IF ( PRESENT( xd_op ) ) THEN - dVhdV = ((RotatePosition(3)/UF%RefHeight)**op%ShrV & ! power-law wind shear - + (op%ShrH*(RotatePosition(2)*op%CosAngleH + RotatePosition(1)*op%SinAngleH) & ! horizontal linear shear - + op%LinShrV*(RotatePosition(3) - UF%RefHeight))/UF%RefLength) ! vertical linear shear - Vh = op%VelH*dVhdV + op%VelGust + END IF + + IF ( PRESENT( z_op ) ) THEN - dVhdVShr = op%VelH*zr**op%ShrV*log(zr) - dVhdPD = op%VelH*op%ShrH/UF%RefLength*(RotatePosition(1)*op%CosAngleH - RotatePosition(2)*op%SinAngleH) + END IF - tmp_du = CosPropDir*op%CosAngleH - SinPropDir*op%SinAngleH - tmp_dv = -SinPropDir*op%CosAngleH - CosPropDir*op%SinAngleH +END SUBROUTINE InflowWind_GetOP - !> $ rac{\partial Vt_u}{\partial X} = \left[ +END MODULE InflowWind diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index 2456f29d4d..8a3e7e61c7 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -750,9 +750,9 @@ PROGRAM InflowWind_Driver IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'Calling InflowWind_CalcOutput...'//NewLine) - DO ITime = 0, MAX( Settings%NumTimeSteps, 1_IntKi ) + DO ITime = 1, MAX( Settings%NumTimeSteps, 1_IntKi ) - TimeNow = Settings%TStart + Settings%DT*(ITime) + TimeNow = Settings%TStart + Settings%DT*(ITime - 1) IF ( SettingsFlags%WindGrid ) THEN diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index f7fc783744..77244e3922 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -188,6 +188,7 @@ MODULE InflowWind_Types TYPE(InflowWind_OutputType) :: y_Avg !< outputs for computing rotor-averaged values [-] TYPE(InflowWind_InputType) :: u_Hub !< inputs for computing hub values [-] TYPE(InflowWind_OutputType) :: y_Hub !< outputs for computing hub values [-] + LOGICAL :: BoxExceedWarned = .FALSE. !< Has a warning been issued for points extrapolated beyond FFWind grid [-] END TYPE InflowWind_MiscVarType ! ======================= CONTAINS @@ -4289,6 +4290,7 @@ SUBROUTINE InflowWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, Err CALL InflowWind_CopyOutput( SrcMiscData%y_Hub, DstMiscData%y_Hub, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + DstMiscData%BoxExceedWarned = SrcMiscData%BoxExceedWarned END SUBROUTINE InflowWind_CopyMisc SUBROUTINE InflowWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -4450,6 +4452,7 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + Int_BufSz = Int_BufSz + 1 ! BoxExceedWarned IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -4644,6 +4647,8 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedWarned, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_PackMisc SUBROUTINE InflowWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -4898,6 +4903,8 @@ SUBROUTINE InflowWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + OutData%BoxExceedWarned = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedWarned) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_UnPackMisc diff --git a/reg_tests/r-test b/reg_tests/r-test index 512f287927..2064017fdf 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 512f287927b50bc6aab45554319140d0fbeb742a +Subproject commit 2064017fdf692ca34c39ef6e1ce7abd1c57da964 From c82222d378b4771cae088cf44cbe253f71897255 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 5 Apr 2023 19:52:55 +0000 Subject: [PATCH 32/51] Regenerated IfW types and updated r-test --- modules/inflowwind/src/InflowWind_Types.f90 | 14 +++++++++++++- reg_tests/r-test | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index fe9225aa4c..a512ae1733 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -337,6 +337,7 @@ SUBROUTINE InflowWind_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCod DstInputFileData%MeasurementInterval = SrcInputFileData%MeasurementInterval DstInputFileData%URefLid = SrcInputFileData%URefLid DstInputFileData%LidRadialVel = SrcInputFileData%LidRadialVel + DstInputFileData%ConsiderHubMotion = SrcInputFileData%ConsiderHubMotion CALL InflowWind_IO_Copygrid3d_initinputtype( SrcInputFileData%FF, DstInputFileData%FF, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -374,6 +375,15 @@ SUBROUTINE InflowWind_DestroyInputFile( InputFileData, ErrStat, ErrMsg, DEALLOCA ENDIF IF (ALLOCATED(InputFileData%OutList)) THEN DEALLOCATE(InputFileData%OutList) +ENDIF +IF (ALLOCATED(InputFileData%FocalDistanceX)) THEN + DEALLOCATE(InputFileData%FocalDistanceX) +ENDIF +IF (ALLOCATED(InputFileData%FocalDistanceY)) THEN + DEALLOCATE(InputFileData%FocalDistanceY) +ENDIF +IF (ALLOCATED(InputFileData%FocalDistanceZ)) THEN + DEALLOCATE(InputFileData%FocalDistanceZ) ENDIF CALL InflowWind_IO_Destroygrid3d_initinputtype( InputFileData%FF, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -731,7 +741,9 @@ SUBROUTINE InflowWind_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat Re_Xferred = Re_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%LidRadialVel, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 - CALL IfW_FFWind_PackInitInput( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF + IntKiBuf(Int_Xferred) = InData%ConsiderHubMotion + Int_Xferred = Int_Xferred + 1 + CALL InflowWind_IO_Packgrid3d_initinputtype( Re_Buf, Db_Buf, Int_Buf, InData%FF, ErrStat2, ErrMsg2, OnlySize ) ! FF CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN diff --git a/reg_tests/r-test b/reg_tests/r-test index 2064017fdf..d5425d6f55 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 2064017fdf692ca34c39ef6e1ce7abd1c57da964 +Subproject commit d5425d6f55e1ec1108c3a5b0cdd2e5db34d57029 From 5075f9ab625a21bfde8352c135f121f75c9fd9d5 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 5 Apr 2023 20:17:20 +0000 Subject: [PATCH 33/51] Removed new InflowwindRegressionCase.py code --- reg_tests/executeInflowwindRegressionCase.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/reg_tests/executeInflowwindRegressionCase.py b/reg_tests/executeInflowwindRegressionCase.py index e1dab6f6da..d06b802e12 100644 --- a/reg_tests/executeInflowwindRegressionCase.py +++ b/reg_tests/executeInflowwindRegressionCase.py @@ -112,22 +112,6 @@ testData, testInfo, _ = pass_fail.readFASTOut(localOutFile) baselineData, baselineInfo, _ = pass_fail.readFASTOut(baselineOutFile) -# Append acceleration data if present -localOutFileAcc = os.path.join(testBuildDirectory, "Points.Acceleration.dat") -baselineOutFileAcc = os.path.join(targetOutputDirectory, "Points.Acceleration.dat") -if os.path.exists(baselineOutFileAcc): - rtl.validateFileOrExit(localOutFileAcc) - rtl.validateFileOrExit(baselineOutFileAcc) - testDataAcc, testInfoAcc, _ = pass_fail.readFASTOut(localOutFile) - testInfo['attribute_names'] += [n+'a' for n in testInfoAcc['attribute_names'][4:]] - testInfo['attribute_units'] += [u+'a' for u in testInfoAcc['attribute_units'][4:]] - testData = np.hstack([testData, testDataAcc[:,4:]]) - - baselineDataAcc, baselineInfoAcc, _ = pass_fail.readFASTOut(baselineOutFile) - baselineInfo['attribute_names'] += [n+'a' for n in testInfoAcc['attribute_names'][4:]] - baselineInfo['attribute_units'] += [u+'a' for u in testInfoAcc['attribute_units'][4:]] - baselineData = np.hstack([baselineData, baselineDataAcc[:,4:]]) - passing_channels = pass_fail.passing_channels(testData.T, baselineData.T, rtol, atol) passing_channels = passing_channels.T From 7ac862bf5f36e45cc5ac3d0f1d83d53ae5ebcc40 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 5 Apr 2023 21:10:58 +0000 Subject: [PATCH 34/51] Moved IfW_FlowField into MiscVars --- glue-codes/fast-farm/src/FASTWrapper.f90 | 8 +- modules/inflowwind/src/IfW_FlowField.f90 | 88 ++++---- modules/inflowwind/src/IfW_FlowField.txt | 1 + .../inflowwind/src/IfW_FlowField_Types.f90 | 7 + modules/inflowwind/src/InflowWind.f90 | 88 ++++---- modules/inflowwind/src/InflowWind.txt | 5 +- modules/inflowwind/src/InflowWind_Driver.f90 | 10 +- modules/inflowwind/src/InflowWind_Subs.f90 | 32 +-- modules/inflowwind/src/InflowWind_Types.f90 | 191 +++++++++--------- .../inflowwind/tests/test_uniform_wind.F90 | 12 +- 10 files changed, 216 insertions(+), 226 deletions(-) diff --git a/glue-codes/fast-farm/src/FASTWrapper.f90 b/glue-codes/fast-farm/src/FASTWrapper.f90 index 903666cb48..717e4e6516 100644 --- a/glue-codes/fast-farm/src/FASTWrapper.f90 +++ b/glue-codes/fast-farm/src/FASTWrapper.f90 @@ -184,7 +184,7 @@ SUBROUTINE FWrap_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init return end if - call move_alloc(m%Turbine%IfW%p%FlowField%Grid4D%Vel, u%Vdist_High) + call move_alloc(m%Turbine%IfW%m%FlowField%Grid4D%Vel, u%Vdist_High) !................. @@ -556,7 +556,7 @@ SUBROUTINE FWrap_CalcOutput(p, u, y, m, ErrStat, ErrMsg) ErrMsg = '' ! put this back! - call move_alloc(m%Turbine%IfW%p%FlowField%Grid4D%Vel, u%Vdist_High) + call move_alloc(m%Turbine%IfW%m%FlowField%Grid4D%Vel, u%Vdist_High) ! Turbine-dependent commands to the super controller: @@ -712,8 +712,8 @@ SUBROUTINE FWrap_SetInputs(u, m, t) REAL(DbKi), INTENT(IN ) :: t !< current simulation time ! set the 4d-wind-inflow input array (a bit of a hack [simplification] so that we don't have large amounts of data copied in multiple data structures): - call move_alloc(u%Vdist_High, m%Turbine%IfW%p%FlowField%Grid4D%Vel) - m%Turbine%IfW%p%FlowField%Grid4D%TimeStart = t + call move_alloc(u%Vdist_High, m%Turbine%IfW%m%FlowField%Grid4D%Vel) + m%Turbine%IfW%m%FlowField%Grid4D%TimeStart = t ! do something with the inputs from the super-controller: if ( m%Turbine%p_FAST%UseSC ) then diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index bef1ad04c3..7c5209d044 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -42,7 +42,7 @@ module IfW_FlowField !! Accelerations are only calculated if the AccelUVW array is allocated. subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, AccelUVW, ErrStat, ErrMsg) - type(FlowFieldType), intent(in) :: FF !< FlowField data structure + type(FlowFieldType), intent(inout) :: FF !< FlowField data structure integer(IntKi), intent(in) :: IStart !< Start index for returning velocities for external field real(DbKi), intent(in) :: Time !< Time to evaluate velocities/accelerations real(ReKi), intent(in) :: PositionXYZ(:, :) !< Array of positions to evaluate velocites/accelerations @@ -170,31 +170,44 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A ! Grid3D Flow Field !------------------------------------------------------------------------- - if (OutputAccel) then + ! Loop through points + do i = 1, NumPoints - ! Loop through points - do i = 1, NumPoints + ! If height < zero, set velocity/acceleration to zero, continue + if (Position(3, i) <= 0.0_ReKi) then + VelocityUVW(:, i) = 0.0_ReKi + AccelUVW(:, i) = 0.0_ReKi + cycle + end if - ! If height < zero, set velocity/acceleration to zero, continue - if (Position(3, i) <= 0.0_ReKi) then - VelocityUVW(:, i) = 0.0_ReKi - AccelUVW(:, i) = 0.0_ReKi - cycle - end if + ! Is this point allowed beyond the bounds of the wind box? + GridExceedAllow = FF%Grid3D%BoxExceedAllowF .and. (i >= FF%Grid3D%BoxExceedAllowIdx) - ! Is this point allowed beyond the bounds of the wind box? - GridExceedAllow = FF%Grid3D%BoxExceedAllowF .and. (i >= FF%Grid3D%BoxExceedAllowIdx) - - ! Calculate grid cells for interpolation, returns velocity and acceleration - ! components at corners of grid cell containing time and position. Also - ! returns interpolation values Xi. - call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), .true., GridExceedAllow, & - VelCell, AccCell, Xi, Is3D, GridExtrap, TmpErrStat, TmpErrMsg) - if (TmpErrStat >= AbortErrLev) then - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - return - end if + ! Calculate grid cells for interpolation, returns velocity and acceleration + ! components at corners of grid cell containing time and position. Also + ! returns interpolation values Xi. + call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), OutputAccel, GridExceedAllow, & + VelCell, AccCell, Xi, Is3D, GridExtrap, TmpErrStat, TmpErrMsg) + if (TmpErrStat >= AbortErrLev) then + call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) + return + end if + + ! Output warning if extrapolation occured + if (GridExtrap .and. (.not. FF%Grid3D%BoxExceedWarned)) then + call WrScr("WARNING from InflowWind:") + call WrScr("------------------------") + call WrScr(" Grid point extrapolated beyond bounds of full-field wind grid [position=("// & + TRIM(Num2LStr(PositionXYZ(1, i)))//", "//TRIM(Num2LStr(PositionXYZ(2, i)))//", "// & + TRIM(Num2LStr(PositionXYZ(3, i)))//") in wind-file coordinates, T="//trim(Num2LStr(Time))//"]."//NewLine// & + "This only occurs for free vortex wake points or LidarSim measurement locations. "// & + "Use a larger full-field wind grid if the simulation yields undesirable results. Further warnings are suppressed.") + call WrScr("------------------------") + FF%Grid3D%BoxExceedWarned = .true. + end if + ! Calculate velocity and acceleration + if (OutputAccel) then if (FF%VelInterpCubic) then ! Cubic velocity and cubic acceleration call Grid3DField_GetVelAccCubic(FF%Grid3D%DTime, VelCell, AccCell, Xi, Is3D, & @@ -205,30 +218,7 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A call Grid3DField_GetVelAccCubic(FF%Grid3D%DTime, VelCell, AccCell, Xi, Is3D, & Accel=AccelUVW(:, i)) end if - - end do - else - - ! Loop through points - do i = 1, NumPoints - - ! If height < zero, set velocity to zero, continue - if (Position(3, i) <= 0.0_ReKi) then - VelocityUVW(:, i) = 0.0_ReKi - cycle - end if - - ! is this point allowed beyond the bounds of the wind box? - GridExceedAllow = FF%Grid3D%BoxExceedAllowF .and. (i >= FF%Grid3D%BoxExceedAllowIdx) - - ! Calculate grid cells for interpolation - call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), FF%VelInterpCubic, GridExceedAllow, & - VelCell, AccCell, Xi, Is3D, GridExtrap, TmpErrStat, TmpErrMsg) - if (TmpErrStat >= AbortErrLev) then - call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) - return - end if - + else if (FF%VelInterpCubic) then ! Cubic velocity call Grid3DField_GetVelAccCubic(FF%Grid3D%DTime, VelCell, AccCell, Xi, Is3D, & @@ -237,9 +227,9 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A ! Linear velocity VelocityUVW(:, i) = Grid3DField_GetVelLinear(VelCell, Xi, Is3D) end if + end if - end do - end if + end do ! Add mean wind speed after interpolation if flag is set if (FF%Grid3D%AddMeanAfterInterp) then @@ -750,7 +740,7 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & real(ReKi), intent(out) :: AccCell(8, 3) !< Acceleration components at corners of grid cell real(ReKi), intent(out) :: Xi(3) !< isoparametric coord of position in cell (y,z,t) [-1, +1] logical, intent(out) :: Is3D !< flag indicating if interpolation is 3D or 2D - logical, intent(out) :: Extrapolated !< Extrapolation outside grid is allowed and point lies outside grid + logical, intent(inout) :: Extrapolated !< Extrapolation outside grid is allowed and point lies outside grid integer(IntKi), intent(out) :: ErrStat !< error status character(*), intent(out) :: ErrMsg !< error message diff --git a/modules/inflowwind/src/IfW_FlowField.txt b/modules/inflowwind/src/IfW_FlowField.txt index 2641f2eb1a..773ec7f861 100644 --- a/modules/inflowwind/src/IfW_FlowField.txt +++ b/modules/inflowwind/src/IfW_FlowField.txt @@ -90,6 +90,7 @@ typedef ^ ^ ReKi VLinShr typedef ^ ^ ReKi HLinShr - 0 - "Horizontal linear wind shear coefficient (used for horizontal wind profile type only)" - typedef ^ ^ LOGICAL BoxExceedAllowF - .FALSE. - "Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim)" - typedef ^ ^ IntKi BoxExceedAllowIdx - -1 - "Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim)" - +typedef ^ ^ LOGICAL BoxExceedWarned - .FALSE. - "Has a warning been issued for points extrapolated beyond FFWind grid" - #---------------------------------------------------------------------------------------------------------------------------------- diff --git a/modules/inflowwind/src/IfW_FlowField_Types.f90 b/modules/inflowwind/src/IfW_FlowField_Types.f90 index 6b17858306..55212a9400 100644 --- a/modules/inflowwind/src/IfW_FlowField_Types.f90 +++ b/modules/inflowwind/src/IfW_FlowField_Types.f90 @@ -124,6 +124,7 @@ MODULE IfW_FlowField_Types REAL(ReKi) :: HLinShr = 0 !< Horizontal linear wind shear coefficient (used for horizontal wind profile type only) [-] LOGICAL :: BoxExceedAllowF = .FALSE. !< Flag to allow Extrapolation winds outside box starting at this index (for OLAF wakes and LidarSim) [-] INTEGER(IntKi) :: BoxExceedAllowIdx = -1 !< Extrapolate winds outside box starting at this index (for OLAF wakes and LidarSim) [-] + LOGICAL :: BoxExceedWarned = .FALSE. !< Has a warning been issued for points extrapolated beyond FFWind grid [-] END TYPE Grid3DFieldType ! ======================= ! ========= Grid4DFieldType ======= @@ -1622,6 +1623,7 @@ SUBROUTINE IfW_FlowField_CopyGrid3DFieldType( SrcGrid3DFieldTypeData, DstGrid3DF DstGrid3DFieldTypeData%HLinShr = SrcGrid3DFieldTypeData%HLinShr DstGrid3DFieldTypeData%BoxExceedAllowF = SrcGrid3DFieldTypeData%BoxExceedAllowF DstGrid3DFieldTypeData%BoxExceedAllowIdx = SrcGrid3DFieldTypeData%BoxExceedAllowIdx + DstGrid3DFieldTypeData%BoxExceedWarned = SrcGrid3DFieldTypeData%BoxExceedWarned END SUBROUTINE IfW_FlowField_CopyGrid3DFieldType SUBROUTINE IfW_FlowField_DestroyGrid3DFieldType( Grid3DFieldTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -1759,6 +1761,7 @@ SUBROUTINE IfW_FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata Re_BufSz = Re_BufSz + 1 ! HLinShr Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowF Int_BufSz = Int_BufSz + 1 ! BoxExceedAllowIdx + Int_BufSz = Int_BufSz + 1 ! BoxExceedWarned IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2004,6 +2007,8 @@ SUBROUTINE IfW_FlowField_PackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%BoxExceedAllowIdx Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedWarned, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE IfW_FlowField_PackGrid3DFieldType SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -2272,6 +2277,8 @@ SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outd Int_Xferred = Int_Xferred + 1 OutData%BoxExceedAllowIdx = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 + OutData%BoxExceedWarned = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedWarned) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE IfW_FlowField_UnPackGrid3DFieldType SUBROUTINE IfW_FlowField_CopyGrid4DFieldType( SrcGrid4DFieldTypeData, DstGrid4DFieldTypeData, CtrlCode, ErrStat, ErrMsg ) diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index 0b4a2a9c32..bb0a0f6bef 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -300,8 +300,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons Steady_InitInput%RefHt = InputFileData%Steady_RefHt Steady_InitInput%PLExp = InputFileData%Steady_PLexp - p%FlowField%FieldType = Uniform_FieldType - call IfW_SteadyWind_Init(Steady_InitInput, SumFileUnit, p%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) + m%FlowField%FieldType = Uniform_FieldType + call IfW_SteadyWind_Init(Steady_InitInput, SumFileUnit, m%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -317,8 +317,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons Uniform_InitInput%UseInputFile = InitInp%WindType2UseInputFile Uniform_InitInput%PassedFileData = InitInp%WindType2Data - p%FlowField%FieldType = Uniform_FieldType - call IfW_UniformWind_Init(Uniform_InitInput, SumFileUnit, p%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) + m%FlowField%FieldType = Uniform_FieldType + call IfW_UniformWind_Init(Uniform_InitInput, SumFileUnit, m%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -329,8 +329,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons TurbSim_InitInput%WindFileName = InputFileData%TSFF_FileName - p%FlowField%FieldType = Grid3D_FieldType - call IfW_TurbSim_Init(TurbSim_InitInput, SumFileUnit, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + m%FlowField%FieldType = Grid3D_FieldType + call IfW_TurbSim_Init(TurbSim_InitInput, SumFileUnit, m%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -352,8 +352,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons Bladed_InitInput%TowerFileExist = InputFileData%BladedFF_TowerFile Bladed_InitInput%NativeBladedFmt = .false. - p%FlowField%FieldType = Grid3D_FieldType - call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + m%FlowField%FieldType = Grid3D_FieldType + call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, m%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -368,8 +368,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons Bladed_InitInput%TowerFileExist = .false. Bladed_InitInput%NativeBladedFmt = .true. - p%FlowField%FieldType = Grid3D_FieldType - call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + m%FlowField%FieldType = Grid3D_FieldType + call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, m%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -401,8 +401,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons HAWC_InitInput%G3D%Z0 = InputFileData%FF%Z0 HAWC_InitInput%G3D%XOffset = InputFileData%FF%XOffset - p%FlowField%FieldType = Grid3D_FieldType - call IfW_HAWC_Init(HAWC_InitInput, SumFileUnit, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + m%FlowField%FieldType = Grid3D_FieldType + call IfW_HAWC_Init(HAWC_InitInput, SumFileUnit, m%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -411,8 +411,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons case (User_WindNumber) - p%FlowField%FieldType = User_FieldType - call IfW_User_Init(User_InitInput, SumFileUnit, p%FlowField%User, FileDat, TmpErrStat, TmpErrMsg) + m%FlowField%FieldType = User_FieldType + call IfW_User_Init(User_InitInput, SumFileUnit, m%FlowField%User, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -421,8 +421,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons case (FDext_WindNumber) - p%FlowField%FieldType = Grid4D_FieldType - call IfW_Grid4D_Init(InitInp%FDext, p%FlowField%Grid4D, FileDat, TmpErrStat, TmpErrMsg) + m%FlowField%FieldType = Grid4D_FieldType + call IfW_Grid4D_Init(InitInp%FDext, m%FlowField%Grid4D, FileDat, TmpErrStat, TmpErrMsg) if (ErrStat >= AbortErrLev) then call Cleanup() return @@ -430,7 +430,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons ! case (Point_WindNumber) - ! p%FlowField%FieldType = Point_FieldType + ! m%FlowField%FieldType = Point_FieldType case default call SetErrStat(ErrID_Fatal, ' Undefined wind type.', ErrStat, ErrMsg, RoutineName) @@ -442,50 +442,50 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons !---------------------------------------------------------------------------- ! Reset flag indicating that acceleration field is valid - p%FlowField%AccFieldValid = .false. + m%FlowField%AccFieldValid = .false. ! Copy flag for enabling cubic velocity interpolation - p%FlowField%VelInterpCubic = InputFileData%VelInterpCubic + m%FlowField%VelInterpCubic = InputFileData%VelInterpCubic ! If cubic velocity interpolation requested and linearization is performed, ! display message that cubic interpolation is incompatible with linearization ! and will be disabled - if (p%FlowField%VelInterpCubic .and. InitInp%Linearize) then + if (m%FlowField%VelInterpCubic .and. InitInp%Linearize) then call WrScr("InflowWind: Cubic interpolation of wind velocity is disabled for linearization") - p%FlowField%VelInterpCubic = .false. + m%FlowField%VelInterpCubic = .false. end if ! Set box exceed flag and index - p%FlowField%Grid3D%BoxExceedAllowF = InitInp%BoxExceedAllowF - p%FlowField%Grid3D%BoxExceedAllowIdx = huge(1_IntKi) + m%FlowField%Grid3D%BoxExceedAllowF = InitInp%BoxExceedAllowF + m%FlowField%Grid3D%BoxExceedAllowIdx = huge(1_IntKi) if (InitInp%BoxExceedAllowF .and. (InitInp%BoxExceedAllowIdx <= InitInp%NumWindPoints)) then - p%FlowField%Grid3D%BoxExceedAllowIdx = InitInp%BoxExceedAllowIdx + m%FlowField%Grid3D%BoxExceedAllowIdx = InitInp%BoxExceedAllowIdx end if ! Select based on field type - select case (p%FlowField%FieldType) + select case (m%FlowField%FieldType) case (Uniform_FieldType) - if (InitInp%OutputAccel .or. p%FlowField%VelInterpCubic) then - call IfW_UniformField_CalcAccel(p%FlowField%Uniform, TmpErrStat, TmpErrMsg) + if (InitInp%OutputAccel .or. m%FlowField%VelInterpCubic) then + call IfW_UniformField_CalcAccel(m%FlowField%Uniform, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return - p%FlowField%AccFieldValid = .true. + m%FlowField%AccFieldValid = .true. end if case (Grid3D_FieldType) ! Calculate acceleration - if (InitInp%OutputAccel .or. p%FlowField%VelInterpCubic) then - call IfW_Grid3DField_CalcAccel(p%FlowField%Grid3D, TmpErrStat, TmpErrMsg) + if (InitInp%OutputAccel .or. m%FlowField%VelInterpCubic) then + call IfW_Grid3DField_CalcAccel(m%FlowField%Grid3D, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return - p%FlowField%AccFieldValid = .true. + m%FlowField%AccFieldValid = .true. end if ! Calculate field average if box is allowed to be exceeded - if (p%FlowField%Grid3D%BoxExceedAllowF .and. p%FlowField%Grid3D%BoxExceedAllowIdx > 0) then - call IfW_Grid3DField_CalcVelAvgProfile(p%FlowField%Grid3D, p%FlowField%AccFieldValid, TmpErrStat, TmpErrMsg) + if (m%FlowField%Grid3D%BoxExceedAllowF .and. m%FlowField%Grid3D%BoxExceedAllowIdx > 0) then + call IfW_Grid3DField_CalcVelAvgProfile(m%FlowField%Grid3D, m%FlowField%AccFieldValid, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return end if @@ -493,13 +493,13 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons case default if (InitInp%OutputAccel) then call SetErrStat(ErrID_Fatal, "Acceleration not implemented for field type "// & - num2LStr(p%FlowField%FieldType), ErrStat, ErrMsg, RoutineName) + num2LStr(m%FlowField%FieldType), ErrStat, ErrMsg, RoutineName) return end if - if (p%FlowField%VelInterpCubic) then + if (m%FlowField%VelInterpCubic) then call WrScr(' Cubic velocity interpolation not implemented for WindType '// & num2LStr(InputFileData%WindType)) - p%FlowField%VelInterpCubic = .false. + m%FlowField%VelInterpCubic = .false. end if end select @@ -551,8 +551,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons ! If field is uniform and there is any nonzero upflow, return error ! Math needs work before this can be implemented - if (p%FlowField%FieldType == Uniform_FieldType) then - if (any(p%FlowField%Uniform%AngleV /= 0.0_ReKi)) then + if (m%FlowField%FieldType == Uniform_FieldType) then + if (any(m%FlowField%Uniform%AngleV /= 0.0_ReKi)) then call SetErrStat(ErrID_Fatal, 'Upflow in uniform wind files must be 0 for linearization analysis in InflowWind.', ErrStat, ErrMsg, RoutineName) call Cleanup() return @@ -995,10 +995,10 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt n = SIZE(u%PositionXYZ,2) ! these are the positions used in the module coupling do i=1,n - ! note that p%FlowField%RotToWind(1,1) = cos(p%PropagationDir) and p%FlowField%RotToWind(2,1) = sin(p%PropagationDir), which are the + ! note that m%FlowField%RotToWind(1,1) = cos(p%PropagationDir) and m%FlowField%RotToWind(2,1) = sin(p%PropagationDir), which are the ! values we need to compute the jacobian. !!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, u%PositionXYZ(:,i), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) + call IfW_UniformWind_JacobianPInput( m%FlowField%Uniform, t, u%PositionXYZ(:,i), m%FlowField%RotToWind(1,1), m%FlowField%RotToWind(2,1), local_dYdu ) i_end = 3*i i_start= i_end - 2 @@ -1021,7 +1021,7 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt do i=1,IfW_NumPtsAvg m%u_Avg%PositionXYZ(:,i) = matmul(u%HubOrientation,p%PositionAvg(:,i)) + u%HubPosition !!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, m%u_Avg%PositionXYZ(:,i), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) + call IfW_UniformWind_JacobianPInput( m%FlowField%Uniform, t, m%u_Avg%PositionXYZ(:,i), m%FlowField%RotToWind(1,1), m%FlowField%RotToWind(2,1), local_dYdu ) ! y%DiskAvg has the same index as u%HubPosition ! Also note that partial_(m%u_Avg%PositionXYZ) / partial_(u%HubPosition) is identity, so we can skip that part of the chain rule for these derivatives: @@ -1043,7 +1043,7 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt if (node > 0) then !!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, p%WindViXYZ(:,node), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) + call IfW_UniformWind_JacobianPInput( m%FlowField%Uniform, t, p%WindViXYZ(:,node), m%FlowField%RotToWind(1,1), m%FlowField%RotToWind(2,1), local_dYdu ) else local_dYdu = 0.0_R8Ki comp = 1 @@ -1468,8 +1468,8 @@ SUBROUTINE InflowWind_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMs u_op((index+1):(index+3)) = EulerExtract(u%HubOrientation) index = index + 3 - call IfW_UniformWind_GetOP( p%FlowField%Uniform, t, p%FlowField%VelInterpCubic, u_op(index+1:index+2) ) - u_op(index + 3) = p%FlowField%PropagationDir + call IfW_UniformWind_GetOP( m%FlowField%Uniform, t, m%FlowField%VelInterpCubic, u_op(index+1:index+2) ) + u_op(index + 3) = m%FlowField%PropagationDir END IF diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 85c0372e98..b0e8d5d3ff 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -116,8 +116,7 @@ typedef ^ InitOutputType LOGICAL IsLoad # ..... Parameters ................................................................................................................ # Define parameters here: # Time step for integration of continuous states (if a fixed-step integrator is used) and update of discrete states: -typedef ^ ParameterType FlowFieldType FlowField - - - "Parameters from Full-Field" - -typedef ^ ^ CHARACTER(1024) RootFileName - - - "Root of the InflowWind input filename" - +typedef ^ ParameterType CHARACTER(1024) RootFileName - - - "Root of the InflowWind input filename" - typedef ^ ^ IntKi WindType - 0 - "Type of wind -- set to Undef_Wind initially" - typedef ^ ^ DbKi DT - - - "Time step for cont. state integration & disc. state update" seconds typedef ^ ^ ReKi WindViXYZprime :: - - "List of XYZ coordinates for velocity measurements, translated to the wind coordinate system (prime coordinates). This equals MATMUL( RotToWind, ParamData%WindViXYZ )" meters @@ -163,8 +162,8 @@ typedef ^ OtherStateType ReKi DummyOtherS typedef ^ MiscVarType ReKi AllOuts : - - "An array holding the value of all of the calculated (not only selected) output channels" "see OutListParameters.xlsx spreadsheet" typedef ^ ^ ReKi WindViUVW :: - - "List of UVW velocities for wind velocity measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ" meters/second typedef ^ ^ ReKi WindAiUVW :: - - "List of UVW accelerations for wind acceleration measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ" m/s^2 +typedef ^ ^ FlowFieldType FlowField - - - "Parameters from Full-Field" - typedef ^ ^ InflowWind_InputType u_Avg - - - "inputs for computing rotor-averaged values" - typedef ^ ^ InflowWind_OutputType y_Avg - - - "outputs for computing rotor-averaged values" - typedef ^ ^ InflowWind_InputType u_Hub - - - "inputs for computing hub values" - typedef ^ ^ InflowWind_OutputType y_Hub - - - "outputs for computing hub values" - -typedef ^ ^ LOGICAL BoxExceedWarned - .FALSE. - "Has a warning been issued for points extrapolated beyond FFWind grid" - diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index 8a3e7e61c7..23c8b57cf6 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -449,7 +449,7 @@ PROGRAM InflowWind_Driver ! Convert InflowWind file to HAWC format IF (SettingsFlags%WrHAWC) THEN - CALL IfW_WriteHAWC( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) + CALL IfW_WriteHAWC( InflowWind_MiscVars%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN @@ -466,7 +466,7 @@ PROGRAM InflowWind_Driver ! Convert InflowWind file to Native Bladed format IF (SettingsFlags%WrBladed) THEN - CALL IfW_WriteBladed( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) + CALL IfW_WriteBladed( InflowWind_MiscVars%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN @@ -481,7 +481,7 @@ PROGRAM InflowWind_Driver END IF IF (SettingsFlags%WrVTK) THEN - CALL IfW_WriteVTK( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) + CALL IfW_WriteVTK( InflowWind_MiscVars%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN @@ -498,7 +498,7 @@ PROGRAM InflowWind_Driver IF (SettingsFlags%WrUniform) THEN - CALL IfW_WriteUniform( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) + CALL IfW_WriteUniform( InflowWind_MiscVars%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN @@ -711,7 +711,7 @@ PROGRAM InflowWind_Driver ! Report the rotation of the coordinates. IF ( IfWDriver_Verbose >= 10_IntKi .and. InflowWind_p%NumOuts > 0 ) THEN CALL WrScr(NewLine//NewLine//' Rotation of coordinates to prime (wind file) coordinates by rotating '// & - TRIM(Num2LStr(R2D*InflowWind_p%FlowField%PropagationDir))// & + TRIM(Num2LStr(R2D*InflowWind_MiscVars%FlowField%PropagationDir))// & ' degrees (meteorological wind direction change) ...'//NewLine) if (InflowWind_p%NWindVel > 0_IntKi) then CALL WrScr(' ------ WindViXYZ --------- ----- WindViXYZprime -----') diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index 578b23dbbb..ba41f691b9 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -938,10 +938,10 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM p%WindType = InputFileData%WindType ! Convert the PropagationDir to radians and store this. For simplicity, we will shift it to be between -pi and pi - p%FlowField%PropagationDir = D2R * InputFileData%PropagationDir - CALL MPi2Pi( p%FlowField%PropagationDir ) ! Shift if necessary so that the value is between -pi and pi + m%FlowField%PropagationDir = D2R * InputFileData%PropagationDir + CALL MPi2Pi( m%FlowField%PropagationDir ) ! Shift if necessary so that the value is between -pi and pi - p%FlowField%VFlowAngle = D2R * InputFileData%VFlowAngle + m%FlowField%VFlowAngle = D2R * InputFileData%VFlowAngle ! Copy over the list of wind coordinates. Move the arrays to the new one. p%NWindVel = InputFileData%NWindVel @@ -1078,15 +1078,15 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM ! Create the rotation matrices -- rotate from XYZ to X'Y'Z' (wind aligned along X) coordinates ! Included in this rotation is the wind upflow (inclination) angle (rotation about Y axis) - p%FlowField%RotToWind(1,:) = [ COS(-p%FlowField%VFlowAngle) * COS(-p%FlowField%PropagationDir), & - COS(-p%FlowField%VFlowAngle) * SIN(-p%FlowField%PropagationDir), & - -SIN(-p%FlowField%VFlowAngle) ] - p%FlowField%RotToWind(2,:) = [ -SIN(-p%FlowField%PropagationDir), & - COS(-p%FlowField%PropagationDir), & + m%FlowField%RotToWind(1,:) = [ COS(-m%FlowField%VFlowAngle) * COS(-m%FlowField%PropagationDir), & + COS(-m%FlowField%VFlowAngle) * SIN(-m%FlowField%PropagationDir), & + -SIN(-m%FlowField%VFlowAngle) ] + m%FlowField%RotToWind(2,:) = [ -SIN(-m%FlowField%PropagationDir), & + COS(-m%FlowField%PropagationDir), & 0.0_ReKi ] - p%FlowField%RotToWind(3,:) = [ SIN(-p%FlowField%VFlowAngle) * COS(-p%FlowField%PropagationDir), & - SIN(-p%FlowField%VFlowAngle) * SIN(-p%FlowField%PropagationDir), & - COS(-p%FlowField%VFlowAngle) ] + m%FlowField%RotToWind(3,:) = [ SIN(-m%FlowField%VFlowAngle) * COS(-m%FlowField%PropagationDir), & + SIN(-m%FlowField%VFlowAngle) * SIN(-m%FlowField%PropagationDir), & + COS(-m%FlowField%VFlowAngle) ] ! Create the rotation matrices -- rotate from X'Y'Z' (wind aligned along X) to global XYZ coordinates: this is the same as a ! rotation about the (positive) upflow angle multiplied by a rotation about the (positive) wind direction: @@ -1094,7 +1094,7 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM ! loal wind = R( -p%VFlowAngle) * R (-p%PropagationDir) [global wind] ! = R^T(p%VFlowAngle) * R^T(p%PropagationDir) [global wind] ! = (R(p%PropagationDir) * R(p%VFlowAngle))^T [global wind] - p%FlowField%RotFromWind = TRANSPOSE(p%FlowField%RotToWind) + m%FlowField%RotFromWind = TRANSPOSE(m%FlowField%RotToWind) ! Create the array used for holding the rotated list of WindViXYZ coordinates in the wind reference frame, and populate it CALL AllocAry( p%WindViXYZprime, 3, p%NWindVel, 'Array for WindViXYZ coordinates in the wind reference frame', & @@ -1107,10 +1107,10 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM p%WindViXYZprime = 0.0_ReKi ! set the output points. Note rotation is about the hub height at [0 0 H]. See InflowWind_SetParameters for details. DO I = 1,p%NWindVel - p%WindViXYZprime(:,I) = MATMUL( p%FlowField%RotToWind, (p%WindViXYZ(:,I) - p%RefPosition )) + p%RefPosition + p%WindViXYZprime(:,I) = MATMUL( m%FlowField%RotToWind, (p%WindViXYZ(:,I) - p%RefPosition )) + p%RefPosition ENDDO - p%FlowField%RotateWindBox = .not. (EqualRealNos (p%FlowField%PropagationDir, 0.0_ReKi) .AND. EqualRealNos (p%FlowField%VFlowAngle, 0.0_ReKi)) + m%FlowField%RotateWindBox = .not. (EqualRealNos (m%FlowField%PropagationDir, 0.0_ReKi) .AND. EqualRealNos (m%FlowField%VFlowAngle, 0.0_ReKi)) END SUBROUTINE InflowWind_SetParameters @@ -1568,14 +1568,14 @@ SUBROUTINE CalculateOutput( Time, InputData, p, x, xd, z, OtherStates, y, m, Fil ErrMsg = "" ! Get velocities and accelerations for the given positions - CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, InputData%PositionXYZ, & + CALL IfW_FlowField_GetVelAcc(m%FlowField, 0, Time, InputData%PositionXYZ, & y%VelocityUVW, y%AccelUVW, TmpErrStat, TmpErrMsg) CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev) RETURN ! Get velocities and accelerations for OutList variables, no error check IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, p%WindViXYZ, & + CALL IfW_FlowField_GetVelAcc(m%FlowField, 0, Time, p%WindViXYZ, & m%WindViUVW, m%WindAiUVW, TmpErrStat, TmpErrMsg) ENDIF diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index a512ae1733..cb3681ed6a 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -133,7 +133,6 @@ MODULE InflowWind_Types ! ======================= ! ========= InflowWind_ParameterType ======= TYPE, PUBLIC :: InflowWind_ParameterType - TYPE(FlowFieldType) :: FlowField !< Parameters from Full-Field [-] CHARACTER(1024) :: RootFileName !< Root of the InflowWind input filename [-] INTEGER(IntKi) :: WindType = 0 !< Type of wind -- set to Undef_Wind initially [-] REAL(DbKi) :: DT !< Time step for cont. state integration & disc. state update [seconds] @@ -192,11 +191,11 @@ MODULE InflowWind_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AllOuts !< An array holding the value of all of the calculated (not only selected) output channels [see OutListParameters.xlsx spreadsheet] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViUVW !< List of UVW velocities for wind velocity measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ [meters/second] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindAiUVW !< List of UVW accelerations for wind acceleration measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ [m/s^2] + TYPE(FlowFieldType) :: FlowField !< Parameters from Full-Field [-] TYPE(InflowWind_InputType) :: u_Avg !< inputs for computing rotor-averaged values [-] TYPE(InflowWind_OutputType) :: y_Avg !< outputs for computing rotor-averaged values [-] TYPE(InflowWind_InputType) :: u_Hub !< inputs for computing hub values [-] TYPE(InflowWind_OutputType) :: y_Hub !< outputs for computing hub values [-] - LOGICAL :: BoxExceedWarned = .FALSE. !< Has a warning been issued for points extrapolated beyond FFWind grid [-] END TYPE InflowWind_MiscVarType ! ======================= CONTAINS @@ -2362,9 +2361,6 @@ SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ! ErrStat = ErrID_None ErrMsg = "" - CALL IfW_FlowField_Copyflowfieldtype( SrcParamData%FlowField, DstParamData%FlowField, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN DstParamData%RootFileName = SrcParamData%RootFileName DstParamData%WindType = SrcParamData%WindType DstParamData%DT = SrcParamData%DT @@ -2470,8 +2466,6 @@ SUBROUTINE InflowWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointe DEALLOCATEpointers_local = .true. END IF - CALL IfW_FlowField_Destroyflowfieldtype( ParamData%FlowField, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ALLOCATED(ParamData%WindViXYZprime)) THEN DEALLOCATE(ParamData%WindViXYZprime) ENDIF @@ -2530,24 +2524,6 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! FlowField: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, .TRUE. ) ! FlowField - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! FlowField - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! FlowField - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! FlowField - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF Int_BufSz = Int_BufSz + 1*LEN(InData%RootFileName) ! RootFileName Int_BufSz = Int_BufSz + 1 ! WindType Db_BufSz = Db_BufSz + 1 ! DT @@ -2573,6 +2549,7 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + 1 ! OutParam allocated yes/no IF ( ALLOCATED(InData%OutParam) ) THEN Int_BufSz = Int_BufSz + 2*1 ! OutParam upper/lower bounds for each dimension + ! Allocate buffers for subtypes, if any (we'll get sizes from these) DO i1 = LBOUND(InData%OutParam,1), UBOUND(InData%OutParam,1) Int_BufSz = Int_BufSz + 3 ! OutParam: size of buffers for each call to pack subtype CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%OutParam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OutParam @@ -2642,34 +2619,6 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Db_Xferred = 1 Int_Xferred = 1 - CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, OnlySize ) ! FlowField - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF DO I = 1, LEN(InData%RootFileName) IntKiBuf(Int_Xferred) = ICHAR(InData%RootFileName(I:I), IntKi) Int_Xferred = Int_Xferred + 1 @@ -2867,46 +2816,6 @@ SUBROUTINE InflowWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_FlowField_Unpackflowfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%FlowField, ErrStat2, ErrMsg2 ) ! FlowField - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) DO I = 1, LEN(OutData%RootFileName) OutData%RootFileName(I:I) = CHAR(IntKiBuf(Int_Xferred)) Int_Xferred = Int_Xferred + 1 @@ -4475,6 +4384,9 @@ SUBROUTINE InflowWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, Err END IF DstMiscData%WindAiUVW = SrcMiscData%WindAiUVW ENDIF + CALL IfW_FlowField_Copyflowfieldtype( SrcMiscData%FlowField, DstMiscData%FlowField, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN CALL InflowWind_CopyInput( SrcMiscData%u_Avg, DstMiscData%u_Avg, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -4487,7 +4399,6 @@ SUBROUTINE InflowWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, Err CALL InflowWind_CopyOutput( SrcMiscData%y_Hub, DstMiscData%y_Hub, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN - DstMiscData%BoxExceedWarned = SrcMiscData%BoxExceedWarned END SUBROUTINE InflowWind_CopyMisc SUBROUTINE InflowWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -4520,6 +4431,8 @@ SUBROUTINE InflowWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers IF (ALLOCATED(MiscData%WindAiUVW)) THEN DEALLOCATE(MiscData%WindAiUVW) ENDIF + CALL IfW_FlowField_Destroyflowfieldtype( MiscData%FlowField, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL InflowWind_DestroyInput( MiscData%u_Avg, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL InflowWind_DestroyOutput( MiscData%y_Avg, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) @@ -4581,6 +4494,23 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = Re_BufSz + SIZE(InData%WindAiUVW) ! WindAiUVW END IF ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! FlowField: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, .TRUE. ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FlowField + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FlowField + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FlowField + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF Int_BufSz = Int_BufSz + 3 ! u_Avg: size of buffers for each call to pack subtype CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Avg, ErrStat2, ErrMsg2, .TRUE. ) ! u_Avg CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -4649,7 +4579,6 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF - Int_BufSz = Int_BufSz + 1 ! BoxExceedWarned IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -4732,6 +4661,34 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err END DO END DO END IF + CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, OnlySize ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Avg, ErrStat2, ErrMsg2, OnlySize ) ! u_Avg CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4844,8 +4801,6 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF - IntKiBuf(Int_Xferred) = TRANSFER(InData%BoxExceedWarned, IntKiBuf(1)) - Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_PackMisc SUBROUTINE InflowWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -4940,6 +4895,46 @@ SUBROUTINE InflowWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, END DO END DO END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackflowfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%FlowField, ErrStat2, ErrMsg2 ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN @@ -5100,8 +5095,6 @@ SUBROUTINE InflowWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) - OutData%BoxExceedWarned = TRANSFER(IntKiBuf(Int_Xferred), OutData%BoxExceedWarned) - Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_UnPackMisc diff --git a/modules/inflowwind/tests/test_uniform_wind.F90 b/modules/inflowwind/tests/test_uniform_wind.F90 index 13421e5da4..b20e86b139 100644 --- a/modules/inflowwind/tests/test_uniform_wind.F90 +++ b/modules/inflowwind/tests/test_uniform_wind.F90 @@ -90,13 +90,13 @@ subroutine test_uniform_wind_direct_data() ! Results @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') - @assertEqual(0.0, p%FlowField%Uniform%Time(1)) - @assertEqual(0.1, p%FlowField%Uniform%Time(2)) - @assertEqual(999.9, p%FlowField%Uniform%Time(3)) + @assertEqual(0.0, m%FlowField%Uniform%Time(1)) + @assertEqual(0.1, m%FlowField%Uniform%Time(2)) + @assertEqual(999.9, m%FlowField%Uniform%Time(3)) - @assertEqual(12.0, p%FlowField%Uniform%VelH(1)) - @assertEqual(12.0, p%FlowField%Uniform%VelH(2)) - @assertEqual(12.0, p%FlowField%Uniform%VelH(3)) + @assertEqual(12.0, m%FlowField%Uniform%VelH(1)) + @assertEqual(12.0, m%FlowField%Uniform%VelH(2)) + @assertEqual(12.0, m%FlowField%Uniform%VelH(3)) end subroutine From d48ce424865fa89172c3cc2185b13ac05b504c8f Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 5 Apr 2023 21:16:29 +0000 Subject: [PATCH 35/51] Removed inflowwind_driver change --- modules/inflowwind/src/InflowWind_Driver.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index 23c8b57cf6..49ec583998 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -750,9 +750,9 @@ PROGRAM InflowWind_Driver IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'Calling InflowWind_CalcOutput...'//NewLine) - DO ITime = 1, MAX( Settings%NumTimeSteps, 1_IntKi ) + DO ITime = 0, MAX( Settings%NumTimeSteps, 1_IntKi ) - TimeNow = Settings%TStart + Settings%DT*(ITime - 1) + TimeNow = Settings%TStart + Settings%DT*(ITime) IF ( SettingsFlags%WindGrid ) THEN From 10b5f51c32c2f30aa2b64562bb22c13f9cef3d89 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 5 Apr 2023 22:16:16 +0000 Subject: [PATCH 36/51] Added InflowWind acceleration outputs --- docs/OtherSupporting/OutListParameters.xlsx | Bin 599387 -> 600181 bytes modules/inflowwind/src/InflowWind.txt | 1 + modules/inflowwind/src/InflowWind_Subs.f90 | 327 ++++++++++++-------- modules/inflowwind/src/InflowWind_Types.f90 | 7 + 4 files changed, 206 insertions(+), 129 deletions(-) diff --git a/docs/OtherSupporting/OutListParameters.xlsx b/docs/OtherSupporting/OutListParameters.xlsx index 98006d67b04b2a41782474b8e6c938fe1065df5f..03146fa76a39a1c3b5d44021ccf8eed463d019e7 100644 GIT binary patch delta 99759 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

PwE}4$WpaDJo1-zl${=htzPP<&+;V=! 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 L(@8uQ-0lAWmliJ| delta 98729 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 diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index b0e8d5d3ff..d4b117f986 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -130,6 +130,7 @@ typedef ^ ^ IntKi NumOuts typedef ^ ^ OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - typedef ^ ^ IntKi OutParamLinIndx {:}{:} - - "Index into WriteOutput for WindViXYZ in linearization analysis" - typedef ^ ^ lidar_ParameterType lidar - - - "Lidar parameter data" - +typedef ^ ^ LOGICAL OutputAccel - .FALSE. - "Flag to output wind acceleration" - # ..... Inputs .................................................................................................................... diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index ba41f691b9..dcbc68b26a 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -32,7 +32,7 @@ MODULE InflowWind_Subs ! using the parameters listed in the "OutListParameters.xlsx" Excel file. Any changes to these ! lines should be modified in the Matlab script and/or Excel worksheet as necessary. ! =================================================================================================== -! This code was generated by "Write_ChckOutLst.m" at 29-Jul-2022 19:48:38. +! This code was generated by "Write_ChckOutLst.m" at 05-Apr-2023. ! Indices for computing output channels: @@ -42,104 +42,141 @@ MODULE InflowWind_Subs ! Time: - INTEGER(IntKi), PARAMETER :: Time = 0 + INTEGER(IntKi), PARAMETER :: Time = 0 ! Wind Motions: - INTEGER(IntKi), PARAMETER :: Wind1VelX = 1 - INTEGER(IntKi), PARAMETER :: Wind1VelY = 2 - INTEGER(IntKi), PARAMETER :: Wind1VelZ = 3 - INTEGER(IntKi), PARAMETER :: Wind2VelX = 4 - INTEGER(IntKi), PARAMETER :: Wind2VelY = 5 - INTEGER(IntKi), PARAMETER :: Wind2VelZ = 6 - INTEGER(IntKi), PARAMETER :: Wind3VelX = 7 - INTEGER(IntKi), PARAMETER :: Wind3VelY = 8 - INTEGER(IntKi), PARAMETER :: Wind3VelZ = 9 - INTEGER(IntKi), PARAMETER :: Wind4VelX = 10 - INTEGER(IntKi), PARAMETER :: Wind4VelY = 11 - INTEGER(IntKi), PARAMETER :: Wind4VelZ = 12 - INTEGER(IntKi), PARAMETER :: Wind5VelX = 13 - INTEGER(IntKi), PARAMETER :: Wind5VelY = 14 - INTEGER(IntKi), PARAMETER :: Wind5VelZ = 15 - INTEGER(IntKi), PARAMETER :: Wind6VelX = 16 - INTEGER(IntKi), PARAMETER :: Wind6VelY = 17 - INTEGER(IntKi), PARAMETER :: Wind6VelZ = 18 - INTEGER(IntKi), PARAMETER :: Wind7VelX = 19 - INTEGER(IntKi), PARAMETER :: Wind7VelY = 20 - INTEGER(IntKi), PARAMETER :: Wind7VelZ = 21 - INTEGER(IntKi), PARAMETER :: Wind8VelX = 22 - INTEGER(IntKi), PARAMETER :: Wind8VelY = 23 - INTEGER(IntKi), PARAMETER :: Wind8VelZ = 24 - INTEGER(IntKi), PARAMETER :: Wind9VelX = 25 - INTEGER(IntKi), PARAMETER :: Wind9VelY = 26 - INTEGER(IntKi), PARAMETER :: Wind9VelZ = 27 - INTEGER(IntKi), PARAMETER :: WindHubVelX = 28 - INTEGER(IntKi), PARAMETER :: WindHubVelY = 29 - INTEGER(IntKi), PARAMETER :: WindHubVelZ = 30 - INTEGER(IntKi), PARAMETER :: WindDiskVelX = 31 - INTEGER(IntKi), PARAMETER :: WindDiskVelY = 32 - INTEGER(IntKi), PARAMETER :: WindDiskVelZ = 33 + INTEGER(IntKi), PARAMETER :: Wind1VelX = 1 + INTEGER(IntKi), PARAMETER :: Wind1VelY = 2 + INTEGER(IntKi), PARAMETER :: Wind1VelZ = 3 + INTEGER(IntKi), PARAMETER :: Wind2VelX = 4 + INTEGER(IntKi), PARAMETER :: Wind2VelY = 5 + INTEGER(IntKi), PARAMETER :: Wind2VelZ = 6 + INTEGER(IntKi), PARAMETER :: Wind3VelX = 7 + INTEGER(IntKi), PARAMETER :: Wind3VelY = 8 + INTEGER(IntKi), PARAMETER :: Wind3VelZ = 9 + INTEGER(IntKi), PARAMETER :: Wind4VelX = 10 + INTEGER(IntKi), PARAMETER :: Wind4VelY = 11 + INTEGER(IntKi), PARAMETER :: Wind4VelZ = 12 + INTEGER(IntKi), PARAMETER :: Wind5VelX = 13 + INTEGER(IntKi), PARAMETER :: Wind5VelY = 14 + INTEGER(IntKi), PARAMETER :: Wind5VelZ = 15 + INTEGER(IntKi), PARAMETER :: Wind6VelX = 16 + INTEGER(IntKi), PARAMETER :: Wind6VelY = 17 + INTEGER(IntKi), PARAMETER :: Wind6VelZ = 18 + INTEGER(IntKi), PARAMETER :: Wind7VelX = 19 + INTEGER(IntKi), PARAMETER :: Wind7VelY = 20 + INTEGER(IntKi), PARAMETER :: Wind7VelZ = 21 + INTEGER(IntKi), PARAMETER :: Wind8VelX = 22 + INTEGER(IntKi), PARAMETER :: Wind8VelY = 23 + INTEGER(IntKi), PARAMETER :: Wind8VelZ = 24 + INTEGER(IntKi), PARAMETER :: Wind9VelX = 25 + INTEGER(IntKi), PARAMETER :: Wind9VelY = 26 + INTEGER(IntKi), PARAMETER :: Wind9VelZ = 27 + INTEGER(IntKi), PARAMETER :: WindHubVelX = 28 + INTEGER(IntKi), PARAMETER :: WindHubVelY = 29 + INTEGER(IntKi), PARAMETER :: WindHubVelZ = 30 + INTEGER(IntKi), PARAMETER :: WindDiskVelX = 31 + INTEGER(IntKi), PARAMETER :: WindDiskVelY = 32 + INTEGER(IntKi), PARAMETER :: WindDiskVelZ = 33 + + + ! Wind Accelerations: + + INTEGER(IntKi), PARAMETER :: Wind1AccX = 34 + INTEGER(IntKi), PARAMETER :: Wind1AccY = 35 + INTEGER(IntKi), PARAMETER :: Wind1AccZ = 36 + INTEGER(IntKi), PARAMETER :: Wind2AccX = 37 + INTEGER(IntKi), PARAMETER :: Wind2AccY = 38 + INTEGER(IntKi), PARAMETER :: Wind2AccZ = 39 + INTEGER(IntKi), PARAMETER :: Wind3AccX = 40 + INTEGER(IntKi), PARAMETER :: Wind3AccY = 41 + INTEGER(IntKi), PARAMETER :: Wind3AccZ = 42 + INTEGER(IntKi), PARAMETER :: Wind4AccX = 43 + INTEGER(IntKi), PARAMETER :: Wind4AccY = 44 + INTEGER(IntKi), PARAMETER :: Wind4AccZ = 45 + INTEGER(IntKi), PARAMETER :: Wind5AccX = 46 + INTEGER(IntKi), PARAMETER :: Wind5AccY = 47 + INTEGER(IntKi), PARAMETER :: Wind5AccZ = 48 + INTEGER(IntKi), PARAMETER :: Wind6AccX = 49 + INTEGER(IntKi), PARAMETER :: Wind6AccY = 50 + INTEGER(IntKi), PARAMETER :: Wind6AccZ = 51 + INTEGER(IntKi), PARAMETER :: Wind7AccX = 52 + INTEGER(IntKi), PARAMETER :: Wind7AccY = 53 + INTEGER(IntKi), PARAMETER :: Wind7AccZ = 54 + INTEGER(IntKi), PARAMETER :: Wind8AccX = 55 + INTEGER(IntKi), PARAMETER :: Wind8AccY = 56 + INTEGER(IntKi), PARAMETER :: Wind8AccZ = 57 + INTEGER(IntKi), PARAMETER :: Wind9AccX = 58 + INTEGER(IntKi), PARAMETER :: Wind9AccY = 59 + INTEGER(IntKi), PARAMETER :: Wind9AccZ = 60 ! Wind Magnitude and Direction: - INTEGER(IntKi), PARAMETER :: Wind1VelXY = 34 - INTEGER(IntKi), PARAMETER :: Wind2VelXY = 35 - INTEGER(IntKi), PARAMETER :: Wind3VelXY = 36 - INTEGER(IntKi), PARAMETER :: Wind4VelXY = 37 - INTEGER(IntKi), PARAMETER :: Wind5VelXY = 38 - INTEGER(IntKi), PARAMETER :: Wind6VelXY = 39 - INTEGER(IntKi), PARAMETER :: Wind7VelXY = 40 - INTEGER(IntKi), PARAMETER :: Wind8VelXY = 41 - INTEGER(IntKi), PARAMETER :: Wind9VelXY = 42 - INTEGER(IntKi), PARAMETER :: WindHubVelXY = 43 - INTEGER(IntKi), PARAMETER :: WindDiskVelXY = 44 - INTEGER(IntKi), PARAMETER :: Wind1VelMag = 45 - INTEGER(IntKi), PARAMETER :: Wind2VelMag = 46 - INTEGER(IntKi), PARAMETER :: Wind3VelMag = 47 - INTEGER(IntKi), PARAMETER :: Wind4VelMag = 48 - INTEGER(IntKi), PARAMETER :: Wind5VelMag = 49 - INTEGER(IntKi), PARAMETER :: Wind6VelMag = 50 - INTEGER(IntKi), PARAMETER :: Wind7VelMag = 51 - INTEGER(IntKi), PARAMETER :: Wind8VelMag = 52 - INTEGER(IntKi), PARAMETER :: Wind9VelMag = 53 - INTEGER(IntKi), PARAMETER :: WindHubVelMag = 54 - INTEGER(IntKi), PARAMETER :: WindDiskVelMag = 55 - INTEGER(IntKi), PARAMETER :: Wind1AngXY = 56 - INTEGER(IntKi), PARAMETER :: Wind2AngXY = 57 - INTEGER(IntKi), PARAMETER :: Wind3AngXY = 58 - INTEGER(IntKi), PARAMETER :: Wind4AngXY = 59 - INTEGER(IntKi), PARAMETER :: Wind5AngXY = 60 - INTEGER(IntKi), PARAMETER :: Wind6AngXY = 61 - INTEGER(IntKi), PARAMETER :: Wind7AngXY = 62 - INTEGER(IntKi), PARAMETER :: Wind8AngXY = 63 - INTEGER(IntKi), PARAMETER :: Wind9AngXY = 64 - INTEGER(IntKi), PARAMETER :: WindHubAngXY = 65 - INTEGER(IntKi), PARAMETER :: WindDiskAngXY = 66 + INTEGER(IntKi), PARAMETER :: Wind1VelXY = 61 + INTEGER(IntKi), PARAMETER :: Wind2VelXY = 62 + INTEGER(IntKi), PARAMETER :: Wind3VelXY = 63 + INTEGER(IntKi), PARAMETER :: Wind4VelXY = 64 + INTEGER(IntKi), PARAMETER :: Wind5VelXY = 65 + INTEGER(IntKi), PARAMETER :: Wind6VelXY = 66 + INTEGER(IntKi), PARAMETER :: Wind7VelXY = 67 + INTEGER(IntKi), PARAMETER :: Wind8VelXY = 68 + INTEGER(IntKi), PARAMETER :: Wind9VelXY = 69 + INTEGER(IntKi), PARAMETER :: WindHubVelXY = 70 + INTEGER(IntKi), PARAMETER :: WindDiskVelXY = 71 + INTEGER(IntKi), PARAMETER :: Wind1VelMag = 72 + INTEGER(IntKi), PARAMETER :: Wind2VelMag = 73 + INTEGER(IntKi), PARAMETER :: Wind3VelMag = 74 + INTEGER(IntKi), PARAMETER :: Wind4VelMag = 75 + INTEGER(IntKi), PARAMETER :: Wind5VelMag = 76 + INTEGER(IntKi), PARAMETER :: Wind6VelMag = 77 + INTEGER(IntKi), PARAMETER :: Wind7VelMag = 78 + INTEGER(IntKi), PARAMETER :: Wind8VelMag = 79 + INTEGER(IntKi), PARAMETER :: Wind9VelMag = 80 + INTEGER(IntKi), PARAMETER :: WindHubVelMag = 81 + INTEGER(IntKi), PARAMETER :: WindDiskVelMag = 82 + INTEGER(IntKi), PARAMETER :: Wind1AngXY = 83 + INTEGER(IntKi), PARAMETER :: Wind2AngXY = 84 + INTEGER(IntKi), PARAMETER :: Wind3AngXY = 85 + INTEGER(IntKi), PARAMETER :: Wind4AngXY = 86 + INTEGER(IntKi), PARAMETER :: Wind5AngXY = 87 + INTEGER(IntKi), PARAMETER :: Wind6AngXY = 88 + INTEGER(IntKi), PARAMETER :: Wind7AngXY = 89 + INTEGER(IntKi), PARAMETER :: Wind8AngXY = 90 + INTEGER(IntKi), PARAMETER :: Wind9AngXY = 91 + INTEGER(IntKi), PARAMETER :: WindHubAngXY = 92 + INTEGER(IntKi), PARAMETER :: WindDiskAngXY = 93 ! Wind Sensor Measurements: - INTEGER(IntKi), PARAMETER :: WindMeas1 = 67 - INTEGER(IntKi), PARAMETER :: WindMeas2 = 68 - INTEGER(IntKi), PARAMETER :: WindMeas3 = 69 - INTEGER(IntKi), PARAMETER :: WindMeas4 = 70 - INTEGER(IntKi), PARAMETER :: WindMeas5 = 71 + INTEGER(IntKi), PARAMETER :: WindMeas1 = 94 + INTEGER(IntKi), PARAMETER :: WindMeas2 = 95 + INTEGER(IntKi), PARAMETER :: WindMeas3 = 96 + INTEGER(IntKi), PARAMETER :: WindMeas4 = 97 + INTEGER(IntKi), PARAMETER :: WindMeas5 = 98 ! The maximum number of output channels which can be output by the code. - INTEGER(IntKi), PARAMETER :: MaxOutPts = 71 + INTEGER(IntKi), PARAMETER :: MaxOutPts = 98 !End of code generated by Matlab script Write_ChckOutLst ! =================================================================================================== INTEGER(IntKi), PARAMETER :: WindMeas(5) = (/ WindMeas1, WindMeas2, WindMeas3, WindMeas4, WindMeas5 /) ! Array of output constants + INTEGER(IntKi), PARAMETER :: WindVelX(9) = (/ Wind1VelX, Wind2VelX, Wind3VelX, Wind4VelX, Wind5VelX, Wind6VelX, Wind7VelX, Wind8VelX, Wind9VelX /) ! Array of output constants INTEGER(IntKi), PARAMETER :: WindVelY(9) = (/ Wind1VelY, Wind2VelY, Wind3VelY, Wind4VelY, Wind5VelY, Wind6VelY, Wind7VelY, Wind8VelY, Wind9VelY /) ! Array of output constants INTEGER(IntKi), PARAMETER :: WindVelZ(9) = (/ Wind1VelZ, Wind2VelZ, Wind3VelZ, Wind4VelZ, Wind5VelZ, Wind6VelZ, Wind7VelZ, Wind8VelZ, Wind9VelZ /) ! Array of output constants + INTEGER(IntKi), PARAMETER :: WindAccX(9) = (/ Wind1AccX, Wind2AccX, Wind3AccX, Wind4AccX, Wind5AccX, Wind6AccX, Wind7AccX, Wind8AccX, Wind9AccX /) ! Array of output constants + INTEGER(IntKi), PARAMETER :: WindAccY(9) = (/ Wind1AccY, Wind2AccY, Wind3AccY, Wind4AccY, Wind5AccY, Wind6AccY, Wind7AccY, Wind8AccY, Wind9AccY /) ! Array of output constants + INTEGER(IntKi), PARAMETER :: WindAccZ(9) = (/ Wind1AccZ, Wind2AccZ, Wind3AccZ, Wind4AccZ, Wind5AccZ, Wind6AccZ, Wind7AccZ, Wind8AccZ, Wind9AccZ /) ! Array of output constants + + INTEGER(IntKi), PARAMETER :: WindVelXY( 9) = (/ Wind1VelXY, Wind2VelXY, Wind3VelXY, Wind4VelXY, Wind5VelXY, Wind6VelXY, Wind7VelXY, Wind8VelXY, Wind9VelXY /) ! Array of output constants INTEGER(IntKi), PARAMETER :: WindVelMag(9) = (/ Wind1VelMag, Wind2VelMag, Wind3VelMag, Wind4VelMag, Wind5VelMag, Wind6VelMag, Wind7VelMag, Wind8VelMag, Wind9VelMag/) ! Array of output constants INTEGER(IntKi), PARAMETER :: WindAngXY( 9) = (/ Wind1AngXY, Wind2AngXY, Wind3AngXY, Wind4AngXY, Wind5AngXY, Wind6AngXY, Wind7AngXY, Wind8AngXY, Wind9AngXY /) ! Array of output constants @@ -1002,7 +1039,7 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM p%PositionAvg(3,i) = 0.0_ReKi end do - + p%OutputAccel = InitInp%OutputAccel ! Set the OutList CALL SetOutParam( InputFileData%OutList, p, TmpErrStat, TmpErrmsg ) @@ -1135,11 +1172,11 @@ END SUBROUTINE InflowWind_SetParameters SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) !.................................................................................................................................. - IMPLICIT NONE + IMPLICIT NONE ! Passed variables - CHARACTER(ChanLen), INTENT(IN) :: OutList(:) !< The list out user-requested outputs + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) !< The list of user-requested outputs TYPE(InflowWind_ParameterType), INTENT(INOUT) :: p !< The module parameters INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred @@ -1148,7 +1185,6 @@ SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) INTEGER :: ErrStat2 ! temporary (local) error status INTEGER :: I ! Generic loop-counting index -! INTEGER :: J ! Generic loop-counting index INTEGER :: INDX ! Index for valid arrays LOGICAL :: CheckOutListAgain ! Flag used to determine if output parameter starting with "M" is valid (or the negative of another parameter) @@ -1156,55 +1192,71 @@ SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) CHARACTER(*), PARAMETER :: RoutineName = "SetOutParam" - CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(71) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically - "WIND1ANGXY ","WIND1VELMAG ","WIND1VELX ","WIND1VELXY ","WIND1VELY ", & - "WIND1VELZ ","WIND2ANGXY ","WIND2VELMAG ","WIND2VELX ","WIND2VELXY ", & - "WIND2VELY ","WIND2VELZ ","WIND3ANGXY ","WIND3VELMAG ","WIND3VELX ", & - "WIND3VELXY ","WIND3VELY ","WIND3VELZ ","WIND4ANGXY ","WIND4VELMAG ", & - "WIND4VELX ","WIND4VELXY ","WIND4VELY ","WIND4VELZ ","WIND5ANGXY ", & + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(98) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + "WIND1ACCX ","WIND1ACCY ","WIND1ACCZ ","WIND1ANGXY ","WIND1VELMAG ", & + "WIND1VELX ","WIND1VELXY ","WIND1VELY ","WIND1VELZ ","WIND2ACCX ", & + "WIND2ACCY ","WIND2ACCZ ","WIND2ANGXY ","WIND2VELMAG ","WIND2VELX ", & + "WIND2VELXY ","WIND2VELY ","WIND2VELZ ","WIND3ACCX ","WIND3ACCY ", & + "WIND3ACCZ ","WIND3ANGXY ","WIND3VELMAG ","WIND3VELX ","WIND3VELXY ", & + "WIND3VELY ","WIND3VELZ ","WIND4ACCX ","WIND4ACCY ","WIND4ACCZ ", & + "WIND4ANGXY ","WIND4VELMAG ","WIND4VELX ","WIND4VELXY ","WIND4VELY ", & + "WIND4VELZ ","WIND5ACCX ","WIND5ACCY ","WIND5ACCZ ","WIND5ANGXY ", & "WIND5VELMAG ","WIND5VELX ","WIND5VELXY ","WIND5VELY ","WIND5VELZ ", & - "WIND6ANGXY ","WIND6VELMAG ","WIND6VELX ","WIND6VELXY ","WIND6VELY ", & - "WIND6VELZ ","WIND7ANGXY ","WIND7VELMAG ","WIND7VELX ","WIND7VELXY ", & - "WIND7VELY ","WIND7VELZ ","WIND8ANGXY ","WIND8VELMAG ","WIND8VELX ", & - "WIND8VELXY ","WIND8VELY ","WIND8VELZ ","WIND9ANGXY ","WIND9VELMAG ", & - "WIND9VELX ","WIND9VELXY ","WIND9VELY ","WIND9VELZ ","WINDDISKANGXY ", & - "WINDDISKVELMAG","WINDDISKVELX ","WINDDISKVELXY ","WINDDISKVELY ","WINDDISKVELZ ", & - "WINDHUBANGXY ","WINDHUBVELMAG ","WINDHUBVELX ","WINDHUBVELXY ","WINDHUBVELY ", & - "WINDHUBVELZ ","WINDMEAS1 ","WINDMEAS2 ","WINDMEAS3 ","WINDMEAS4 ", & - "WINDMEAS5 "/) - INTEGER(IntKi), PARAMETER :: ParamIndxAry(71) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) - Wind1AngXY , Wind1VelMag , Wind1VelX , Wind1VelXY , Wind1VelY , & - Wind1VelZ , Wind2AngXY , Wind2VelMag , Wind2VelX , Wind2VelXY , & - Wind2VelY , Wind2VelZ , Wind3AngXY , Wind3VelMag , Wind3VelX , & - Wind3VelXY , Wind3VelY , Wind3VelZ , Wind4AngXY , Wind4VelMag , & - Wind4VelX , Wind4VelXY , Wind4VelY , Wind4VelZ , Wind5AngXY , & + "WIND6ACCX ","WIND6ACCY ","WIND6ACCZ ","WIND6ANGXY ","WIND6VELMAG ", & + "WIND6VELX ","WIND6VELXY ","WIND6VELY ","WIND6VELZ ","WIND7ACCX ", & + "WIND7ACCY ","WIND7ACCZ ","WIND7ANGXY ","WIND7VELMAG ","WIND7VELX ", & + "WIND7VELXY ","WIND7VELY ","WIND7VELZ ","WIND8ACCX ","WIND8ACCY ", & + "WIND8ACCZ ","WIND8ANGXY ","WIND8VELMAG ","WIND8VELX ","WIND8VELXY ", & + "WIND8VELY ","WIND8VELZ ","WIND9ACCX ","WIND9ACCY ","WIND9ACCZ ", & + "WIND9ANGXY ","WIND9VELMAG ","WIND9VELX ","WIND9VELXY ","WIND9VELY ", & + "WIND9VELZ ","WINDDISKANGXY ","WINDDISKVELMAG","WINDDISKVELX ","WINDDISKVELXY ", & + "WINDDISKVELY ","WINDDISKVELZ ","WINDHUBANGXY ","WINDHUBVELMAG ","WINDHUBVELX ", & + "WINDHUBVELXY ","WINDHUBVELY ","WINDHUBVELZ ","WINDMEAS1 ","WINDMEAS2 ", & + "WINDMEAS3 ","WINDMEAS4 ","WINDMEAS5 "/) + + INTEGER(IntKi), PARAMETER :: ParamIndxAry(98) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + Wind1AccX , Wind1AccY , Wind1AccZ , Wind1AngXY , Wind1VelMag , & + Wind1VelX , Wind1VelXY , Wind1VelY , Wind1VelZ , Wind2AccX , & + Wind2AccY , Wind2AccZ , Wind2AngXY , Wind2VelMag , Wind2VelX , & + Wind2VelXY , Wind2VelY , Wind2VelZ , Wind3AccX , Wind3AccY , & + Wind3AccZ , Wind3AngXY , Wind3VelMag , Wind3VelX , Wind3VelXY , & + Wind3VelY , Wind3VelZ , Wind4AccX , Wind4AccY , Wind4AccZ , & + Wind4AngXY , Wind4VelMag , Wind4VelX , Wind4VelXY , Wind4VelY , & + Wind4VelZ , Wind5AccX , Wind5AccY , Wind5AccZ , Wind5AngXY , & Wind5VelMag , Wind5VelX , Wind5VelXY , Wind5VelY , Wind5VelZ , & - Wind6AngXY , Wind6VelMag , Wind6VelX , Wind6VelXY , Wind6VelY , & - Wind6VelZ , Wind7AngXY , Wind7VelMag , Wind7VelX , Wind7VelXY , & - Wind7VelY , Wind7VelZ , Wind8AngXY , Wind8VelMag , Wind8VelX , & - Wind8VelXY , Wind8VelY , Wind8VelZ , Wind9AngXY , Wind9VelMag , & - Wind9VelX , Wind9VelXY , Wind9VelY , Wind9VelZ , WindDiskAngXY , & - WindDiskVelMag , WindDiskVelX , WindDiskVelXY , WindDiskVelY , WindDiskVelZ , & - WindHubAngXY , WindHubVelMag , WindHubVelX , WindHubVelXY , WindHubVelY , & - WindHubVelZ , WindMeas1 , WindMeas2 , WindMeas3 , WindMeas4 , & - WindMeas5 /) - CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(71) = (/ character(ChanLen) :: & ! This lists the units corresponding to the allowed parameters - "(deg)","(m/s)","(m/s)","(m/s)","(m/s)", & - "(m/s)","(deg)","(m/s)","(m/s)","(m/s)", & - "(m/s)","(m/s)","(deg)","(m/s)","(m/s)", & + Wind6AccX , Wind6AccY , Wind6AccZ , Wind6AngXY , Wind6VelMag , & + Wind6VelX , Wind6VelXY , Wind6VelY , Wind6VelZ , Wind7AccX , & + Wind7AccY , Wind7AccZ , Wind7AngXY , Wind7VelMag , Wind7VelX , & + Wind7VelXY , Wind7VelY , Wind7VelZ , Wind8AccX , Wind8AccY , & + Wind8AccZ , Wind8AngXY , Wind8VelMag , Wind8VelX , Wind8VelXY , & + Wind8VelY , Wind8VelZ , Wind9AccX , Wind9AccY , Wind9AccZ , & + Wind9AngXY , Wind9VelMag , Wind9VelX , Wind9VelXY , Wind9VelY , & + Wind9VelZ , WindDiskAngXY , WindDiskVelMag , WindDiskVelX , WindDiskVelXY , & + WindDiskVelY , WindDiskVelZ , WindHubAngXY , WindHubVelMag , WindHubVelX , & + WindHubVelXY , WindHubVelY , WindHubVelZ , WindMeas1 , WindMeas2 , & + WindMeas3 , WindMeas4 , WindMeas5 /) + + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(98) = (/ character(ChanLen) :: & ! This lists the units corresponding to the allowed parameters "(m/s)","(m/s)","(m/s)","(deg)","(m/s)", & - "(m/s)","(m/s)","(m/s)","(m/s)","(deg)", & "(m/s)","(m/s)","(m/s)","(m/s)","(m/s)", & - "(deg)","(m/s)","(m/s)","(m/s)","(m/s)", & - "(m/s)","(deg)","(m/s)","(m/s)","(m/s)", & "(m/s)","(m/s)","(deg)","(m/s)","(m/s)", & - "(m/s)","(m/s)","(m/s)","(deg)","(m/s)", & + "(m/s)","(m/s)","(m/s)","(m/s)","(m/s)", & + "(m/s)","(deg)","(m/s)","(m/s)","(m/s)", & + "(m/s)","(m/s)","(m/s)","(m/s)","(m/s)", & + "(deg)","(m/s)","(m/s)","(m/s)","(m/s)", & "(m/s)","(m/s)","(m/s)","(m/s)","(deg)", & "(m/s)","(m/s)","(m/s)","(m/s)","(m/s)", & + "(m/s)","(m/s)","(m/s)","(deg)","(m/s)", & + "(m/s)","(m/s)","(m/s)","(m/s)","(m/s)", & + "(m/s)","(m/s)","(deg)","(m/s)","(m/s)", & + "(m/s)","(m/s)","(m/s)","(m/s)","(m/s)", & + "(m/s)","(deg)","(m/s)","(m/s)","(m/s)", & + "(m/s)","(m/s)","(m/s)","(m/s)","(m/s)", & "(deg)","(m/s)","(m/s)","(m/s)","(m/s)", & + "(m/s)","(deg)","(m/s)","(m/s)","(m/s)", & + "(m/s)","(m/s)","(deg)","(m/s)","(m/s)", & "(m/s)","(m/s)","(m/s)","(m/s)","(m/s)", & - "(m/s)"/) - + "(m/s)","(m/s)","(m/s)"/) ! Initialize values ErrStat = ErrID_None @@ -1221,21 +1273,30 @@ SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) InvalidOutput( WindVelX( I) ) = .TRUE. InvalidOutput( WindVelY( I) ) = .TRUE. InvalidOutput( WindVelZ( I) ) = .TRUE. + InvalidOutput( WindAccX( I) ) = .TRUE. + InvalidOutput( WindAccY( I) ) = .TRUE. + InvalidOutput( WindAccZ( I) ) = .TRUE. InvalidOutput( WindVelXY( I) ) = .TRUE. InvalidOutput( WindVelMag(I) ) = .TRUE. InvalidOutput( WindAngXY( I) ) = .TRUE. END DO -IF (p%lidar%SensorType == SensorType_SinglePoint) THEN - DO I=p%lidar%NumBeam+1,5 - InvalidOutput( WindMeas(I) ) = .TRUE. - END DO -ELSE - DO I=p%lidar%NumPulseGate+1,5 - InvalidOutput( WindMeas(I) ) = .TRUE. - END DO - - END IF + ! Set all accelerations invalid if not requested + if (.not. p%OutputAccel) then + InvalidOutput(WindAccX) = .TRUE. + InvalidOutput(WindAccY) = .TRUE. + InvalidOutput(WindAccZ) = .TRUE. + end if + + IF (p%lidar%SensorType == SensorType_SinglePoint) THEN + DO I=p%lidar%NumBeam+1,5 + InvalidOutput( WindMeas(I) ) = .TRUE. + END DO + ELSE + DO I=p%lidar%NumPulseGate+1,5 + InvalidOutput( WindMeas(I) ) = .TRUE. + END DO + END IF ! ................. End of validity checking ................. @@ -1420,9 +1481,17 @@ SUBROUTINE SetAllOuts( p, y, m, ErrStat, ErrMsg ) else m%AllOuts( WindAngXY(I) ) = ATAN2( m%WindViUVW(2,I), m%WindViUVW(1,I) )*R2D ! in degrees end if -! m%AllOuts( WindAngVer(I) ) = ATAN2( m%WindViUVW(3,I), m%AllOuts( WindVelXY(I) ) )*R2D ! in degrees END DO + + ! Set accelerations + if (allocated(m%WindAiUVW)) then + DO I = 1,p%NWindVel + m%AllOuts( WindAccX(I) ) = m%WindAiUVW(1,I) + m%AllOuts( WindAccY(I) ) = m%WindAiUVW(2,I) + m%AllOuts( WindAccZ(I) ) = m%WindAiUVW(3,I) + END DO + end if ! DiskVel outputs: m%AllOuts( WindDiskVelX ) = y%DiskVel(1) diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index cb3681ed6a..0b8f1780ee 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -146,6 +146,7 @@ MODULE InflowWind_Types TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: OutParamLinIndx !< Index into WriteOutput for WindViXYZ in linearization analysis [-] TYPE(Lidar_ParameterType) :: lidar !< Lidar parameter data [-] + LOGICAL :: OutputAccel = .FALSE. !< Flag to output wind acceleration [-] END TYPE InflowWind_ParameterType ! ======================= ! ========= InflowWind_InputType ======= @@ -2443,6 +2444,7 @@ SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, CALL Lidar_CopyParam( SrcParamData%lidar, DstParamData%lidar, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN + DstParamData%OutputAccel = SrcParamData%OutputAccel END SUBROUTINE InflowWind_CopyParam SUBROUTINE InflowWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -2592,6 +2594,7 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + SIZE( Int_Buf ) DEALLOCATE(Int_Buf) END IF + Int_BufSz = Int_BufSz + 1 ! OutputAccel IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2786,6 +2789,8 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er ELSE IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 ENDIF + IntKiBuf(Int_Xferred) = TRANSFER(InData%OutputAccel, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_PackParam SUBROUTINE InflowWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -3024,6 +3029,8 @@ SUBROUTINE InflowWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) + OutData%OutputAccel = TRANSFER(IntKiBuf(Int_Xferred), OutData%OutputAccel) + Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_UnPackParam SUBROUTINE InflowWind_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg ) From aca292ebaff30790b54df31ede80ce2ac8e5705a Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Wed, 5 Apr 2023 22:20:23 +0000 Subject: [PATCH 37/51] Missing check for OutputAccel in IfW --- modules/inflowwind/src/IfW_FlowField.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index 7c5209d044..b2307c215e 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -176,7 +176,7 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A ! If height < zero, set velocity/acceleration to zero, continue if (Position(3, i) <= 0.0_ReKi) then VelocityUVW(:, i) = 0.0_ReKi - AccelUVW(:, i) = 0.0_ReKi + if (OutputAccel) AccelUVW(:, i) = 0.0_ReKi cycle end if From fbf44875f5dfc1d196f36fdb9d6d270fe6173dd8 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 6 Apr 2023 13:25:48 +0000 Subject: [PATCH 38/51] InflowWind: minor cleanup --- modules/inflowwind/src/IfW_FlowField.f90 | 72 ++++++++++-------- modules/inflowwind/src/InflowWind_IO.f90 | 94 +++++++++++------------- 2 files changed, 85 insertions(+), 81 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index b2307c215e..bedbd47341 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -999,15 +999,16 @@ subroutine GetCellInTower(cell, grid, gridAvg, tower) real(SiKi), intent(in) :: gridAvg(:, :, :) real(SiKi), intent(in) :: tower(:, :, :) - real(ReKi) :: GridVal(3, 2) - real(ReKi) :: TowerVal(3, 2) + real(ReKi) :: GridUVW(3, 2) + real(ReKi) :: TowerUVW(3, 2) real(ReKi) :: vc(2, 3, 2) real(ReKi) :: N(2) real(ReKi) :: Xv(3), Yv(3), Wv(3), Px, Py real(ReKi) :: denom integer(IntKi) :: ic, it - if (abs(Position(2)) >= 2.0_ReKi*G3D%YHWid) then ! Extrapolation allowed and Y beyond interp + ! If Y is beyond the grid width from the tower (clamped) + if (abs(Position(2)) >= 2.0_ReKi*G3D%YHWid) then ! Interp between ground and bottom of grid average Xi(2) = 2.0_ReKi*Position(3)/G3D%GridBase - 1.0_ReKi @@ -1016,29 +1017,9 @@ subroutine GetCellInTower(cell, grid, gridAvg, tower) cell(3, :) = 0.0_ReKi cell(4, :) = gridAvg(:, 1, IT_HI) - else ! Extrapolation allowed and Y within interp range + else ! Position is below grid and within +- 2*GridWidth from tower - ! Distance from tower (Y) - Px = Position(2) - Xv(1) = 0.0_ReKi ! Tower - Xv(2) = Position(2) ! Grid bottom - Xv(3) = sign(2.0*G3D%YHWid, Position(2)) ! Ground - - ! Elevation from ground (Z) - Py = Position(3) - Yv(1) = Position(3) ! Tower - Yv(2) = G3D%GridBase ! Grid bottom - Yv(3) = 0.0_ReKi ! Ground - - ! Barycentric weights - denom = ((Yv(2) - Yv(3))*(Xv(1) - Xv(3)) + & - (Xv(3) - Xv(2))*(Yv(1) - Yv(3))) - Wv(1) = ((Yv(2) - Yv(3))*(Px - Xv(3)) + & - (Xv(3) - Xv(2))*(Py - Yv(3)))/denom - Wv(2) = ((Yv(3) - Yv(1))*(Px - Xv(3)) + & - (Xv(1) - Xv(3))*(Py - Yv(3)))/denom - - ! Interpolate grid + ! Interpolate grid (wind components on bottom of grid at Position(2)) N(1) = (1.0_ReKi - Xi(1))/2.0_ReKi N(2) = (1.0_ReKi + Xi(1))/2.0_ReKi @@ -1062,11 +1043,11 @@ subroutine GetCellInTower(cell, grid, gridAvg, tower) do it = 1, 2 do ic = 1, 3 - GridVal(ic, it) = dot_product(vc(:, ic, it), N) + GridUVW(ic, it) = dot_product(vc(:, ic, it), N) end do end do - ! Interpolate tower + ! Interpolate tower (wind components on tower at Position(3)) N(1) = (1.0_ReKi - Xi(2))/2.0_ReKi N(2) = (1.0_ReKi + Xi(2))/2.0_ReKi @@ -1084,14 +1065,43 @@ subroutine GetCellInTower(cell, grid, gridAvg, tower) do it = 1, 2 do ic = 1, 3 - TowerVal(ic, it) = dot_product(vc(:, ic, it), N) + TowerUVW(ic, it) = dot_product(vc(:, ic, it), N) end do end do - ! Populate cell - cell(1, :) = Wv(1)*TowerVal(:, 1) + Wv(2)*GridVal(:, 1) + !---------------------------------------------------------------------- + ! Use Barycentric interpolation to blend grid, tower, and ground wind + ! components at Position. Construct triangle where Point 1 is on the + ! Tower, Point 2 is on the bottom of the grid, Point 3 is on the ground + ! at grid width away from tower. Position will always be within this + ! triangle. Only the weights for Point 1 and Point 2 are calculated + ! as the velocities at Point 3 (ground) are always zero. + !---------------------------------------------------------------------- + + ! Distance from tower (Y) + Px = abs(Position(2)) + Xv(1) = 0.0_ReKi ! Tower + Xv(2) = Position(2) ! Grid bottom + Xv(3) = 2.0*G3D%YHWid ! Ground + + ! Elevation from ground (Z) + Py = Position(3) + Yv(1) = Position(3) ! Tower + Yv(2) = G3D%GridBase ! Grid bottom + Yv(3) = 0.0_ReKi ! Ground + + ! Barycentric weights + denom = ((Yv(2) - Yv(3))*(Xv(1) - Xv(3)) + & + (Xv(3) - Xv(2))*(Yv(1) - Yv(3))) + Wv(1) = ((Yv(2) - Yv(3))*(Px - Xv(3)) + & + (Xv(3) - Xv(2))*(Py - Yv(3)))/denom + Wv(2) = ((Yv(3) - Yv(1))*(Px - Xv(3)) + & + (Xv(1) - Xv(3))*(Py - Yv(3)))/denom + + ! Interpolate wind components and populate cell at IT_Lo and IT_Hi + cell(1, :) = Wv(1)*TowerUVW(:, 1) + Wv(2)*GridUVW(:, 1) cell(2, :) = cell(1, :) - cell(3, :) = Wv(1)*TowerVal(:, 2) + Wv(2)*GridVal(:, 2) + cell(3, :) = Wv(1)*TowerUVW(:, 2) + Wv(2)*GridUVW(:, 2) cell(4, :) = cell(3, :) end if diff --git a/modules/inflowwind/src/InflowWind_IO.f90 b/modules/inflowwind/src/InflowWind_IO.f90 index 3f644e95a2..e68e888de3 100644 --- a/modules/inflowwind/src/InflowWind_IO.f90 +++ b/modules/inflowwind/src/InflowWind_IO.f90 @@ -1,8 +1,3 @@ -!> This module uses grid-field binary wind files to determine the wind inflow. -!! This module assumes that the origin, (0,0,0), is located at the tower centerline at ground level, -!! and that all units are specified in the metric system (using meters and seconds). -!! Data is shifted by half the grid width to account for turbine yaw (so that data in the X -!! direction actually starts at -1*p%YHWid meters). !********************************************************************************************************************************** ! LICENSING ! Copyright (C) 2022 National Renewable Energy Laboratory @@ -41,19 +36,9 @@ module InflowWind_IO ScaleMethod_Direct = 1, & !< direct scaling factors ScaleMethod_StdDev = 2 !< requested standard deviation -type :: TurbSimHeaderType - integer(B2Ki) :: FileID - integer(B4Ki) :: NZGrids, NYGrids, NTGrids, NSteps - real(SiKi) :: dz, dy, dt - real(SiKi) :: mws, ref_height, grid_base_height - real(SiKi) :: VslopeX, VoffsetX - real(SiKi) :: VslopeY, VoffsetY - real(SiKi) :: VslopeZ, VoffsetZ - integer(B4Ki) :: DescLen -end type - contains +!> IfW_SteadyWind_Init initializes a Uniform field with with one set of values. subroutine IfW_SteadyWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) type(Steady_InitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit @@ -134,8 +119,9 @@ subroutine IfW_SteadyWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMs end subroutine +!> IfW_UniformWind_Init initializes a Uniform field from file. subroutine IfW_UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) - type(Uniform_InitInputType), intent(in) :: InitInp + type(Uniform_InitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(UniformFieldType), intent(out) :: UF type(WindFileDat), intent(out) :: FileDat @@ -343,6 +329,7 @@ subroutine IfW_UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrM end subroutine +!> UniformWind_AllocArrays allocates the data arrays in the Uniform field. subroutine UniformWind_AllocArrays(UF, ErrStat, ErrMsg) type(UniformFieldType), intent(inout) :: UF integer(IntKi), intent(out) :: ErrStat @@ -411,6 +398,7 @@ subroutine UniformWind_AllocArrays(UF, ErrStat, ErrMsg) end subroutine +!> Uniform_WriteHH writes a Uniform field hub-height wind file. subroutine Uniform_WriteHH(UF, FileRootName, unit, ErrStat, ErrMsg) type(UniformFieldType), intent(in) :: UF !< Parameter @@ -472,6 +460,17 @@ subroutine IfW_TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) integer(IntKi) :: TmpErrStat ! temporary error status character(ErrMsgLen) :: TmpErrMsg ! temporary error message + type :: TurbSimHeaderType + integer(B2Ki) :: FileID + integer(B4Ki) :: NZGrids, NYGrids, NTGrids, NSteps + real(SiKi) :: dz, dy, dt + real(SiKi) :: mws, ref_height, grid_base_height + real(SiKi) :: VslopeX, VoffsetX + real(SiKi) :: VslopeY, VoffsetY + real(SiKi) :: VslopeZ, VoffsetZ + integer(B4Ki) :: DescLen + end type + type(TurbSimHeaderType) :: header !---------------------------------------------------------------------------- @@ -507,19 +506,19 @@ subroutine IfW_TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) ! Populate parameter data from header !---------------------------------------------------------------------------- - G3D%WindFileFormat = header%FileID ! file format identifier - G3D%Periodic = header%FileID == 8 ! 7 is used for non-periodic wind files; 8 is periodic wind - G3D%InterpTower = .false. ! wind should not be interpolated at tower - G3D%AddMeanAfterInterp = .false. ! do not add mean wind speed after interpolation + G3D%WindFileFormat = header%FileID ! file format identifier + G3D%Periodic = header%FileID == 8 ! 7 is used for non-periodic wind files; 8 is periodic wind + G3D%InterpTower = .false. ! wind should not be interpolated at tower + G3D%AddMeanAfterInterp = .false. ! do not add mean wind speed after interpolation - G3D%DTime = real(header%dt, ReKi) ! grid spacing in time (dt), m/s - G3D%Rate = 1.0_ReKi/G3D%DTime ! Data rate (1/DTime), Hertz + G3D%DTime = real(header%dt, ReKi) ! grid spacing in time (dt), m/s + G3D%Rate = 1.0_ReKi/G3D%DTime ! Data rate (1/DTime), Hertz - G3D%NComp = 3 ! TurbSim file file contains 3 wind components - G3D%NYGrids = header%NYGrids ! the number of grid points laterally - G3D%NZGrids = header%NZGrids ! the number of grid points vertically - G3D%NTGrids = header%NTGrids ! the number of tower points - G3D%NSteps = header%NSteps ! the number of time steps + G3D%NComp = 3 ! TurbSim file file contains 3 wind components + G3D%NYGrids = header%NYGrids ! the number of grid points laterally + G3D%NZGrids = header%NZGrids ! the number of grid points vertically + G3D%NTGrids = header%NTGrids ! the number of tower points + G3D%NSteps = header%NSteps ! the number of time steps G3D%InvDY = 1.0_ReKi/real(header%dy, ReKi) ! 1/dy G3D%YHWid = 0.5_ReKi*(G3D%NYGrids - 1)/G3D%InvDY ! half the grid width (m) @@ -740,7 +739,7 @@ subroutine IfW_TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) subroutine IfW_HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) - type(HAWC_InitInputType), intent(in) :: InitInp + type(HAWC_InitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(Grid3DFieldType), intent(out) :: G3D type(WindFileDat), intent(out) :: FileDat @@ -749,12 +748,10 @@ subroutine IfW_HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) character(*), parameter :: RoutineName = "Read_HAWC" integer(IntKi) :: WindFileUnit - real(SiKi), allocatable :: VelRaw(:, :) ! grid-field data for one timestep + real(SiKi), allocatable :: VelRaw(:, :) ! grid-field data for one timestep integer :: IC ! Loop counter for the number of wind components integer :: IX, IY, IZ ! Loop counters for the number of grid points in the X,Y,Z directions real(DbKi) :: vMean ! average wind speeds over time at target position - real(DbKi) :: vSum2 ! sum of wind speeds squared - real(ReKi) :: ActualSigma ! computed standard deviation real(ReKi) :: ScaleFactors(3) ! scale factors integer(IntKi) :: TmpErrStat ! temporary error status character(ErrMsgLen) :: TmpErrMsg @@ -882,8 +879,6 @@ subroutine IfW_HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) ! Reorganize raw data into grid-field array (reverse Y indices) do IZ = 1, G3D%NZGrids - ! Vel(NComp, NYGrids, NZGrids, NSteps) - ! VelRaw(NZGrids, NYGrids) G3D%Vel(IC, :, IZ, IX) = VelRaw(IZ, G3D%NYGrids:1:-1) end do end do @@ -942,18 +937,18 @@ subroutine IfW_HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) write (SumFileUnit, '(A)') ' Z range (m): [ '// & TRIM(Num2LStr(G3D%GridBase))//' : '//TRIM(Num2LStr(G3D%GridBase + G3D%ZHWid*2.0))//' ]' - IF ( G3D%BoxExceedAllowF ) THEN - WRITE(SumFileUnit,'(A)') ' Wind grid exceedence allowed: '// & - 'True -- Only for points requested by OLAF free vortex wake, or LidarSim module' - WRITE(SumFileUnit,'(A)') ' '// & - ' Out of bounds values are linearly interpolated to mean at Z loction for' - WRITE(SumFileUnit,'(A)') ' '// & - ' given timestep and X,T value. Values above grid are held to top of wind' - WRITE(SumFileUnit,'(A)') ' '// & - ' grid value' - ELSE - WRITE(SumFileUnit,'(A)') ' Wind grid exceedence allowed: False' - ENDIF + if (G3D%BoxExceedAllowF) then + write (SumFileUnit, '(A)') ' Wind grid exceedence allowed: '// & + 'True -- Only for points requested by OLAF free vortex wake, or LidarSim module' + write (SumFileUnit, '(A)') ' '// & + ' Out of bounds values are linearly interpolated to mean at Z loction for' + write (SumFileUnit, '(A)') ' '// & + ' given timestep and X,T value. Values above grid are held to top of wind' + write (SumFileUnit, '(A)') ' '// & + ' grid value' + else + write (SumFileUnit, '(A)') ' Wind grid exceedence allowed: False' + end if write (SumFileUnit, '(A)') 'Scaling factors used:' write (SumFileUnit, '(A)') ' u v w ' @@ -2474,7 +2469,6 @@ subroutine Grid3D_ScaleTurbulence(InitInp, Vel, ScaleFactors, ErrStat, ErrMsg) real(ReKi) :: ActualSigma(3) ! computed standard deviation integer :: ic ! Loop counter for wind component - integer :: it ! Loop counter for t integer :: iy ! Loop counter for y integer :: iz ! Loop counter for z @@ -2638,7 +2632,7 @@ subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) ! and ensure that 32.767*sigma_u >= |V-UHub| so that we don't get values out of the range of our scaling values ! in this BLADED-style binary output. Tmp is |V-UHub| ! Get the range of wind speed values for scaling in BLADED-format .wnd files - Tmp = max(abs(maxval(G3D%Vel(:, :, 1, :)) - G3D%MeanWS), abs(minval(G3D%Vel(1, :, :, :)) - G3D%MeanWS)) + Tmp = real(max(abs(maxval(G3D%Vel(:, :, 1, :)) - G3D%MeanWS), abs(minval(G3D%Vel(1, :, :, :)) - G3D%MeanWS)), SiKi) Sigma(1) = max(Sigma(1), 0.05_SiKi*Tmp) do ic = 2, 3 ! put the abs() after the maxval() and minval() to avoid stack-overflow issues with large wind files @@ -2653,7 +2647,7 @@ subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) MeanWS_nonZero = G3D%MeanWS end if - TI = Sigma/MeanWS_nonZero + TI = real(Sigma/MeanWS_nonZero, SiKi) !---------------------------------------------------------------------------- ! The summary file @@ -2740,7 +2734,7 @@ subroutine Grid3D_WriteBladed(G3D, FileRootName, unit, ErrStat, ErrMsg) if (G3D%AddMeanAfterInterp) then ! Note that this will not take into account any shear!!! Off(1) = 0.0 else - Off(1) = G3D%MeanWS*Scl(1) + Off(1) = real(G3D%MeanWS*Scl(1), SiKi) end if Off(2) = 0.0 Off(3) = 0.0 From bdf7f18274c3b47318737da988ac1f9cd61fba01 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 6 Apr 2023 18:30:11 +0000 Subject: [PATCH 39/51] InflowWind cleanup and better tower grid interp --- modules/inflowwind/src/IfW_FlowField.f90 | 411 +++++++++--------- .../inflowwind/src/InflowWind_Driver_Subs.f90 | 4 +- .../src/InflowWind_Driver_Types.f90 | 2 +- 3 files changed, 205 insertions(+), 212 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index bedbd47341..f6e7c661a5 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -805,26 +805,11 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & Is3D = .false. ! Tower grids present and position is below main grid - if (.not. AllowExtrap) then - - ! Get cell without extrapolation - call GetCellInTowerNoExtrap(VelCell, G3D%VelTower) - - ! If acceleration requested, get cell values - if (CalcAccel) then - call GetCellInTowerNoExtrap(AccCell, G3D%AccTower) - end if - - else - - ! Get cell with extrapolation - call GetCellInTower(VelCell, G3D%Vel, G3D%VelAvg, G3D%VelTower) - - ! If acceleration requested, get cell values - if (CalcAccel) then - call GetCellInTower(AccCell, G3D%Acc, G3D%AccAvg, G3D%AccTower) - end if + call GetCellInTower(VelCell, G3D%Vel, G3D%VelAvg, G3D%VelTower) + ! If acceleration requested, get cell values + if (CalcAccel) then + call GetCellInTower(AccCell, G3D%Acc, G3D%AccAvg, G3D%AccTower) end if else @@ -833,44 +818,44 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & Is3D = .true. ! Tower interpolation without tower grids - call GetCellBelowGrid(VelCell, G3D%Vel, G3D%VelAvg) + call GetCellBelowGrid(VelCell, G3D%Vel) ! If acceleration requested, get cell values if (CalcAccel) then - call GetCellBelowGrid(AccCell, G3D%Acc, G3D%AccAvg) + call GetCellBelowGrid(AccCell, G3D%Acc) end if end if contains - subroutine GetCellInGrid(cell, grid, gridAvg) + subroutine GetCellInGrid(cell, gridVal, gridAvg) - real(ReKi), intent(out) :: cell(8, 3) - real(SiKi), intent(in) :: grid(:, :, :, :) - real(SiKi), intent(in) :: gridAvg(:, :, :) + real(ReKi), intent(out) :: cell(8, 3) + real(SiKi), intent(in) :: gridVal(:, :, :, :) + real(SiKi), intent(in), allocatable :: gridAvg(:, :, :) ! Select based on extrapolation flags select case (AllExtrap) case (ExtrapNone) ! No extrapolation - cell(1, :) = grid(:, IY_Lo, IZ_Lo, IT_Lo) - cell(2, :) = grid(:, IY_Hi, IZ_Lo, IT_Lo) - cell(3, :) = grid(:, IY_Lo, IZ_Hi, IT_Lo) - cell(4, :) = grid(:, IY_Hi, IZ_Hi, IT_Lo) - cell(5, :) = grid(:, IY_Lo, IZ_Lo, IT_Hi) - cell(6, :) = grid(:, IY_Hi, IZ_Lo, IT_Hi) - cell(7, :) = grid(:, IY_Lo, IZ_Hi, IT_Hi) - cell(8, :) = grid(:, IY_Hi, IZ_Hi, IT_Hi) + cell(1, :) = gridVal(:, IY_Lo, IZ_Lo, IT_Lo) + cell(2, :) = gridVal(:, IY_Hi, IZ_Lo, IT_Lo) + cell(3, :) = gridVal(:, IY_Lo, IZ_Hi, IT_Lo) + cell(4, :) = gridVal(:, IY_Hi, IZ_Hi, IT_Lo) + cell(5, :) = gridVal(:, IY_Lo, IZ_Lo, IT_Hi) + cell(6, :) = gridVal(:, IY_Hi, IZ_Lo, IT_Hi) + cell(7, :) = gridVal(:, IY_Lo, IZ_Hi, IT_Hi) + cell(8, :) = gridVal(:, IY_Hi, IZ_Hi, IT_Hi) case (ior(ExtrapZmax, ExtrapYmax)) ! Extrapolate top right corner - cell(1, :) = grid(:, IY_Lo, IZ_Lo, IT_Lo) + cell(1, :) = gridVal(:, IY_Lo, IZ_Lo, IT_Lo) cell(2, :) = gridAvg(:, IZ_Lo, IT_Lo) cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) - cell(5, :) = grid(:, IY_Lo, IZ_Lo, IT_Hi) + cell(5, :) = gridVal(:, IY_Lo, IZ_Lo, IT_Hi) cell(6, :) = gridAvg(:, IZ_Lo, IT_Hi) cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) @@ -878,236 +863,246 @@ subroutine GetCellInGrid(cell, grid, gridAvg) case (ior(ExtrapZmax, ExtrapYmin))! Extrapolate top left corner cell(1, :) = gridAvg(:, IZ_Lo, IT_Lo) - cell(2, :) = grid(:, IY_Hi, IZ_Lo, IT_Lo) + cell(2, :) = gridVal(:, IY_Hi, IZ_Lo, IT_Lo) cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) cell(5, :) = gridAvg(:, IZ_Lo, IT_Hi) - cell(6, :) = grid(:, IY_Hi, IZ_Lo, IT_Hi) + cell(6, :) = gridVal(:, IY_Hi, IZ_Lo, IT_Hi) cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) case (ExtrapZmax) ! Extrapolate above grid only - cell(1, :) = grid(:, IY_Lo, IZ_Lo, IT_Lo) - cell(2, :) = grid(:, IY_Hi, IZ_Lo, IT_Lo) + cell(1, :) = gridVal(:, IY_Lo, IZ_Lo, IT_Lo) + cell(2, :) = gridVal(:, IY_Hi, IZ_Lo, IT_Lo) cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) - cell(5, :) = grid(:, IY_Lo, IZ_Lo, IT_Hi) - cell(6, :) = grid(:, IY_Hi, IZ_Lo, IT_Hi) + cell(5, :) = gridVal(:, IY_Lo, IZ_Lo, IT_Hi) + cell(6, :) = gridVal(:, IY_Hi, IZ_Lo, IT_Hi) cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) case (ExtrapYmax) ! Extrapolate to the right of grid only - cell(1, :) = grid(:, IY_Lo, IZ_Lo, IT_Lo) + cell(1, :) = gridVal(:, IY_Lo, IZ_Lo, IT_Lo) cell(2, :) = gridAvg(:, IZ_Lo, IT_Lo) - cell(3, :) = grid(:, IY_Lo, IZ_Hi, IT_Lo) + cell(3, :) = gridVal(:, IY_Lo, IZ_Hi, IT_Lo) cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) - cell(5, :) = grid(:, IY_Lo, IZ_Lo, IT_Hi) + cell(5, :) = gridVal(:, IY_Lo, IZ_Lo, IT_Hi) cell(6, :) = gridAvg(:, IZ_Lo, IT_Hi) - cell(7, :) = grid(:, IY_Lo, IZ_Hi, IT_Hi) + cell(7, :) = gridVal(:, IY_Lo, IZ_Hi, IT_Hi) cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) case (ExtrapYmin) ! Extrapolate to the left of grid only cell(1, :) = gridAvg(:, IZ_Lo, IT_Lo) - cell(2, :) = grid(:, IY_Hi, IZ_Lo, IT_Lo) + cell(2, :) = gridVal(:, IY_Hi, IZ_Lo, IT_Lo) cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) - cell(4, :) = grid(:, IY_Hi, IZ_Hi, IT_Lo) + cell(4, :) = gridVal(:, IY_Hi, IZ_Hi, IT_Lo) cell(5, :) = gridAvg(:, IZ_Lo, IT_Hi) - cell(6, :) = grid(:, IY_Hi, IZ_Lo, IT_Hi) + cell(6, :) = gridVal(:, IY_Hi, IZ_Lo, IT_Hi) cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) - cell(8, :) = grid(:, IY_Hi, IZ_Hi, IT_Hi) + cell(8, :) = gridVal(:, IY_Hi, IZ_Hi, IT_Hi) + + case (ExtrapZmin) ! Extrapolate below grid + + cell(1, :) = 0.0_ReKi ! Ground + cell(2, :) = 0.0_ReKi ! Ground + cell(3, :) = gridVal(:, IY_Lo, 1, IT_Lo) + cell(4, :) = gridVal(:, IY_Hi, 1, IT_Lo) + cell(5, :) = 0.0_ReKi ! Ground + cell(6, :) = 0.0_ReKi ! Ground + cell(7, :) = gridVal(:, IY_Lo, 1, IT_Hi) + cell(8, :) = gridVal(:, IY_Hi, 1, IT_Hi) + + case (ior(ExtrapZmin, ExtrapYmin)) ! Extrapolate lower left of grid + + cell(1, :) = 0.0_ReKi ! Ground + cell(2, :) = 0.0_ReKi ! Ground + cell(3, :) = gridAvg(:, 1, IT_Lo) ! Average + cell(4, :) = gridVal(:, 1, 1, IT_Lo) + cell(5, :) = 0.0_ReKi ! Ground + cell(6, :) = 0.0_ReKi ! Ground + cell(7, :) = gridAvg(:, 1, IT_Hi) ! Average + cell(8, :) = gridVal(:, 1, 1, IT_Hi) + + case (ior(ExtrapZmin, ExtrapYmax)) ! Extrapolate lower right of grid + + cell(1, :) = 0.0_ReKi ! Ground + cell(2, :) = 0.0_ReKi ! Ground + cell(3, :) = gridVal(:, G3D%NYGrids, 1, IT_Lo) + cell(4, :) = gridAvg(:, 1, IT_Lo) ! Average + cell(5, :) = 0.0_ReKi ! Ground + cell(6, :) = 0.0_ReKi ! Ground + cell(7, :) = gridVal(:, G3D%NYGrids, 1, IT_Hi) + cell(8, :) = gridAvg(:, 1, IT_Hi) ! Average end select end subroutine - subroutine GetCellBelowGrid(cell, grid, gridAvg) + !> GetCellBelowGrid interpolates between bottom of grid and ground. This + !! is only called if G3D%InterpTower == .true. + subroutine GetCellBelowGrid(cell, gridVal) real(ReKi), intent(out) :: cell(8, 3) - real(SiKi), intent(in) :: grid(:, :, :, :) - real(SiKi), intent(in) :: gridAvg(:, :, :) - - ! Select based on extrapolation flags - select case (AllExtrap) - - case (ExtrapNone) + real(SiKi), intent(in) :: gridVal(:, :, :, :) - cell(1, :) = 0.0_ReKi ! Ground - cell(2, :) = 0.0_ReKi ! Ground - cell(3, :) = grid(:, IY_Lo, IZ_Hi, IT_Lo) - cell(4, :) = grid(:, IY_Hi, IZ_Hi, IT_Lo) - cell(5, :) = 0.0_ReKi ! Ground - cell(6, :) = 0.0_ReKi ! Ground - cell(7, :) = grid(:, IY_Lo, IZ_Hi, IT_Hi) - cell(8, :) = grid(:, IY_Hi, IZ_Hi, IT_Hi) - - case (ExtrapYmin) ! Extrap to bottom left of grid - - cell(1, :) = 0.0_ReKi ! Ground - cell(2, :) = 0.0_ReKi ! Ground - cell(3, :) = gridAvg(:, IZ_Hi, IT_Lo) - cell(4, :) = grid(:, IY_Hi, IZ_Hi, IT_Lo) - cell(5, :) = 0.0_ReKi ! Ground - cell(6, :) = 0.0_ReKi ! Ground - cell(7, :) = gridAvg(:, IZ_Hi, IT_Hi) - cell(8, :) = grid(:, IY_Hi, IZ_Hi, IT_Hi) - - case (ExtrapYmax) ! Extrap to bottom right of grid - - cell(1, :) = 0.0_ReKi ! Ground - cell(2, :) = 0.0_ReKi ! Ground - cell(3, :) = grid(:, IY_Lo, IZ_Hi, IT_Lo) - cell(4, :) = gridAvg(:, IZ_Hi, IT_Lo) - cell(5, :) = 0.0_ReKi ! Ground - cell(6, :) = 0.0_ReKi ! Ground - cell(7, :) = grid(:, IY_Lo, IZ_Hi, IT_Hi) - cell(8, :) = gridAvg(:, IZ_Hi, IT_Hi) - - end select + cell(1, :) = 0.0_ReKi ! Ground + cell(2, :) = 0.0_ReKi ! Ground + cell(3, :) = gridVal(:, IY_Lo, IZ_Hi, IT_Lo) + cell(4, :) = gridVal(:, IY_Hi, IZ_Hi, IT_Lo) + cell(5, :) = 0.0_ReKi ! Ground + cell(6, :) = 0.0_ReKi ! Ground + cell(7, :) = gridVal(:, IY_Lo, IZ_Hi, IT_Hi) + cell(8, :) = gridVal(:, IY_Hi, IZ_Hi, IT_Hi) end subroutine - subroutine GetCellInTowerNoExtrap(cell, tower) - - real(ReKi), intent(out) :: cell(8, 3) - real(SiKi), intent(in) :: tower(:, :, :) - - if (IZ_HI <= G3D%NTGrids) then ! In tower grid + subroutine GetCellInTower(cell, gridVal, gridAvg, towerVal) - cell(1, :) = tower(:, IZ_LO, IT_LO) - cell(2, :) = tower(:, IZ_HI, IT_LO) - cell(3, :) = tower(:, IZ_LO, IT_HI) - cell(4, :) = tower(:, IZ_HI, IT_HI) + real(ReKi), intent(out) :: cell(8, 3) + real(SiKi), intent(in) :: gridVal(:, :, :, :) + real(SiKi), intent(in), allocatable :: gridAvg(:, :, :) + real(SiKi), intent(in), allocatable :: towerVal(:, :, :) - else ! Between tower grid and ground + real(ReKi) :: Y(0:5), Z(0:5), W(4), Py, Pz + real(ReKi) :: V(3, 4, 2) + real(ReKi) :: alpha + integer(IntKi) :: ic, i - cell(1, :) = tower(:, IZ_LO, IT_LO) - cell(2, :) = 0.0_ReKi - cell(3, :) = tower(:, IZ_LO, IT_HI) - cell(4, :) = 0.0_ReKi + !------------------------------------------------------------------------- + ! If extrapolation is not allowed, apply tower values to all Y positions + !------------------------------------------------------------------------- + if (.not. AllowExtrap) then + if (IZ_HI <= G3D%NTGrids) then ! In tower grid + cell(1, :) = towerVal(:, IZ_LO, IT_LO) + cell(2, :) = towerVal(:, IZ_HI, IT_LO) + cell(3, :) = towerVal(:, IZ_LO, IT_HI) + cell(4, :) = towerVal(:, IZ_HI, IT_HI) + else ! Between tower grid and ground + cell(1, :) = towerVal(:, IZ_LO, IT_LO) + cell(2, :) = 0.0_ReKi + cell(3, :) = towerVal(:, IZ_LO, IT_HI) + cell(4, :) = 0.0_ReKi + end if + return end if - end subroutine - - subroutine GetCellInTower(cell, grid, gridAvg, tower) + !------------------------------------------------------------------------- + ! If Y is beyond grid width from the tower (clamped), + ! interp between ground and bottom of grid average + !------------------------------------------------------------------------- - real(ReKi), intent(out) :: cell(8, 3) - real(SiKi), intent(in) :: grid(:, :, :, :) - real(SiKi), intent(in) :: gridAvg(:, :, :) - real(SiKi), intent(in) :: tower(:, :, :) - - real(ReKi) :: GridUVW(3, 2) - real(ReKi) :: TowerUVW(3, 2) - real(ReKi) :: vc(2, 3, 2) - real(ReKi) :: N(2) - real(ReKi) :: Xv(3), Yv(3), Wv(3), Px, Py - real(ReKi) :: denom - integer(IntKi) :: ic, it - - ! If Y is beyond the grid width from the tower (clamped) - if (abs(Position(2)) >= 2.0_ReKi*G3D%YHWid) then - - ! Interp between ground and bottom of grid average + if (abs(Position(2)) >= 2.0_ReKi*G3D%YHWid) then Xi(2) = 2.0_ReKi*Position(3)/G3D%GridBase - 1.0_ReKi cell(1, :) = 0.0_ReKi cell(2, :) = gridAvg(:, 1, IT_LO) cell(3, :) = 0.0_ReKi cell(4, :) = gridAvg(:, 1, IT_HI) + return + end if - else ! Position is below grid and within +- 2*GridWidth from tower - - ! Interpolate grid (wind components on bottom of grid at Position(2)) - N(1) = (1.0_ReKi - Xi(1))/2.0_ReKi - N(2) = (1.0_ReKi + Xi(1))/2.0_ReKi - - select case (AllExtrap) - case (ExtrapNone) - vc(1, :, 1) = grid(:, IY_Lo, 1, IT_Lo) - vc(2, :, 1) = grid(:, IY_Hi, 1, IT_Lo) - vc(1, :, 2) = grid(:, IY_Lo, 1, IT_Hi) - vc(2, :, 2) = grid(:, IY_Hi, 1, IT_Hi) - case (ExtrapYmin) - vc(1, :, 1) = gridAvg(:, 1, IT_Lo) - vc(2, :, 1) = grid(:, IY_Lo, 1, IT_Lo) - vc(1, :, 2) = gridAvg(:, 1, IT_Hi) - vc(2, :, 2) = grid(:, IY_Lo, 1, IT_Hi) - case (ExtrapYmax) - vc(1, :, 1) = grid(:, IY_Hi, 1, IT_Lo) - vc(2, :, 1) = gridAvg(:, 1, IT_Lo) - vc(1, :, 2) = grid(:, IY_Hi, 1, IT_Hi) - vc(2, :, 2) = gridAvg(:, 1, IT_Hi) - end select - - do it = 1, 2 - do ic = 1, 3 - GridUVW(ic, it) = dot_product(vc(:, ic, it), N) - end do - end do + !------------------------------------------------------------------------- + ! Otherwise, position is below grid and within +- 2*GridWidth from tower + ! This section uses Barycentric interpolation between four points to get + ! the wind components at the desired Position. + ! + ! Points are ordered counter clockwise. Points on left side of tower + ! are reflected to the right side. + !------------------------------------------------------------------------- - ! Interpolate tower (wind components on tower at Position(3)) - N(1) = (1.0_ReKi - Xi(2))/2.0_ReKi - N(2) = (1.0_ReKi + Xi(2))/2.0_ReKi + ! Point 1 (ground @ grid width away from tower) + Y(1) = 2.0_ReKi*G3D%YHWid + Z(1) = 0.0_Reki + V(:, 1, :) = 0.0_ReKi - if (IZ_HI <= G3D%NTGrids) then - vc(1, :, 1) = tower(:, IZ_Lo, IT_Lo) - vc(2, :, 1) = tower(:, IZ_Hi, IT_Lo) - vc(1, :, 2) = tower(:, IZ_Lo, IT_Hi) - vc(2, :, 2) = tower(:, IZ_Hi, IT_Hi) - else - vc(1, :, 1) = tower(:, IZ_Lo, IT_Lo) - vc(2, :, 1) = 0.0_ReKi - vc(1, :, 2) = tower(:, IZ_Lo, IT_Hi) - vc(2, :, 2) = 0.0_ReKi - end if + ! Point 2 (grid bottom point) + Y(2) = abs(Position(2)) + Z(2) = G3D%GridBase - do it = 1, 2 - do ic = 1, 3 - TowerUVW(ic, it) = dot_product(vc(:, ic, it), N) - end do - end do + select case (AllExtrap) + case (ExtrapNone) + + ! Interpolate between grid points + alpha = (Xi(1) + 1.0_ReKi)/2.0_ReKi + V(:, 2, 1) = (1.0_ReKi - alpha)*gridVal(:, IY_Lo, 1, IT_Lo) + & + alpha*gridVal(:, IY_Hi, 1, IT_Lo) + V(:, 2, 2) = (1.0_ReKi - alpha)*gridVal(:, IY_Lo, 1, IT_Hi) + & + alpha*gridVal(:, IY_Hi, 1, IT_Hi) + + case (ExtrapYmin, ExtrapYmax) + + ! Interpolate between edge of grid and grid average + alpha = abs(Position(2))/G3D%YHWid - 1.0_ReKi + V(:, 2, 1) = (1.0_ReKi - alpha)*gridVal(:, IY_Lo, 1, IT_Lo) + & + alpha*gridAvg(:, 1, IT_Lo) + V(:, 2, 2) = (1.0_ReKi - alpha)*gridVal(:, IY_Lo, 1, IT_Hi) + & + alpha*gridAvg(:, 1, IT_Hi) - !---------------------------------------------------------------------- - ! Use Barycentric interpolation to blend grid, tower, and ground wind - ! components at Position. Construct triangle where Point 1 is on the - ! Tower, Point 2 is on the bottom of the grid, Point 3 is on the ground - ! at grid width away from tower. Position will always be within this - ! triangle. Only the weights for Point 1 and Point 2 are calculated - ! as the velocities at Point 3 (ground) are always zero. - !---------------------------------------------------------------------- - - ! Distance from tower (Y) - Px = abs(Position(2)) - Xv(1) = 0.0_ReKi ! Tower - Xv(2) = Position(2) ! Grid bottom - Xv(3) = 2.0*G3D%YHWid ! Ground - - ! Elevation from ground (Z) - Py = Position(3) - Yv(1) = Position(3) ! Tower - Yv(2) = G3D%GridBase ! Grid bottom - Yv(3) = 0.0_ReKi ! Ground - - ! Barycentric weights - denom = ((Yv(2) - Yv(3))*(Xv(1) - Xv(3)) + & - (Xv(3) - Xv(2))*(Yv(1) - Yv(3))) - Wv(1) = ((Yv(2) - Yv(3))*(Px - Xv(3)) + & - (Xv(3) - Xv(2))*(Py - Yv(3)))/denom - Wv(2) = ((Yv(3) - Yv(1))*(Px - Xv(3)) + & - (Xv(1) - Xv(3))*(Py - Yv(3)))/denom - - ! Interpolate wind components and populate cell at IT_Lo and IT_Hi - cell(1, :) = Wv(1)*TowerUVW(:, 1) + Wv(2)*GridUVW(:, 1) - cell(2, :) = cell(1, :) - cell(3, :) = Wv(1)*TowerUVW(:, 2) + Wv(2)*GridUVW(:, 2) - cell(4, :) = cell(3, :) + end select + ! Point 3 (upper tower point) + Y(3) = 0.0_ReKi + Z(3) = G3D%GridBase - real(IZ_Lo - 1, ReKi)/G3D%InvDZ + V(:, 3, 1) = towerVal(:, IZ_Lo, IT_Lo) + V(:, 3, 2) = towerVal(:, IZ_Lo, IT_Hi) + + ! Point 4 (lower tower point) + Y(4) = 0.0_ReKi + if (IZ_HI <= G3D%NTGrids) then ! Lower point above ground + Z(4) = G3D%GridBase - real(IZ_Hi - 1, ReKi)/G3D%InvDZ + V(:, 4, 1) = towerVal(:, IZ_Hi, IT_Lo) + V(:, 4, 2) = towerVal(:, IZ_Hi, IT_Hi) + else ! Lower point on ground + Z(4) = 0.0_ReKi + V(:, 4, :) = 0.0_ReKi end if + !------------------------------------------------------------------------- + ! Calculate Barycentric weights for quadrilateral + !------------------------------------------------------------------------- + + ! Get interpolation point + Py = abs(Position(2)) + Pz = Position(3) + + ! Copy start and end coords for easier indexing when calculating weights + Y(0) = Y(4) + Y(5) = Y(1) + Z(0) = Z(4) + Z(5) = Z(1) + + ! Calculate weights + do i = 1, 4 + W(i) = TriangleArea([Y(i - 1), Y(i), Y(i + 1)], [Z(i - 1), Z(i), Z(i + 1)])/ & + (TriangleArea([Py, Y(i - 1), Y(i)], [Pz, Z(i - 1), Z(i)])* & + TriangleArea([Py, Y(i), Y(i + 1)], [Pz, Z(i), Z(i + 1)])) + end do + + ! Normalize Weights so they sum to 1.0 + W = W/sum(W) + + ! Interpolate wind components based on weights + do ic = 1, 3 + cell(1, ic) = dot_product(V(ic, :, 1), W) + cell(3, ic) = dot_product(V(ic, :, 2), W) + end do + cell(2, :) = cell(1, :) + cell(4, :) = cell(3, :) + end subroutine + !> TriangleArea returns the signed area of a triangle. + function TriangleArea(x, y) result(A) + real(ReKi) :: x(3), y(3) + real(ReKi) :: A + A = (x(1)*(y(2) - y(3)) + & + x(2)*(y(3) - y(1)) + & + x(3)*(y(1) - y(2)))/2.0_ReKi + end function + subroutine GetBoundsY(PosY, DY) real(ReKi), intent(in) :: PosY @@ -1120,7 +1115,7 @@ subroutine GetBoundsY(PosY, DY) ! Calculate bounding grid indices IY_LO = floor(Y_Grid, IntKi) - IY_HI = ceiling(Y_Grid, IntKi) + IY_HI = IY_LO + 1 ! Position location within interval [0,1] DY = Y_Grid - aint(Y_Grid) @@ -1171,7 +1166,7 @@ subroutine GetBoundsZ(PosZ, DZ) ! Calculate bounding grid indices IZ_LO = floor(Z_GRID, IntKi) - IZ_HI = ceiling(Z_GRID, IntKi) + IZ_HI = IZ_LO + 1 ! Position location within interval [-1,1] DZ = Z_GRID - aint(Z_GRID) diff --git a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 index 928eb4cb2e..09b1e099ba 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 @@ -330,15 +330,13 @@ SUBROUTINE ParseArg( CLSettings, CLFlags, ThisArgUC, ThisArg, ifwFlagSet, ErrSta RETURN ELSEIF ( TRIM(ThisArgUC) == "UNIFORM" ) THEN CLFlags%WrUniform = .TRUE. + RETURN ELSEIF ( TRIM(ThisArgUC) == "BOXEXCEEDALLOW" ) THEN CLFlags%BoxExceedAllowF = .TRUE. RETURN ELSEIF ( TRIM(ThisArgUC) == "ACCEL" ) THEN CLFlags%OutputAccel = .TRUE. RETURN - ELSEIF ( TRIM(ThisArgUC) == "ACCEL" ) THEN - CLFlags%OutputAccel = .TRUE. - RETURN ELSE CALL SetErrStat( ErrID_Warn," Unrecognized option '"//SwChar//TRIM(ThisArg)//"'. Ignoring. Use option "//SwChar//"help for list of options.", & ErrStat,ErrMsg,'ParseArg') diff --git a/modules/inflowwind/src/InflowWind_Driver_Types.f90 b/modules/inflowwind/src/InflowWind_Driver_Types.f90 index 5527d29304..d2584a9b2a 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Types.f90 @@ -66,7 +66,7 @@ MODULE InflowWind_Driver_Types LOGICAL :: Dz = .FALSE. !< specified a resolution in z LOGICAL :: PointsFile = .FALSE. !< points filename to read in - LOGICAL :: OutputAccel = .FALSE. !< flag to calculate and output wind acceleration in addition to velocity + LOGICAL :: OutputAccel = .FALSE. !< flag to calculate and output wind acceleration in addition to velocity LOGICAL :: Verbose = .FALSE. !< Verbose error reporting LOGICAL :: VVerbose = .FALSE. !< Very Verbose error reporting From a8a4de697a1e99e98575235c31c37ec63e64cd13 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Thu, 6 Apr 2023 19:45:34 +0000 Subject: [PATCH 40/51] Updated api_change.rst for InflowWind changes --- docs/source/user/api_change.rst | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index b301b8247d..19d9d3a1aa 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -18,24 +18,25 @@ Modified in OpenFAST `dev` Module Line Flag Name Example Value ============================================= ==== ==================== ======================================================================================================================================================================================================== ServoDyn-StructCtrl 6 StC_DOF_MODE 2 StC_DOF_MODE - DOF mode (switch) {0: No StC or TLCD DOF; 1: StC_X_DOF, StC_Y_DOF, and/or StC_Z_DOF (three independent StC DOFs); 2: StC_XY_DOF (Omni-Directional StC); 3: TLCD; 4: Prescribed force/moment time series; 5: Force determined by external DLL} -InflowWind 50 ================== LIDAR Parameters =========================================================================== -InflowWind 51 SensorType 0 SensorType - Switch for lidar configuration (0 = None, 1 = Single Point Beam(s), 2 = Continuous, 3 = Pulsed) -InflowWind 52 NumPulseGate 0 NumPulseGate - Number of lidar measurement gates (used when SensorType = 3) -InflowWind 53 PulseSpacing 30 PulseSpacing - Distance between range gates (m) (used when SensorType = 3) -InflowWind 54 NumBeam 0 NumBeam - Number of lidar measurement beams (0-5)(used when SensorType = 1) -InflowWind 55 FocalDistanceX -200 FocalDistanceX - Focal distance co-ordinates of the lidar beam in the x direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m) -InflowWind 56 FocalDistanceY 0 FocalDistanceY - Focal distance co-ordinates of the lidar beam in the y direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m) -InflowWind 57 FocalDistanceZ 0 FocalDistanceZ - Focal distance co-ordinates of the lidar beam in the z direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m) -InflowWind 58 RotorApexOffsetPos 0.0 0.0 0.0 RotorApexOffsetPos - Offset of the lidar from hub height (m) -InflowWind 59 URefLid 17 URefLid - Reference average wind speed for the lidar[m/s] -InflowWind 50 MeasurementInterval 0.25 MeasurementInterval - Time between each measurement [s] -InflowWind 61 LidRadialVel False LidRadialVel - TRUE => return radial component, FALSE => return 'x' direction estimate -InflowWind 62 ConsiderHubMotion 1 ConsiderHubMotion - Flag whether to consider the hub motion's impact on Lidar measurements +InflowWind 8 VelInterpCubic true VelInterpCubic - Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7] +InflowWind 51 ================== LIDAR Parameters =========================================================================== +InflowWind 52 SensorType 0 SensorType - Switch for lidar configuration (0 = None, 1 = Single Point Beam(s), 2 = Continuous, 3 = Pulsed) +InflowWind 53 NumPulseGate 0 NumPulseGate - Number of lidar measurement gates (used when SensorType = 3) +InflowWind 54 PulseSpacing 30 PulseSpacing - Distance between range gates (m) (used when SensorType = 3) +InflowWind 55 NumBeam 0 NumBeam - Number of lidar measurement beams (0-5)(used when SensorType = 1) +InflowWind 56 FocalDistanceX -200 FocalDistanceX - Focal distance co-ordinates of the lidar beam in the x direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m) +InflowWind 57 FocalDistanceY 0 FocalDistanceY - Focal distance co-ordinates of the lidar beam in the y direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m) +InflowWind 58 FocalDistanceZ 0 FocalDistanceZ - Focal distance co-ordinates of the lidar beam in the z direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m) +InflowWind 59 RotorApexOffsetPos 0.0 0.0 0.0 RotorApexOffsetPos - Offset of the lidar from hub height (m) +InflowWind 60 URefLid 17 URefLid - Reference average wind speed for the lidar[m/s] +InflowWind 61 MeasurementInterval 0.25 MeasurementInterval - Time between each measurement [s] +InflowWind 62 LidRadialVel False LidRadialVel - TRUE => return radial component, FALSE => return 'x' direction estimate +InflowWind 63 ConsiderHubMotion 1 ConsiderHubMotion - Flag whether to consider the hub motion's impact on Lidar measurements ============================================= ==== ==================== ======================================================================================================================================================================================================== -OpenFAST v3.4.1 to OpenFAST v3.4.1 +OpenFAST v3.4.0 to OpenFAST v3.4.1 ---------------------------------- Restored the AeroDyn channel names with `Aero` in the name. These had be From 465d5a9145888fecc58755e9269960abe56fed6b Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 08:42:05 -0400 Subject: [PATCH 41/51] IfW: fix comment on Point_WindNumber --- modules/inflowwind/src/InflowWind.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index d4b117f986..144183b537 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -23,7 +23,7 @@ param ^ - IntKi HAWC_WindNu param ^ - IntKi User_WindNumber - 6 - "User defined wind." - param ^ - IntKi BladedFF_Shr_WindNumber - 7 - "Native Bladed binary full-field file." - param ^ - IntKi FDext_WindNumber - 8 - "4D wind from external souce (i.e., FAST.Farm)." - -param ^ - IntKi Point_WindNumber - 9 - "4D wind from external souce (i.e., FAST.Farm)." - +param ^ - IntKi Point_WindNumber - 9 - "1D wind components from ExtInflow" - param ^ - IntKi Highest_WindNumber - 9 - "Highest wind number supported." - param ^ - IntKi IfW_NumPtsAvg - 144 - "Number of points averaged for rotor-average wind speed" - From 3059a246f51d4147e21df33a61859c010157856e Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 15:06:58 +0000 Subject: [PATCH 42/51] Fix Grid3DField_GetCell returning NaN when Y=0 --- modules/inflowwind/src/IfW_FlowField.f90 | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index f6e7c661a5..8206ec9654 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -193,19 +193,6 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A return end if - ! Output warning if extrapolation occured - if (GridExtrap .and. (.not. FF%Grid3D%BoxExceedWarned)) then - call WrScr("WARNING from InflowWind:") - call WrScr("------------------------") - call WrScr(" Grid point extrapolated beyond bounds of full-field wind grid [position=("// & - TRIM(Num2LStr(PositionXYZ(1, i)))//", "//TRIM(Num2LStr(PositionXYZ(2, i)))//", "// & - TRIM(Num2LStr(PositionXYZ(3, i)))//") in wind-file coordinates, T="//trim(Num2LStr(Time))//"]."//NewLine// & - "This only occurs for free vortex wake points or LidarSim measurement locations. "// & - "Use a larger full-field wind grid if the simulation yields undesirable results. Further warnings are suppressed.") - call WrScr("------------------------") - FF%Grid3D%BoxExceedWarned = .true. - end if - ! Calculate velocity and acceleration if (OutputAccel) then if (FF%VelInterpCubic) then @@ -972,10 +959,11 @@ subroutine GetCellInTower(cell, gridVal, gridAvg, towerVal) integer(IntKi) :: ic, i !------------------------------------------------------------------------- - ! If extrapolation is not allowed, apply tower values to all Y positions + ! If extrapolation is not allowed or Y is nearly zero, only interpolate + ! along the tower !------------------------------------------------------------------------- - if (.not. AllowExtrap) then + if (.not. AllowExtrap .or. EqualRealNos(Position(2), 0.0_ReKi)) then if (IZ_HI <= G3D%NTGrids) then ! In tower grid cell(1, :) = towerVal(:, IZ_LO, IT_LO) cell(2, :) = towerVal(:, IZ_HI, IT_LO) @@ -1103,6 +1091,8 @@ function TriangleArea(x, y) result(A) x(3)*(y(1) - y(2)))/2.0_ReKi end function + !> GetBoundsY populates IY_Lo, IY_Hi, and the interpolant [-1,1]. It also + !! adds ExtrapYmin or ExtrapYmax to AllExtrap if applicable. subroutine GetBoundsY(PosY, DY) real(ReKi), intent(in) :: PosY @@ -1154,6 +1144,8 @@ subroutine GetBoundsY(PosY, DY) end subroutine + !> GetBoundsZ populates IZ_Lo, IZ_Hi, and the interpolant [-1,1]. It also + !! adds ExtrapZmin or ExtrapZmax to AllExtrap if applicable. subroutine GetBoundsZ(PosZ, DZ) real(ReKi), intent(in) :: PosZ @@ -1248,6 +1240,7 @@ subroutine GetBoundsZ(PosZ, DZ) end subroutine + !> GetBoundsT populates IT_Lo, IT_Hi, and the interpolant [-1,1]. subroutine GetBoundsT(PosX, DT) real(ReKi), intent(in) :: PosX From 05e999e036a6ecee3fd8926776cb7d48cd3c586c Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 15:16:13 +0000 Subject: [PATCH 43/51] IfW: Moved Y bounds checking to reduce calls --- modules/inflowwind/src/IfW_FlowField.f90 | 25 +++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index 8206ec9654..93fe841111 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -67,7 +67,6 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A real(ReKi) :: VelCell(8, 3), AccCell(8, 3) logical :: Is3D logical :: GridExceedAllow ! is this point allowed to exceed bounds of wind grid - logical :: GridExtrap ! did this point fall outside the wind box and get extrapolated? ErrStat = ErrID_None ErrMsg = "" @@ -187,7 +186,7 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A ! components at corners of grid cell containing time and position. Also ! returns interpolation values Xi. call Grid3DField_GetCell(FF%Grid3D, Time, Position(:, i), OutputAccel, GridExceedAllow, & - VelCell, AccCell, Xi, Is3D, GridExtrap, TmpErrStat, TmpErrMsg) + VelCell, AccCell, Xi, Is3D, TmpErrStat, TmpErrMsg) if (TmpErrStat >= AbortErrLev) then call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) return @@ -716,7 +715,7 @@ subroutine IfW_UniformWind_GetOP(UF, t, InterpCubic, OP_out) end subroutine subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & - VelCell, AccCell, Xi, Is3D, Extrapolated, ErrStat, ErrMsg) + VelCell, AccCell, Xi, Is3D, ErrStat, ErrMsg) type(Grid3DFieldType), intent(in) :: G3D !< 3D Grid-Field data real(DbKi), intent(in) :: Time !< time (s) @@ -727,7 +726,6 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & real(ReKi), intent(out) :: AccCell(8, 3) !< Acceleration components at corners of grid cell real(ReKi), intent(out) :: Xi(3) !< isoparametric coord of position in cell (y,z,t) [-1, +1] logical, intent(out) :: Is3D !< flag indicating if interpolation is 3D or 2D - logical, intent(inout) :: Extrapolated !< Extrapolation outside grid is allowed and point lies outside grid integer(IntKi), intent(out) :: ErrStat !< error status character(*), intent(out) :: ErrMsg !< error message @@ -761,13 +759,6 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & call GetBoundsZ(Position(3), Xi(2)) if (ErrStat >= AbortErrLev) return - ! Get grid Y bounds - call GetBoundsY(Position(2), Xi(1)) - if (ErrStat >= AbortErrLev) return - - ! Set flag indicating if extrapolation occured - Extrapolated = AllExtrap /= ExtrapNone - !---------------------------------------------------------------------------- ! Extract interpolation cells from grids based on poisiont !---------------------------------------------------------------------------- @@ -778,6 +769,10 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & ! Set flag to use 3D interpolation Is3D = .true. + ! Get grid Y bounds + call GetBoundsY(Position(2), Xi(1)) + if (ErrStat >= AbortErrLev) return + ! Interpolate within grid (or top, left, right if extrapolation enabled) call GetCellInGrid(VelCell, G3D%Vel, G3D%VelAvg) @@ -804,6 +799,10 @@ subroutine Grid3DField_GetCell(G3D, Time, Position, CalcAccel, AllowExtrap, & ! Set flag to use 3D interpolation Is3D = .true. + ! Get grid Y bounds + call GetBoundsY(Position(2), Xi(1)) + if (ErrStat >= AbortErrLev) return + ! Tower interpolation without tower grids call GetCellBelowGrid(VelCell, G3D%Vel) @@ -992,6 +991,10 @@ subroutine GetCellInTower(cell, gridVal, gridAvg, towerVal) return end if + ! Get grid Y bounds + call GetBoundsY(Position(2), Xi(1)) + if (ErrStat >= AbortErrLev) return + !------------------------------------------------------------------------- ! Otherwise, position is below grid and within +- 2*GridWidth from tower ! This section uses Barycentric interpolation between four points to get From c0fd51886f7a00dca4fb793eceb5ede93f671c23 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 15:36:32 +0000 Subject: [PATCH 44/51] Updated InflowWind docs for acceleration --- docs/source/user/inflowwind/driver.rst | 12 ++++++++++++ .../examples/inflowwind_driver_example.inp | 1 + .../inflowwind/examples/inflowwind_example.dat | 16 +++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/source/user/inflowwind/driver.rst b/docs/source/user/inflowwind/driver.rst index 8a07ed722d..f436f2203a 100644 --- a/docs/source/user/inflowwind/driver.rst +++ b/docs/source/user/inflowwind/driver.rst @@ -140,6 +140,18 @@ When converting from a full-field wind format to a uniform wind file, the follow 1. The power-law exponent specified in InflowWind (if a power law wind profile is used to add to the turbulence with native-Bladed or HAWC2 files), or 2. Calculated by using the mean wind speeds at two points: the reference (hub) height and the uppermost height on the grid. +accel flag +------------------- + +The ability to calculate the acceleration of the flow field was added to InflowWind +to support the analysis of MHK, underwater, turbines. The acceleration is needed +to calculate the mass effects of the fluid interacting with the rotor. Calculation of the +acceleration is supported for Uniform/Steady Wind and grid based wind profiles (Turbsim, +HAWC, and Bladed files). Enabling this flag causes the driver to output the flow field +acceleration for points defined in the Points file in addition to the velocities at those +same points. + + BoxExceedAllow flag ------------------- diff --git a/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp b/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp index b82594c65a..396035d1b9 100644 --- a/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp +++ b/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp @@ -17,6 +17,7 @@ InflowWind driver input file. ---- Points file input (output given as POINTSFILENAME.Velocity.dat) -------- f PointsFile -- read in a list of output points from a file (flag) "Test005.txt" PointsFileName -- name of points file (-) (comma separated x,y,z coordinates, # symbol for comments) + f CalcAccel -- calculate and output acceleration at points in addition to velocity ---- Output grid (Points below ground will simply be ignored) --------------- t WindGrid -- report wind data at set of X,Y,Z coordinat (flag) 6,0,15 GridCtrCoord -- coordinate of center of grid (m) diff --git a/docs/source/user/inflowwind/examples/inflowwind_example.dat b/docs/source/user/inflowwind/examples/inflowwind_example.dat index 1f7ee25be6..9a9aa62f59 100644 --- a/docs/source/user/inflowwind/examples/inflowwind_example.dat +++ b/docs/source/user/inflowwind/examples/inflowwind_example.dat @@ -6,6 +6,7 @@ False Echo - Echo input data to .ech (flag) 0 PropagationDir - Direction of wind propagation (meteorological rotation from aligned with X (positive rotates towards -Y) -- degrees) (not used for native Bladed format WindType=7) 0 VFlowAng - Upflow angle (degrees) (not used for native Bladed format WindType=7) 1 NWindVel - Number of points to output the wind velocity (0 to 9) + False VelInterpCubic - Use cubic interpolation for velocity in time (false=linear, true=cubic) [Used with WindType=2,3,4,5,7] 0 WindVxiList - List of coordinates in the inertial X direction (m) 0 WindVyiList - List of coordinates in the inertial Y direction (m) 90 WindVziList - List of coordinates in the inertial Z direction (m) @@ -46,7 +47,20 @@ False TowerFile - Have tower file (.twr) (flag) ignored when WindTy 2 WindProfile - Wind profile type (0=constant;1=logarithmic,2=power law) 0.2 PLExp_HAWC - Power law exponent (-) (used for PL wind profile type only) 0.03 Z0 - Surface roughness length (m) (used for LG wind profile type only) - 0 XOffset - Initial offset in +x direction (shift of wind box) + 0 XOffset - Initial offset in +x direction (shift of wind box) +================== LIDAR Parameters =========================================================================== + 0 SensorType - Switch for lidar configuration (0 = None, 1 = Single Point Beam(s), 2 = Continuous, 3 = Pulsed) + 0 NumPulseGate - Number of lidar measurement gates (used when SensorType = 3) + 30 PulseSpacing - Distance between range gates (m) (used when SensorType = 3) + 0 NumBeam - Number of lidar measurement beams (0-5)(used when SensorType = 1) + -200 FocalDistanceX - Focal distance co-ordinates of the lidar beam in the x direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m) + 0 FocalDistanceY - Focal distance co-ordinates of the lidar beam in the y direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m) + 0 FocalDistanceZ - Focal distance co-ordinates of the lidar beam in the z direction (relative to hub height) (only first coordinate used for SensorType 2 and 3) (m) +0.0 0.0 0.0 RotorApexOffsetPos - Offset of the lidar from hub height (m) + 17 URefLid - Reference average wind speed for the lidar[m/s] + 0.25 MeasurementInterval - Time between each measurement [s] + False LidRadialVel - TRUE => return radial component, FALSE => return 'x' direction estimate + 1 ConsiderHubMotion - Flag whether to consider the hub motion's impact on Lidar measurements ====================== OUTPUT ================================================== False SumPrint - Print summary data to .IfW.sum (flag) OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) From d3dfeeefec779ef94b8476e8a7ecf49dc3f8c9b4 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 17:25:34 +0000 Subject: [PATCH 45/51] IfW: final iteration of tower interpolation --- modules/inflowwind/src/IfW_FlowField.f90 | 129 ++++++++++------------- 1 file changed, 53 insertions(+), 76 deletions(-) diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index 93fe841111..1952ed20a2 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -952,17 +952,18 @@ subroutine GetCellInTower(cell, gridVal, gridAvg, towerVal) real(SiKi), intent(in), allocatable :: gridAvg(:, :, :) real(SiKi), intent(in), allocatable :: towerVal(:, :, :) - real(ReKi) :: Y(0:5), Z(0:5), W(4), Py, Pz - real(ReKi) :: V(3, 4, 2) - real(ReKi) :: alpha - integer(IntKi) :: ic, i + real(ReKi), dimension(2) :: P, P1, P2, P3, V0, V1, V2 + real(ReKi) :: d00, d01, d11, d20, d21 + real(ReKi) :: V(3, 3, 2), W(3) + real(ReKi) :: alpha, omalpha, denom + integer(IntKi) :: ic !------------------------------------------------------------------------- ! If extrapolation is not allowed or Y is nearly zero, only interpolate ! along the tower !------------------------------------------------------------------------- - if (.not. AllowExtrap .or. EqualRealNos(Position(2), 0.0_ReKi)) then + if (.not. AllowExtrap) then if (IZ_HI <= G3D%NTGrids) then ! In tower grid cell(1, :) = towerVal(:, IZ_LO, IT_LO) cell(2, :) = towerVal(:, IZ_HI, IT_LO) @@ -991,109 +992,85 @@ subroutine GetCellInTower(cell, gridVal, gridAvg, towerVal) return end if - ! Get grid Y bounds - call GetBoundsY(Position(2), Xi(1)) - if (ErrStat >= AbortErrLev) return - !------------------------------------------------------------------------- ! Otherwise, position is below grid and within +- 2*GridWidth from tower - ! This section uses Barycentric interpolation between four points to get - ! the wind components at the desired Position. - ! - ! Points are ordered counter clockwise. Points on left side of tower - ! are reflected to the right side. + ! This section uses Barycentric interpolation of a triangle to get + ! the wind components at the desired Position. The components on the + ! bottom of the grid and on the tower are interpolated to get the first + ! two points. The third point is on the ground at the GridWidth away + ! from the tower. !------------------------------------------------------------------------- - ! Point 1 (ground @ grid width away from tower) - Y(1) = 2.0_ReKi*G3D%YHWid - Z(1) = 0.0_Reki - V(:, 1, :) = 0.0_ReKi + ! Get grid Y bounds + call GetBoundsY(Position(2), Xi(1)) + if (ErrStat >= AbortErrLev) return - ! Point 2 (grid bottom point) - Y(2) = abs(Position(2)) - Z(2) = G3D%GridBase + ! Get interpolation point + P = [abs(Position(2)), Position(3)] + ! Point 1 (grid bottom point) + P1 = [abs(Position(2)), G3D%GridBase] select case (AllExtrap) case (ExtrapNone) - ! Interpolate between grid points alpha = (Xi(1) + 1.0_ReKi)/2.0_ReKi - V(:, 2, 1) = (1.0_ReKi - alpha)*gridVal(:, IY_Lo, 1, IT_Lo) + & + omalpha = 1.0_ReKi - alpha + V(:, 1, 1) = omalpha*gridVal(:, IY_Lo, 1, IT_Lo) + & alpha*gridVal(:, IY_Hi, 1, IT_Lo) - V(:, 2, 2) = (1.0_ReKi - alpha)*gridVal(:, IY_Lo, 1, IT_Hi) + & + V(:, 1, 2) = omalpha*gridVal(:, IY_Lo, 1, IT_Hi) + & alpha*gridVal(:, IY_Hi, 1, IT_Hi) - case (ExtrapYmin, ExtrapYmax) - ! Interpolate between edge of grid and grid average alpha = abs(Position(2))/G3D%YHWid - 1.0_ReKi - V(:, 2, 1) = (1.0_ReKi - alpha)*gridVal(:, IY_Lo, 1, IT_Lo) + & + omalpha = 1.0_ReKi - alpha + V(:, 1, 1) = omalpha*gridVal(:, IY_Lo, 1, IT_Lo) + & alpha*gridAvg(:, 1, IT_Lo) - V(:, 2, 2) = (1.0_ReKi - alpha)*gridVal(:, IY_Lo, 1, IT_Hi) + & + V(:, 1, 2) = omalpha*gridVal(:, IY_Lo, 1, IT_Hi) + & alpha*gridAvg(:, 1, IT_Hi) - end select - ! Point 3 (upper tower point) - Y(3) = 0.0_ReKi - Z(3) = G3D%GridBase - real(IZ_Lo - 1, ReKi)/G3D%InvDZ - V(:, 3, 1) = towerVal(:, IZ_Lo, IT_Lo) - V(:, 3, 2) = towerVal(:, IZ_Lo, IT_Hi) - - ! Point 4 (lower tower point) - Y(4) = 0.0_ReKi + ! Point 2 (tower point) + P2 = [0.0_ReKi, Position(3)] + alpha = (Xi(2) + 1.0_ReKi)/2.0_ReKi + omalpha = 1.0_ReKi - alpha if (IZ_HI <= G3D%NTGrids) then ! Lower point above ground - Z(4) = G3D%GridBase - real(IZ_Hi - 1, ReKi)/G3D%InvDZ - V(:, 4, 1) = towerVal(:, IZ_Hi, IT_Lo) - V(:, 4, 2) = towerVal(:, IZ_Hi, IT_Hi) + V(:, 2, 1) = omalpha*towerVal(:, IZ_Lo, IT_Lo) + & + alpha*towerVal(:, IZ_Hi, IT_Lo) + V(:, 2, 2) = omalpha*towerVal(:, IZ_Lo, IT_Hi) + & + alpha*towerVal(:, IZ_Hi, IT_Hi) else ! Lower point on ground - Z(4) = 0.0_ReKi - V(:, 4, :) = 0.0_ReKi + V(:, 2, 1) = omalpha*towerVal(:, IZ_Lo, IT_Lo) + V(:, 2, 2) = omalpha*towerVal(:, IZ_Lo, IT_Hi) end if - !------------------------------------------------------------------------- - ! Calculate Barycentric weights for quadrilateral - !------------------------------------------------------------------------- - - ! Get interpolation point - Py = abs(Position(2)) - Pz = Position(3) - - ! Copy start and end coords for easier indexing when calculating weights - Y(0) = Y(4) - Y(5) = Y(1) - Z(0) = Z(4) - Z(5) = Z(1) - - ! Calculate weights - do i = 1, 4 - W(i) = TriangleArea([Y(i - 1), Y(i), Y(i + 1)], [Z(i - 1), Z(i), Z(i + 1)])/ & - (TriangleArea([Py, Y(i - 1), Y(i)], [Pz, Z(i - 1), Z(i)])* & - TriangleArea([Py, Y(i), Y(i + 1)], [Pz, Z(i), Z(i + 1)])) - end do - - ! Normalize Weights so they sum to 1.0 - W = W/sum(W) + ! Point 3 (ground @ grid width away from tower) + P3 = [2.0_ReKi*G3D%YHWid, 0.0_Reki] + ! V(:, 3, :) = 0.0_ReKi ! Not used + + ! Calculate Barycentric weights for triangle + V0 = P1 - P3 + V1 = P2 - P3 + V2 = P - P3 + d00 = dot_product(v0, v0) + d01 = dot_product(v0, v1) + d11 = dot_product(v1, v1) + d20 = dot_product(v2, v0) + d21 = dot_product(v2, v1) + denom = d00*d11 - d01*d01 + W(1) = (d11*d20 - d01*d21)/denom + W(2) = (d00*d21 - d01*d20)/denom + ! W(3) = 1.0_ReKi - W(1) - W(2) ! Not used ! Interpolate wind components based on weights do ic = 1, 3 - cell(1, ic) = dot_product(V(ic, :, 1), W) - cell(3, ic) = dot_product(V(ic, :, 2), W) + cell(1, ic) = V(ic, 1, 1) * W(1) + V(ic, 2, 1) * W(2) + cell(3, ic) = V(ic, 1, 2) * W(1) + V(ic, 2, 2) * W(2) end do cell(2, :) = cell(1, :) cell(4, :) = cell(3, :) end subroutine - !> TriangleArea returns the signed area of a triangle. - function TriangleArea(x, y) result(A) - real(ReKi) :: x(3), y(3) - real(ReKi) :: A - A = (x(1)*(y(2) - y(3)) + & - x(2)*(y(3) - y(1)) + & - x(3)*(y(1) - y(2)))/2.0_ReKi - end function - !> GetBoundsY populates IY_Lo, IY_Hi, and the interpolant [-1,1]. It also !! adds ExtrapYmin or ExtrapYmax to AllExtrap if applicable. subroutine GetBoundsY(PosY, DY) From 4860bc4333fbcd6b503edce9472b773c536363aa Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 18:04:59 +0000 Subject: [PATCH 46/51] IfW put FlowField back in ParameterType, cleanup --- glue-codes/fast-farm/src/FASTWrapper.f90 | 8 +- modules/inflowwind/src/IfW_FlowField.f90 | 2 +- modules/inflowwind/src/InflowWind.f90 | 96 ++++----- modules/inflowwind/src/InflowWind.txt | 3 +- modules/inflowwind/src/InflowWind_Driver.f90 | 10 +- modules/inflowwind/src/InflowWind_IO.f90 | 178 +++++++++-------- modules/inflowwind/src/InflowWind_IO.txt | 2 +- .../inflowwind/src/InflowWind_IO_Types.f90 | 10 +- modules/inflowwind/src/InflowWind_Subs.f90 | 32 +-- modules/inflowwind/src/InflowWind_Types.f90 | 186 +++++++++--------- .../inflowwind/tests/test_uniform_wind.F90 | 12 +- 11 files changed, 280 insertions(+), 259 deletions(-) diff --git a/glue-codes/fast-farm/src/FASTWrapper.f90 b/glue-codes/fast-farm/src/FASTWrapper.f90 index 717e4e6516..903666cb48 100644 --- a/glue-codes/fast-farm/src/FASTWrapper.f90 +++ b/glue-codes/fast-farm/src/FASTWrapper.f90 @@ -184,7 +184,7 @@ SUBROUTINE FWrap_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init return end if - call move_alloc(m%Turbine%IfW%m%FlowField%Grid4D%Vel, u%Vdist_High) + call move_alloc(m%Turbine%IfW%p%FlowField%Grid4D%Vel, u%Vdist_High) !................. @@ -556,7 +556,7 @@ SUBROUTINE FWrap_CalcOutput(p, u, y, m, ErrStat, ErrMsg) ErrMsg = '' ! put this back! - call move_alloc(m%Turbine%IfW%m%FlowField%Grid4D%Vel, u%Vdist_High) + call move_alloc(m%Turbine%IfW%p%FlowField%Grid4D%Vel, u%Vdist_High) ! Turbine-dependent commands to the super controller: @@ -712,8 +712,8 @@ SUBROUTINE FWrap_SetInputs(u, m, t) REAL(DbKi), INTENT(IN ) :: t !< current simulation time ! set the 4d-wind-inflow input array (a bit of a hack [simplification] so that we don't have large amounts of data copied in multiple data structures): - call move_alloc(u%Vdist_High, m%Turbine%IfW%m%FlowField%Grid4D%Vel) - m%Turbine%IfW%m%FlowField%Grid4D%TimeStart = t + call move_alloc(u%Vdist_High, m%Turbine%IfW%p%FlowField%Grid4D%Vel) + m%Turbine%IfW%p%FlowField%Grid4D%TimeStart = t ! do something with the inputs from the super-controller: if ( m%Turbine%p_FAST%UseSC ) then diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90 index 1952ed20a2..5bcc3bfee4 100644 --- a/modules/inflowwind/src/IfW_FlowField.f90 +++ b/modules/inflowwind/src/IfW_FlowField.f90 @@ -42,7 +42,7 @@ module IfW_FlowField !! Accelerations are only calculated if the AccelUVW array is allocated. subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, AccelUVW, ErrStat, ErrMsg) - type(FlowFieldType), intent(inout) :: FF !< FlowField data structure + type(FlowFieldType), intent(in) :: FF !< FlowField data structure integer(IntKi), intent(in) :: IStart !< Start index for returning velocities for external field real(DbKi), intent(in) :: Time !< Time to evaluate velocities/accelerations real(ReKi), intent(in) :: PositionXYZ(:, :) !< Array of positions to evaluate velocites/accelerations diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90 index bb0a0f6bef..4534424e51 100644 --- a/modules/inflowwind/src/InflowWind.f90 +++ b/modules/inflowwind/src/InflowWind.f90 @@ -300,8 +300,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons Steady_InitInput%RefHt = InputFileData%Steady_RefHt Steady_InitInput%PLExp = InputFileData%Steady_PLexp - m%FlowField%FieldType = Uniform_FieldType - call IfW_SteadyWind_Init(Steady_InitInput, SumFileUnit, m%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) + p%FlowField%FieldType = Uniform_FieldType + call IfW_SteadyWind_Init(Steady_InitInput, SumFileUnit, p%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -317,8 +317,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons Uniform_InitInput%UseInputFile = InitInp%WindType2UseInputFile Uniform_InitInput%PassedFileData = InitInp%WindType2Data - m%FlowField%FieldType = Uniform_FieldType - call IfW_UniformWind_Init(Uniform_InitInput, SumFileUnit, m%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) + p%FlowField%FieldType = Uniform_FieldType + call IfW_UniformWind_Init(Uniform_InitInput, SumFileUnit, p%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -329,8 +329,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons TurbSim_InitInput%WindFileName = InputFileData%TSFF_FileName - m%FlowField%FieldType = Grid3D_FieldType - call IfW_TurbSim_Init(TurbSim_InitInput, SumFileUnit, m%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + p%FlowField%FieldType = Grid3D_FieldType + call IfW_TurbSim_Init(TurbSim_InitInput, SumFileUnit, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -352,8 +352,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons Bladed_InitInput%TowerFileExist = InputFileData%BladedFF_TowerFile Bladed_InitInput%NativeBladedFmt = .false. - m%FlowField%FieldType = Grid3D_FieldType - call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, m%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + p%FlowField%FieldType = Grid3D_FieldType + call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -368,8 +368,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons Bladed_InitInput%TowerFileExist = .false. Bladed_InitInput%NativeBladedFmt = .true. - m%FlowField%FieldType = Grid3D_FieldType - call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, m%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + p%FlowField%FieldType = Grid3D_FieldType + call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -401,8 +401,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons HAWC_InitInput%G3D%Z0 = InputFileData%FF%Z0 HAWC_InitInput%G3D%XOffset = InputFileData%FF%XOffset - m%FlowField%FieldType = Grid3D_FieldType - call IfW_HAWC_Init(HAWC_InitInput, SumFileUnit, m%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) + p%FlowField%FieldType = Grid3D_FieldType + call IfW_HAWC_Init(HAWC_InitInput, SumFileUnit, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -411,8 +411,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons case (User_WindNumber) - m%FlowField%FieldType = User_FieldType - call IfW_User_Init(User_InitInput, SumFileUnit, m%FlowField%User, FileDat, TmpErrStat, TmpErrMsg) + p%FlowField%FieldType = User_FieldType + call IfW_User_Init(User_InitInput, SumFileUnit, p%FlowField%User, FileDat, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) then call Cleanup() @@ -421,16 +421,22 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons case (FDext_WindNumber) - m%FlowField%FieldType = Grid4D_FieldType - call IfW_Grid4D_Init(InitInp%FDext, m%FlowField%Grid4D, FileDat, TmpErrStat, TmpErrMsg) + p%FlowField%FieldType = Grid4D_FieldType + call IfW_Grid4D_Init(InitInp%FDext, p%FlowField%Grid4D, TmpErrStat, TmpErrMsg) if (ErrStat >= AbortErrLev) then call Cleanup() return endif - ! case (Point_WindNumber) + case (Point_WindNumber) - ! m%FlowField%FieldType = Point_FieldType + p%FlowField%FieldType = Point_FieldType + Points_InitInput%NumWindPoints = InitInp%NumWindPoints + call IfW_Points_Init(Points_InitInput, p%FlowField%Points, TmpErrStat, TmpErrMsg) + if (ErrStat >= AbortErrLev) then + call Cleanup() + return + endif case default call SetErrStat(ErrID_Fatal, ' Undefined wind type.', ErrStat, ErrMsg, RoutineName) @@ -442,50 +448,50 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons !---------------------------------------------------------------------------- ! Reset flag indicating that acceleration field is valid - m%FlowField%AccFieldValid = .false. + p%FlowField%AccFieldValid = .false. ! Copy flag for enabling cubic velocity interpolation - m%FlowField%VelInterpCubic = InputFileData%VelInterpCubic + p%FlowField%VelInterpCubic = InputFileData%VelInterpCubic ! If cubic velocity interpolation requested and linearization is performed, ! display message that cubic interpolation is incompatible with linearization ! and will be disabled - if (m%FlowField%VelInterpCubic .and. InitInp%Linearize) then + if (p%FlowField%VelInterpCubic .and. InitInp%Linearize) then call WrScr("InflowWind: Cubic interpolation of wind velocity is disabled for linearization") - m%FlowField%VelInterpCubic = .false. + p%FlowField%VelInterpCubic = .false. end if ! Set box exceed flag and index - m%FlowField%Grid3D%BoxExceedAllowF = InitInp%BoxExceedAllowF - m%FlowField%Grid3D%BoxExceedAllowIdx = huge(1_IntKi) + p%FlowField%Grid3D%BoxExceedAllowF = InitInp%BoxExceedAllowF + p%FlowField%Grid3D%BoxExceedAllowIdx = huge(1_IntKi) if (InitInp%BoxExceedAllowF .and. (InitInp%BoxExceedAllowIdx <= InitInp%NumWindPoints)) then - m%FlowField%Grid3D%BoxExceedAllowIdx = InitInp%BoxExceedAllowIdx + p%FlowField%Grid3D%BoxExceedAllowIdx = InitInp%BoxExceedAllowIdx end if ! Select based on field type - select case (m%FlowField%FieldType) + select case (p%FlowField%FieldType) case (Uniform_FieldType) - if (InitInp%OutputAccel .or. m%FlowField%VelInterpCubic) then - call IfW_UniformField_CalcAccel(m%FlowField%Uniform, TmpErrStat, TmpErrMsg) + if (InitInp%OutputAccel .or. p%FlowField%VelInterpCubic) then + call IfW_UniformField_CalcAccel(p%FlowField%Uniform, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return - m%FlowField%AccFieldValid = .true. + p%FlowField%AccFieldValid = .true. end if case (Grid3D_FieldType) ! Calculate acceleration - if (InitInp%OutputAccel .or. m%FlowField%VelInterpCubic) then - call IfW_Grid3DField_CalcAccel(m%FlowField%Grid3D, TmpErrStat, TmpErrMsg) + if (InitInp%OutputAccel .or. p%FlowField%VelInterpCubic) then + call IfW_Grid3DField_CalcAccel(p%FlowField%Grid3D, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return - m%FlowField%AccFieldValid = .true. + p%FlowField%AccFieldValid = .true. end if ! Calculate field average if box is allowed to be exceeded - if (m%FlowField%Grid3D%BoxExceedAllowF .and. m%FlowField%Grid3D%BoxExceedAllowIdx > 0) then - call IfW_Grid3DField_CalcVelAvgProfile(m%FlowField%Grid3D, m%FlowField%AccFieldValid, TmpErrStat, TmpErrMsg) + if (p%FlowField%Grid3D%BoxExceedAllowF .and. p%FlowField%Grid3D%BoxExceedAllowIdx > 0) then + call IfW_Grid3DField_CalcVelAvgProfile(p%FlowField%Grid3D, p%FlowField%AccFieldValid, TmpErrStat, TmpErrMsg) call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return end if @@ -493,13 +499,13 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons case default if (InitInp%OutputAccel) then call SetErrStat(ErrID_Fatal, "Acceleration not implemented for field type "// & - num2LStr(m%FlowField%FieldType), ErrStat, ErrMsg, RoutineName) + num2LStr(p%FlowField%FieldType), ErrStat, ErrMsg, RoutineName) return end if - if (m%FlowField%VelInterpCubic) then + if (p%FlowField%VelInterpCubic) then call WrScr(' Cubic velocity interpolation not implemented for WindType '// & num2LStr(InputFileData%WindType)) - m%FlowField%VelInterpCubic = .false. + p%FlowField%VelInterpCubic = .false. end if end select @@ -551,8 +557,8 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons ! If field is uniform and there is any nonzero upflow, return error ! Math needs work before this can be implemented - if (m%FlowField%FieldType == Uniform_FieldType) then - if (any(m%FlowField%Uniform%AngleV /= 0.0_ReKi)) then + if (p%FlowField%FieldType == Uniform_FieldType) then + if (any(p%FlowField%Uniform%AngleV /= 0.0_ReKi)) then call SetErrStat(ErrID_Fatal, 'Upflow in uniform wind files must be 0 for linearization analysis in InflowWind.', ErrStat, ErrMsg, RoutineName) call Cleanup() return @@ -995,10 +1001,10 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt n = SIZE(u%PositionXYZ,2) ! these are the positions used in the module coupling do i=1,n - ! note that m%FlowField%RotToWind(1,1) = cos(p%PropagationDir) and m%FlowField%RotToWind(2,1) = sin(p%PropagationDir), which are the + ! note that p%FlowField%RotToWind(1,1) = cos(p%PropagationDir) and p%FlowField%RotToWind(2,1) = sin(p%PropagationDir), which are the ! values we need to compute the jacobian. !!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput( m%FlowField%Uniform, t, u%PositionXYZ(:,i), m%FlowField%RotToWind(1,1), m%FlowField%RotToWind(2,1), local_dYdu ) + call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, u%PositionXYZ(:,i), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) i_end = 3*i i_start= i_end - 2 @@ -1021,7 +1027,7 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt do i=1,IfW_NumPtsAvg m%u_Avg%PositionXYZ(:,i) = matmul(u%HubOrientation,p%PositionAvg(:,i)) + u%HubPosition !!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput( m%FlowField%Uniform, t, m%u_Avg%PositionXYZ(:,i), m%FlowField%RotToWind(1,1), m%FlowField%RotToWind(2,1), local_dYdu ) + call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, m%u_Avg%PositionXYZ(:,i), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) ! y%DiskAvg has the same index as u%HubPosition ! Also note that partial_(m%u_Avg%PositionXYZ) / partial_(u%HubPosition) is identity, so we can skip that part of the chain rule for these derivatives: @@ -1043,7 +1049,7 @@ SUBROUTINE InflowWind_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrSt if (node > 0) then !!!FIX ME with the propagation values!!!! - call IfW_UniformWind_JacobianPInput( m%FlowField%Uniform, t, p%WindViXYZ(:,node), m%FlowField%RotToWind(1,1), m%FlowField%RotToWind(2,1), local_dYdu ) + call IfW_UniformWind_JacobianPInput( p%FlowField%Uniform, t, p%WindViXYZ(:,node), p%FlowField%RotToWind(1,1), p%FlowField%RotToWind(2,1), local_dYdu ) else local_dYdu = 0.0_R8Ki comp = 1 @@ -1468,8 +1474,8 @@ SUBROUTINE InflowWind_GetOP( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMs u_op((index+1):(index+3)) = EulerExtract(u%HubOrientation) index = index + 3 - call IfW_UniformWind_GetOP( m%FlowField%Uniform, t, m%FlowField%VelInterpCubic, u_op(index+1:index+2) ) - u_op(index + 3) = m%FlowField%PropagationDir + call IfW_UniformWind_GetOP( p%FlowField%Uniform, t, p%FlowField%VelInterpCubic, u_op(index+1:index+2) ) + u_op(index + 3) = p%FlowField%PropagationDir END IF diff --git a/modules/inflowwind/src/InflowWind.txt b/modules/inflowwind/src/InflowWind.txt index 144183b537..4231273e3c 100644 --- a/modules/inflowwind/src/InflowWind.txt +++ b/modules/inflowwind/src/InflowWind.txt @@ -121,7 +121,7 @@ typedef ^ ^ IntKi WindType typedef ^ ^ DbKi DT - - - "Time step for cont. state integration & disc. state update" seconds typedef ^ ^ ReKi WindViXYZprime :: - - "List of XYZ coordinates for velocity measurements, translated to the wind coordinate system (prime coordinates). This equals MATMUL( RotToWind, ParamData%WindViXYZ )" meters typedef ^ ^ ReKi WindViXYZ :: - - "List of XYZ coordinates for wind velocity measurements, 3xNWindVel" meters - +typedef ^ ^ FlowFieldType FlowField - - - "Parameters from Full-Field" - typedef ^ ^ ReKi PositionAvg :: - - "(non-rotated) positions of points used for averaging wind speed" meters typedef ^ ^ ReKi ReferenceHeight - - - "Height of the wind turbine" meters typedef ^ ^ ReKi RefPosition 3 - - "Reference position (point where box is rotated)" meters @@ -163,7 +163,6 @@ typedef ^ OtherStateType ReKi DummyOtherS typedef ^ MiscVarType ReKi AllOuts : - - "An array holding the value of all of the calculated (not only selected) output channels" "see OutListParameters.xlsx spreadsheet" typedef ^ ^ ReKi WindViUVW :: - - "List of UVW velocities for wind velocity measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ" meters/second typedef ^ ^ ReKi WindAiUVW :: - - "List of UVW accelerations for wind acceleration measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ" m/s^2 -typedef ^ ^ FlowFieldType FlowField - - - "Parameters from Full-Field" - typedef ^ ^ InflowWind_InputType u_Avg - - - "inputs for computing rotor-averaged values" - typedef ^ ^ InflowWind_OutputType y_Avg - - - "outputs for computing rotor-averaged values" - typedef ^ ^ InflowWind_InputType u_Hub - - - "inputs for computing hub values" - diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index 49ec583998..2456f29d4d 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -449,7 +449,7 @@ PROGRAM InflowWind_Driver ! Convert InflowWind file to HAWC format IF (SettingsFlags%WrHAWC) THEN - CALL IfW_WriteHAWC( InflowWind_MiscVars%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) + CALL IfW_WriteHAWC( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN @@ -466,7 +466,7 @@ PROGRAM InflowWind_Driver ! Convert InflowWind file to Native Bladed format IF (SettingsFlags%WrBladed) THEN - CALL IfW_WriteBladed( InflowWind_MiscVars%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) + CALL IfW_WriteBladed( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN @@ -481,7 +481,7 @@ PROGRAM InflowWind_Driver END IF IF (SettingsFlags%WrVTK) THEN - CALL IfW_WriteVTK( InflowWind_MiscVars%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) + CALL IfW_WriteVTK( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN @@ -498,7 +498,7 @@ PROGRAM InflowWind_Driver IF (SettingsFlags%WrUniform) THEN - CALL IfW_WriteUniform( InflowWind_MiscVars%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) + CALL IfW_WriteUniform( InflowWind_p%FlowField, InflowWind_InitInp%RootName, ErrStat, ErrMsg ) IF (ErrStat > ErrID_None) THEN CALL WrScr( TRIM(ErrMsg) ) IF ( ErrStat >= AbortErrLev ) THEN @@ -711,7 +711,7 @@ PROGRAM InflowWind_Driver ! Report the rotation of the coordinates. IF ( IfWDriver_Verbose >= 10_IntKi .and. InflowWind_p%NumOuts > 0 ) THEN CALL WrScr(NewLine//NewLine//' Rotation of coordinates to prime (wind file) coordinates by rotating '// & - TRIM(Num2LStr(R2D*InflowWind_MiscVars%FlowField%PropagationDir))// & + TRIM(Num2LStr(R2D*InflowWind_p%FlowField%PropagationDir))// & ' degrees (meteorological wind direction change) ...'//NewLine) if (InflowWind_p%NWindVel > 0_IntKi) then CALL WrScr(' ------ WindViXYZ --------- ----- WindViXYZprime -----') diff --git a/modules/inflowwind/src/InflowWind_IO.f90 b/modules/inflowwind/src/InflowWind_IO.f90 index e68e888de3..c7f0b5471d 100644 --- a/modules/inflowwind/src/InflowWind_IO.f90 +++ b/modules/inflowwind/src/InflowWind_IO.f90 @@ -26,9 +26,20 @@ module InflowWind_IO implicit none private -public :: IfW_SteadyWind_Init, IfW_UniformWind_Init, IfW_TurbSim_Init, IfW_Bladed_Init, & - IfW_HAWC_Init, IfW_User_Init, IfW_Grid4D_Init -public :: Uniform_WriteHH, Grid3D_WriteBladed, Grid3D_WriteHAWC, Grid3D_WriteVTK + +public :: IfW_SteadyWind_Init, & + IfW_UniformWind_Init, & + IfW_TurbSim_Init, & + IfW_Bladed_Init, & + IfW_HAWC_Init, & + IfW_User_Init, & + IfW_Grid4D_Init, & + IfW_Points_Init + +public :: Uniform_WriteHH, & + Grid3D_WriteBladed, & + Grid3D_WriteHAWC, & + Grid3D_WriteVTK type(ProgDesc), parameter :: InflowWind_IO_Ver = ProgDesc('InflowWind_IO', '', '') @@ -38,16 +49,34 @@ module InflowWind_IO contains +subroutine IfW_Points_Init(InitInp, PF, ErrStat, ErrMsg) + type(Points_InitInputType), intent(in) :: InitInp + type(PointsFieldType), intent(out) :: PF + integer(IntKi), intent(out) :: ErrStat + character(*), intent(out) :: ErrMsg + + character(*), parameter :: RoutineName = 'IfW_Points_Init' + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg + + ! UVW components at points + call AllocAry(PF%Vel, 3, InitInp%NumWindPoints, & + 'Point Velocity Array', TmpErrStat, TmpErrMsg) + call SetErrStat(ErrStat, ErrMsg, TmpErrStat, TmpErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + +end subroutine + !> IfW_SteadyWind_Init initializes a Uniform field with with one set of values. subroutine IfW_SteadyWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) - type(Steady_InitInputType), intent(in) :: InitInp + type(Steady_InitInputType), intent(in) :: InitInp integer(IntKi), intent(in) :: SumFileUnit type(UniformFieldType), intent(out) :: UF type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = 'SteadyWind_ReadFile' + character(*), parameter :: RoutineName = 'IfW_SteadyWind_Init' integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg @@ -128,7 +157,7 @@ subroutine IfW_UniformWind_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrM integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = 'UniformWind_ReadFile' + character(*), parameter :: RoutineName = 'IfW_UniformWind_Init' integer(IntKi), parameter :: MaxNumCols = 9 integer(IntKi), parameter :: MaxTries = 100 integer(IntKi) :: NumCols @@ -447,7 +476,7 @@ subroutine IfW_TurbSim_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = "TurbSim_Init" + character(*), parameter :: RoutineName = "IfW_TurbSim_Init" integer(IntKi) :: WindFileUnit integer(B2Ki), allocatable :: VelRaw(:, :, :) ! raw grid-field velocity data at one time step integer(B2Ki), allocatable :: TwrRaw(:, :) ! raw towrer velocity data at one time step @@ -746,7 +775,7 @@ subroutine IfW_HAWC_Init(InitInp, SumFileUnit, G3D, FileDat, ErrStat, ErrMsg) integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = "Read_HAWC" + character(*), parameter :: RoutineName = "IfW_HAWC_Init" integer(IntKi) :: WindFileUnit real(SiKi), allocatable :: VelRaw(:, :) ! grid-field data for one timestep integer :: IC ! Loop counter for the number of wind components @@ -968,7 +997,7 @@ subroutine IfW_User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = "User_Init" + character(*), parameter :: RoutineName = "IfW_User_Init" ErrStat = ErrID_None ErrMsg = "" @@ -981,16 +1010,15 @@ subroutine IfW_User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg) end subroutine -!> Grid4D_Init initializes a wind field defined by a 4D grid. -subroutine IfW_Grid4D_Init(InitInp, G4D, FileDat, ErrStat, ErrMsg) +!> IfW_Grid4D_Init initializes a wind field defined by a 4D grid. +subroutine IfW_Grid4D_Init(InitInp, G4D, ErrStat, ErrMsg) type(Grid4D_InitInputType), intent(in) :: InitInp type(Grid4DFieldType), intent(out) :: G4D - type(WindFileDat), intent(out) :: FileDat integer(IntKi), intent(out) :: ErrStat character(*), intent(out) :: ErrMsg - character(*), parameter :: RoutineName = "Grid4D_Init" + character(*), parameter :: RoutineName = "IfW_Grid4D_Init" integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg @@ -1024,7 +1052,7 @@ subroutine IfW_Bladed_Init(InitInp, SumFileUnit, InitOut, G3D, FileDat, ErrStat, integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered character(*), intent(out) :: ErrMsg !< Message about errors - character(*), parameter :: RoutineName = "Bladed_Init" + character(*), parameter :: RoutineName = "IfW_Bladed_Init" real(ReKi) :: TI(3) ! turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI type(Grid3D_InitInputType) :: G3D_InitInp ! initialization input for grid 3d field real(ReKi) :: BinTI(3) ! turbulence intensities of the wind components as defined in the FF binary file, not necessarially the actual TI @@ -1391,38 +1419,29 @@ end subroutine IfW_Bladed_Init subroutine Bladed_ReadTurbSimSummary(UnitWind, FileName, CWise, ZCenter, TI, UBar, RefHt, Periodic, LHR, ErrStat, ErrMsg) - character(*), parameter :: RoutineName = "Bladed_ReadTurbSimSummary" - - ! Passed variables - integer(IntKi), intent(in) :: UnitWind !< unit number for the file to open - character(*), intent(in) :: FileName !< name of the summary file - logical, intent(out) :: CWise !< rotation (for reading the order of the binary data) - real(ReKi), intent(out) :: ZCenter !< the height at the center of the grid - real(ReKi), intent(out) :: TI(3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI - real(ReKi), intent(out) :: UBar !< mean (advection) wind speed - real(ReKi), intent(out) :: RefHt !< Reference height - logical, intent(out) :: Periodic !< rotation (for reading the order of the binary data) - logical, intent(out) :: LHR !< Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) - integer(IntKi), intent(out) :: ErrStat !< returns 0 if no error encountered in the subroutine - character(*), intent(out) :: ErrMsg !< holds the error messages - - ! Local variables - real(ReKi) :: ZGOffset ! The vertical offset of the turbine on rectangular grid (allows turbulence not centered on turbine hub) - - integer, parameter :: NumStrings = 7 ! number of strings to be looking for in the file - - integer(IntKi) :: FirstIndx ! The first character of a line where data is located - integer(IntKi) :: I ! A loop counter - integer(IntKi) :: LastIndx ! The last character of a line where data is located - integer(IntKi) :: LineCount ! Number of lines that have been read in the file - - logical :: StrNeeded(NumStrings) ! if the string has been found - - character(1024) :: LINE ! temporary storage for reading a line from the file - - ! Temporary variables for error handling - integer(IntKi) :: TmpErrStat ! temporary error status - character(ErrMsgLen) :: TmpErrMsg ! temporary error message + integer(IntKi), intent(in) :: UnitWind !< unit number for the file to open + character(*), intent(in) :: FileName !< name of the summary file + logical, intent(out) :: CWise !< rotation (for reading the order of the binary data) + real(ReKi), intent(out) :: ZCenter !< the height at the center of the grid + real(ReKi), intent(out) :: TI(3) !< turbulence intensities of the wind components as defined in the FF file, not necessarially the actual TI + real(ReKi), intent(out) :: UBar !< mean (advection) wind speed + real(ReKi), intent(out) :: RefHt !< Reference height + logical, intent(out) :: Periodic !< rotation (for reading the order of the binary data) + logical, intent(out) :: LHR !< Left-hand rule for Bladed files (is the v component aligned along *negative* Y?) + integer(IntKi), intent(out) :: ErrStat !< returns 0 if no error encountered in the subroutine + character(*), intent(out) :: ErrMsg !< holds the error messages + + character(*), parameter :: RoutineName = "Bladed_ReadTurbSimSummary" + integer(IntKi) :: TmpErrStat ! temporary error status + character(ErrMsgLen) :: TmpErrMsg ! temporary error message + real(ReKi) :: ZGOffset ! The vertical offset of the turbine on rectangular grid (allows turbulence not centered on turbine hub) + integer, parameter :: NumStrings = 7 ! number of strings to be looking for in the file + integer(IntKi) :: FirstIndx ! The first character of a line where data is located + integer(IntKi) :: I ! A loop counter + integer(IntKi) :: LastIndx ! The last character of a line where data is located + integer(IntKi) :: LineCount ! Number of lines that have been read in the file + logical :: StrNeeded(NumStrings) ! if the string has been found + character(1024) :: LINE ! temporary storage for reading a line from the file !---------------------------------------------------------------------------------------------- ! Initialize some variables @@ -1669,19 +1688,19 @@ subroutine Bladed_ReadNativeSummary(FileName, PLExp, VLinShr, HLinShr, RefLength character(*), intent(out) :: ErrMsg !< holds the error messages character(*), parameter :: RoutineName = "Bladed_ReadNativeSummary" - integer(IntKi), parameter :: UnEc = -1 ! echo file unit number (set to something else > 0 for debugging) - integer(IntKi) :: CurLine ! Current line to parse in FileInfo data structure integer(IntKi) :: ErrStat2 ! temporary error status character(ErrMsgLen) :: ErrMsg2 ! temporary error message + integer(IntKi), parameter :: UnEc = -1 ! echo file unit number (set to something else > 0 for debugging) + integer(IntKi) :: CurLine ! Current line to parse in FileInfo data structure type(FileInfoType) :: FileInfo ! The derived type for holding the file information. ErrStat = ErrID_None ErrMsg = '' -!---------------------------------------------------------------------------- -! Open and read the summary file; store data in FileInfo structure. -!---------------------------------------------------------------------------- + !---------------------------------------------------------------------------- + ! Open and read the summary file; store data in FileInfo structure. + !---------------------------------------------------------------------------- call ProcessComFile(FileName, FileInfo, ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -1690,9 +1709,9 @@ subroutine Bladed_ReadNativeSummary(FileName, PLExp, VLinShr, HLinShr, RefLength return end if -!---------------------------------------------------------------------------- -! Process the lines stored in FileInfo -!---------------------------------------------------------------------------- + !---------------------------------------------------------------------------- + ! Process the lines stored in FileInfo + !---------------------------------------------------------------------------- CurLine = 1 @@ -1750,9 +1769,9 @@ subroutine Bladed_ReadNativeSummary(FileName, PLExp, VLinShr, HLinShr, RefLength XOffset = 0.0_ReKi ! this will be the default if offset is not in the file end if -!---------------------------------------------------------------------------- -! Clean FileInfo data structure (including pointers and allocatable arrays) -!---------------------------------------------------------------------------- + !---------------------------------------------------------------------------- + ! Clean FileInfo data structure (including pointers and allocatable arrays) + !---------------------------------------------------------------------------- call Cleanup() @@ -1765,9 +1784,9 @@ end subroutine Cleanup end subroutine Bladed_ReadNativeSummary !> Reads the binary headers from the turbulence files of the old Bladed variety. Note that - !! because of the normalization, neither ParamData%FF%NZGrids or ParamData%FF%NYGrids are larger than 32 points. - !! 21-Sep-2009 - B. Jonkman, NREL/NWTC. - !! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 +!! because of the normalization, neither ParamData%FF%NZGrids or ParamData%FF%NYGrids are larger than 32 points. +!! 21-Sep-2009 - B. Jonkman, NREL/NWTC. +!! 16-Apr-2013 - A. Platt, NREL. Converted to modular framework. Modified for NWTC_Library 2.0 subroutine Bladed_ReadHeader0(WindFileUnit, G3D, NativeBladedFmt, ErrStat, ErrMsg) integer(IntKi), intent(in) :: WindFileUnit !< unit number of already-opened wind file @@ -2034,13 +2053,13 @@ subroutine Bladed_ReadGrids(UnitWind, NativeBladedFmt, CWise, LHR, TI, G3D, ErrS character(*), intent(out) :: ErrMsg !< error message character(*), parameter :: RoutineName = "Bladed_ReadGrids" + integer(IntKi) :: TmpErrStat + character(ErrMsgLen) :: TmpErrMsg real(ReKi) :: FF_Scale(3) !< used for "un-normalizing" the data real(ReKi) :: FF_Offset(3) !< used for "un-normalizing" the data integer(B2Ki), allocatable :: raw_ff(:, :, :) integer(IntKi) :: CFirst, CLast, CStep integer(IntKi) :: IC, IR, IT - integer(IntKi) :: TmpErrStat - character(ErrMsgLen) :: TmpErrMsg ErrMsg = "" ErrStat = ErrID_None @@ -2188,14 +2207,14 @@ subroutine Bladed_ReadTower(UnitWind, G3D, TwrFileName, ErrStat, ErrMsg) end type character(*), parameter :: RoutineName = "Bladed_ReadTower" + integer(IntKi) :: TmpErrStat ! IOSTAT value. + character(ErrMsgLen) :: TmpErrMsg real(ReKi), parameter :: FF_Offset(3) = (/1.0, 0.0, 0.0/) ! used for "un-normalizing" the data real(ReKi), parameter :: TOL = 1E-4 ! tolerence for wind file comparisons integer(IntKi) :: IC, IT ! loop counters real(SiKi) :: TI(3) ! scaling values for "un-normalizing the data" [approx. turbulence intensities of the wind components] integer(B2Ki), allocatable :: raw_twr(:, :) ! holds tower velocity for one timestep type(HeaderType) :: header - integer(IntKi) :: TmpErrStat ! IOSTAT value. - character(ErrMsgLen) :: TmpErrMsg ErrMsg = '' ErrStat = ErrID_None @@ -2343,11 +2362,11 @@ end subroutine Bladed_ReadTower subroutine Grid3D_PopulateWindFileDat(Grid3DField, FileName, WindType, HasTower, FileDat) - type(Grid3DFieldType), intent(in) :: Grid3DField - character(*), intent(in) :: FileName - integer(IntKi), intent(in) :: WindType - logical, intent(in) :: HasTower - type(WindFileDat), intent(out) :: FileDat + type(Grid3DFieldType), intent(in) :: Grid3DField + character(*), intent(in) :: FileName + integer(IntKi), intent(in) :: WindType + logical, intent(in) :: HasTower + type(WindFileDat), intent(out) :: FileDat FileDat%FileName = FileName FileDat%WindType = WindType @@ -2388,14 +2407,14 @@ subroutine Grid3D_PopulateWindFileDat(Grid3DField, FileName, WindType, HasTower, subroutine Grid3D_AddMeanVelocity(InitInp, G3D) - type(Grid3D_InitInputType), intent(in) :: InitInp !< Initialization input data passed to the module - type(Grid3DFieldType), intent(inout) :: G3D !< Initialization input data passed to the module + type(Grid3D_InitInputType), intent(in) :: InitInp !< Initialization input data passed to the module + type(Grid3DFieldType), intent(inout) :: G3D !< Initialization input data passed to the module - real(ReKi) :: Z ! height - real(ReKi) :: Y ! distance from centre in horizontal direction - real(ReKi) :: U ! mean wind speed - integer(IntKi) :: iz, iy ! loop counter - integer(IntKi) :: centre_y ! index of centre in y direction + real(ReKi) :: Z ! height + real(ReKi) :: Y ! distance from centre in horizontal direction + real(ReKi) :: U ! mean wind speed + integer(IntKi) :: iz, iy ! loop counter + integer(IntKi) :: centre_y ! index of centre in y direction ! Loop through grid elevations do iz = 1, G3D%NZGrids @@ -2459,10 +2478,7 @@ subroutine Grid3D_ScaleTurbulence(InitInp, Vel, ScaleFactors, ErrStat, ErrMsg) integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered character(*), intent(out) :: ErrMsg !< Message about errors - ! Local Variables: - ! note that the variables used to compute statistics use double precision: - character(*), parameter :: RoutineName = 'ScaleTurbulence' - real(DbKi) :: v(3) ! instanteanous wind speed at target position + character(*), parameter :: RoutineName = 'Grid3D_ScaleTurbulence' real(DbKi) :: vMean(3) ! average wind speeds over time at target position real(DbKi) :: vSum(3) ! sum over time of wind speeds at target position real(DbKi) :: vSum2(3) ! sum of wind speeds squared @@ -2542,7 +2558,7 @@ subroutine Grid3D_ValidateInput(InitInp, NComp, ErrStat, ErrMsg) type(Grid3D_InitInputType), intent(in) :: InitInp !< Initialization input data passed to the module integer(IntKi), intent(in) :: NComp !< number of full-field wind components (normally 3) - character(*), parameter :: RoutineName = 'Grid3DField_ValidateInput' + character(*), parameter :: RoutineName = 'Grid3D_ValidateInput' integer(IntKi), intent(out) :: ErrStat !< determines if an error has been encountered character(*), intent(out) :: ErrMsg !< Message about errors diff --git a/modules/inflowwind/src/InflowWind_IO.txt b/modules/inflowwind/src/InflowWind_IO.txt index a6d825bde9..5d6c60e59b 100644 --- a/modules/inflowwind/src/InflowWind_IO.txt +++ b/modules/inflowwind/src/InflowWind_IO.txt @@ -89,4 +89,4 @@ typedef ^ ^ ReKi delta typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m" #---------------------------------------------------------------------------------------------------------------------------------- -typedef ^ Points_InitInputType IntKi Dummy - - - "Point field initialization input dummy value" - +typedef ^ Points_InitInputType IntKi NumWindPoints - - - "Number of points where wind components will be provided" - diff --git a/modules/inflowwind/src/InflowWind_IO_Types.f90 b/modules/inflowwind/src/InflowWind_IO_Types.f90 index a486af7d63..4409b9804d 100644 --- a/modules/inflowwind/src/InflowWind_IO_Types.f90 +++ b/modules/inflowwind/src/InflowWind_IO_Types.f90 @@ -136,7 +136,7 @@ MODULE InflowWind_IO_Types ! ======================= ! ========= Points_InitInputType ======= TYPE, PUBLIC :: Points_InitInputType - INTEGER(IntKi) :: Dummy !< Point field initialization input dummy value [-] + INTEGER(IntKi) :: NumWindPoints !< Number of points where wind components will be provided [-] END TYPE Points_InitInputType ! ======================= CONTAINS @@ -2082,7 +2082,7 @@ SUBROUTINE InflowWind_IO_CopyPoints_InitInputType( SrcPoints_InitInputTypeData, ! ErrStat = ErrID_None ErrMsg = "" - DstPoints_InitInputTypeData%Dummy = SrcPoints_InitInputTypeData%Dummy + DstPoints_InitInputTypeData%NumWindPoints = SrcPoints_InitInputTypeData%NumWindPoints END SUBROUTINE InflowWind_IO_CopyPoints_InitInputType SUBROUTINE InflowWind_IO_DestroyPoints_InitInputType( Points_InitInputTypeData, ErrStat, ErrMsg, DEALLOCATEpointers ) @@ -2143,7 +2143,7 @@ SUBROUTINE InflowWind_IO_PackPoints_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 - Int_BufSz = Int_BufSz + 1 ! Dummy + Int_BufSz = Int_BufSz + 1 ! NumWindPoints IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -2171,7 +2171,7 @@ SUBROUTINE InflowWind_IO_PackPoints_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, I Db_Xferred = 1 Int_Xferred = 1 - IntKiBuf(Int_Xferred) = InData%Dummy + IntKiBuf(Int_Xferred) = InData%NumWindPoints Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_IO_PackPoints_InitInputType @@ -2201,7 +2201,7 @@ SUBROUTINE InflowWind_IO_UnPackPoints_InitInputType( ReKiBuf, DbKiBuf, IntKiBuf, Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 - OutData%Dummy = IntKiBuf(Int_Xferred) + OutData%NumWindPoints = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 END SUBROUTINE InflowWind_IO_UnPackPoints_InitInputType diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90 index dcbc68b26a..4b4e381420 100644 --- a/modules/inflowwind/src/InflowWind_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Subs.f90 @@ -975,10 +975,10 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM p%WindType = InputFileData%WindType ! Convert the PropagationDir to radians and store this. For simplicity, we will shift it to be between -pi and pi - m%FlowField%PropagationDir = D2R * InputFileData%PropagationDir - CALL MPi2Pi( m%FlowField%PropagationDir ) ! Shift if necessary so that the value is between -pi and pi + p%FlowField%PropagationDir = D2R * InputFileData%PropagationDir + CALL MPi2Pi( p%FlowField%PropagationDir ) ! Shift if necessary so that the value is between -pi and pi - m%FlowField%VFlowAngle = D2R * InputFileData%VFlowAngle + p%FlowField%VFlowAngle = D2R * InputFileData%VFlowAngle ! Copy over the list of wind coordinates. Move the arrays to the new one. p%NWindVel = InputFileData%NWindVel @@ -1115,15 +1115,15 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM ! Create the rotation matrices -- rotate from XYZ to X'Y'Z' (wind aligned along X) coordinates ! Included in this rotation is the wind upflow (inclination) angle (rotation about Y axis) - m%FlowField%RotToWind(1,:) = [ COS(-m%FlowField%VFlowAngle) * COS(-m%FlowField%PropagationDir), & - COS(-m%FlowField%VFlowAngle) * SIN(-m%FlowField%PropagationDir), & - -SIN(-m%FlowField%VFlowAngle) ] - m%FlowField%RotToWind(2,:) = [ -SIN(-m%FlowField%PropagationDir), & - COS(-m%FlowField%PropagationDir), & + p%FlowField%RotToWind(1,:) = [ COS(-p%FlowField%VFlowAngle) * COS(-p%FlowField%PropagationDir), & + COS(-p%FlowField%VFlowAngle) * SIN(-p%FlowField%PropagationDir), & + -SIN(-p%FlowField%VFlowAngle) ] + p%FlowField%RotToWind(2,:) = [ -SIN(-p%FlowField%PropagationDir), & + COS(-p%FlowField%PropagationDir), & 0.0_ReKi ] - m%FlowField%RotToWind(3,:) = [ SIN(-m%FlowField%VFlowAngle) * COS(-m%FlowField%PropagationDir), & - SIN(-m%FlowField%VFlowAngle) * SIN(-m%FlowField%PropagationDir), & - COS(-m%FlowField%VFlowAngle) ] + p%FlowField%RotToWind(3,:) = [ SIN(-p%FlowField%VFlowAngle) * COS(-p%FlowField%PropagationDir), & + SIN(-p%FlowField%VFlowAngle) * SIN(-p%FlowField%PropagationDir), & + COS(-p%FlowField%VFlowAngle) ] ! Create the rotation matrices -- rotate from X'Y'Z' (wind aligned along X) to global XYZ coordinates: this is the same as a ! rotation about the (positive) upflow angle multiplied by a rotation about the (positive) wind direction: @@ -1131,7 +1131,7 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM ! loal wind = R( -p%VFlowAngle) * R (-p%PropagationDir) [global wind] ! = R^T(p%VFlowAngle) * R^T(p%PropagationDir) [global wind] ! = (R(p%PropagationDir) * R(p%VFlowAngle))^T [global wind] - m%FlowField%RotFromWind = TRANSPOSE(m%FlowField%RotToWind) + p%FlowField%RotFromWind = TRANSPOSE(p%FlowField%RotToWind) ! Create the array used for holding the rotated list of WindViXYZ coordinates in the wind reference frame, and populate it CALL AllocAry( p%WindViXYZprime, 3, p%NWindVel, 'Array for WindViXYZ coordinates in the wind reference frame', & @@ -1144,10 +1144,10 @@ SUBROUTINE InflowWind_SetParameters( InitInp, InputFileData, p, m, ErrStat, ErrM p%WindViXYZprime = 0.0_ReKi ! set the output points. Note rotation is about the hub height at [0 0 H]. See InflowWind_SetParameters for details. DO I = 1,p%NWindVel - p%WindViXYZprime(:,I) = MATMUL( m%FlowField%RotToWind, (p%WindViXYZ(:,I) - p%RefPosition )) + p%RefPosition + p%WindViXYZprime(:,I) = MATMUL( p%FlowField%RotToWind, (p%WindViXYZ(:,I) - p%RefPosition )) + p%RefPosition ENDDO - m%FlowField%RotateWindBox = .not. (EqualRealNos (m%FlowField%PropagationDir, 0.0_ReKi) .AND. EqualRealNos (m%FlowField%VFlowAngle, 0.0_ReKi)) + p%FlowField%RotateWindBox = .not. (EqualRealNos (p%FlowField%PropagationDir, 0.0_ReKi) .AND. EqualRealNos (p%FlowField%VFlowAngle, 0.0_ReKi)) END SUBROUTINE InflowWind_SetParameters @@ -1637,14 +1637,14 @@ SUBROUTINE CalculateOutput( Time, InputData, p, x, xd, z, OtherStates, y, m, Fil ErrMsg = "" ! Get velocities and accelerations for the given positions - CALL IfW_FlowField_GetVelAcc(m%FlowField, 0, Time, InputData%PositionXYZ, & + CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, InputData%PositionXYZ, & y%VelocityUVW, y%AccelUVW, TmpErrStat, TmpErrMsg) CALL SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName ) IF ( ErrStat >= AbortErrLev) RETURN ! Get velocities and accelerations for OutList variables, no error check IF ( p%NWindVel >= 1_IntKi .AND. FillWrOut ) THEN - CALL IfW_FlowField_GetVelAcc(m%FlowField, 0, Time, p%WindViXYZ, & + CALL IfW_FlowField_GetVelAcc(p%FlowField, 0, Time, p%WindViXYZ, & m%WindViUVW, m%WindAiUVW, TmpErrStat, TmpErrMsg) ENDIF diff --git a/modules/inflowwind/src/InflowWind_Types.f90 b/modules/inflowwind/src/InflowWind_Types.f90 index 0b8f1780ee..67d5089934 100644 --- a/modules/inflowwind/src/InflowWind_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Types.f90 @@ -44,7 +44,7 @@ MODULE InflowWind_Types INTEGER(IntKi), PUBLIC, PARAMETER :: User_WindNumber = 6 ! User defined wind. [-] INTEGER(IntKi), PUBLIC, PARAMETER :: BladedFF_Shr_WindNumber = 7 ! Native Bladed binary full-field file. [-] INTEGER(IntKi), PUBLIC, PARAMETER :: FDext_WindNumber = 8 ! 4D wind from external souce (i.e., FAST.Farm). [-] - INTEGER(IntKi), PUBLIC, PARAMETER :: Point_WindNumber = 9 ! 4D wind from external souce (i.e., FAST.Farm). [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: Point_WindNumber = 9 ! 1D wind components from ExtInflow [-] INTEGER(IntKi), PUBLIC, PARAMETER :: Highest_WindNumber = 9 ! Highest wind number supported. [-] INTEGER(IntKi), PUBLIC, PARAMETER :: IfW_NumPtsAvg = 144 ! Number of points averaged for rotor-average wind speed [-] ! ========= InflowWind_InputFile ======= @@ -138,6 +138,7 @@ MODULE InflowWind_Types REAL(DbKi) :: DT !< Time step for cont. state integration & disc. state update [seconds] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViXYZprime !< List of XYZ coordinates for velocity measurements, translated to the wind coordinate system (prime coordinates). This equals MATMUL( RotToWind, ParamData%WindViXYZ ) [meters] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViXYZ !< List of XYZ coordinates for wind velocity measurements, 3xNWindVel [meters] + TYPE(FlowFieldType) :: FlowField !< Parameters from Full-Field [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PositionAvg !< (non-rotated) positions of points used for averaging wind speed [meters] REAL(ReKi) :: ReferenceHeight !< Height of the wind turbine [meters] REAL(ReKi) , DIMENSION(1:3) :: RefPosition !< Reference position (point where box is rotated) [meters] @@ -192,7 +193,6 @@ MODULE InflowWind_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AllOuts !< An array holding the value of all of the calculated (not only selected) output channels [see OutListParameters.xlsx spreadsheet] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindViUVW !< List of UVW velocities for wind velocity measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ [meters/second] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WindAiUVW !< List of UVW accelerations for wind acceleration measurements, 3xNWindVel. corresponds to ParamData%WindViXYZ [m/s^2] - TYPE(FlowFieldType) :: FlowField !< Parameters from Full-Field [-] TYPE(InflowWind_InputType) :: u_Avg !< inputs for computing rotor-averaged values [-] TYPE(InflowWind_OutputType) :: y_Avg !< outputs for computing rotor-averaged values [-] TYPE(InflowWind_InputType) :: u_Hub !< inputs for computing hub values [-] @@ -2393,6 +2393,9 @@ SUBROUTINE InflowWind_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, END IF DstParamData%WindViXYZ = SrcParamData%WindViXYZ ENDIF + CALL IfW_FlowField_Copyflowfieldtype( SrcParamData%FlowField, DstParamData%FlowField, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN IF (ALLOCATED(SrcParamData%PositionAvg)) THEN i1_l = LBOUND(SrcParamData%PositionAvg,1) i1_u = UBOUND(SrcParamData%PositionAvg,1) @@ -2474,6 +2477,8 @@ SUBROUTINE InflowWind_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointe IF (ALLOCATED(ParamData%WindViXYZ)) THEN DEALLOCATE(ParamData%WindViXYZ) ENDIF + CALL IfW_FlowField_Destroyflowfieldtype( ParamData%FlowField, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ALLOCATED(ParamData%PositionAvg)) THEN DEALLOCATE(ParamData%PositionAvg) ENDIF @@ -2539,6 +2544,24 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + 2*2 ! WindViXYZ upper/lower bounds for each dimension Re_BufSz = Re_BufSz + SIZE(InData%WindViXYZ) ! WindViXYZ END IF + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! FlowField: size of buffers for each call to pack subtype + CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, .TRUE. ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! FlowField + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! FlowField + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! FlowField + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF Int_BufSz = Int_BufSz + 1 ! PositionAvg allocated yes/no IF ( ALLOCATED(InData%PositionAvg) ) THEN Int_BufSz = Int_BufSz + 2*2 ! PositionAvg upper/lower bounds for each dimension @@ -2551,7 +2574,6 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_BufSz = Int_BufSz + 1 ! OutParam allocated yes/no IF ( ALLOCATED(InData%OutParam) ) THEN Int_BufSz = Int_BufSz + 2*1 ! OutParam upper/lower bounds for each dimension - ! Allocate buffers for subtypes, if any (we'll get sizes from these) DO i1 = LBOUND(InData%OutParam,1), UBOUND(InData%OutParam,1) Int_BufSz = Int_BufSz + 3 ! OutParam: size of buffers for each call to pack subtype CALL NWTC_Library_Packoutparmtype( Re_Buf, Db_Buf, Int_Buf, InData%OutParam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! OutParam @@ -2670,6 +2692,34 @@ SUBROUTINE InflowWind_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END DO END DO END IF + CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, OnlySize ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF IF ( .NOT. ALLOCATED(InData%PositionAvg) ) THEN IntKiBuf( Int_Xferred ) = 0 Int_Xferred = Int_Xferred + 1 @@ -2875,6 +2925,46 @@ SUBROUTINE InflowWind_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, END DO END DO END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL IfW_FlowField_Unpackflowfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%FlowField, ErrStat2, ErrMsg2 ) ! FlowField + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! PositionAvg not allocated Int_Xferred = Int_Xferred + 1 ELSE @@ -4391,9 +4481,6 @@ SUBROUTINE InflowWind_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, Err END IF DstMiscData%WindAiUVW = SrcMiscData%WindAiUVW ENDIF - CALL IfW_FlowField_Copyflowfieldtype( SrcMiscData%FlowField, DstMiscData%FlowField, CtrlCode, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) - IF (ErrStat>=AbortErrLev) RETURN CALL InflowWind_CopyInput( SrcMiscData%u_Avg, DstMiscData%u_Avg, CtrlCode, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) IF (ErrStat>=AbortErrLev) RETURN @@ -4438,8 +4525,6 @@ SUBROUTINE InflowWind_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers IF (ALLOCATED(MiscData%WindAiUVW)) THEN DEALLOCATE(MiscData%WindAiUVW) ENDIF - CALL IfW_FlowField_Destroyflowfieldtype( MiscData%FlowField, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL InflowWind_DestroyInput( MiscData%u_Avg, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) CALL InflowWind_DestroyOutput( MiscData%y_Avg, ErrStat2, ErrMsg2, DEALLOCATEpointers_local ) @@ -4501,23 +4586,6 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err Re_BufSz = Re_BufSz + SIZE(InData%WindAiUVW) ! WindAiUVW END IF ! Allocate buffers for subtypes, if any (we'll get sizes from these) - Int_BufSz = Int_BufSz + 3 ! FlowField: size of buffers for each call to pack subtype - CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, .TRUE. ) ! FlowField - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN ! FlowField - Re_BufSz = Re_BufSz + SIZE( Re_Buf ) - DEALLOCATE(Re_Buf) - END IF - IF(ALLOCATED(Db_Buf)) THEN ! FlowField - Db_BufSz = Db_BufSz + SIZE( Db_Buf ) - DEALLOCATE(Db_Buf) - END IF - IF(ALLOCATED(Int_Buf)) THEN ! FlowField - Int_BufSz = Int_BufSz + SIZE( Int_Buf ) - DEALLOCATE(Int_Buf) - END IF Int_BufSz = Int_BufSz + 3 ! u_Avg: size of buffers for each call to pack subtype CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Avg, ErrStat2, ErrMsg2, .TRUE. ) ! u_Avg CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -4668,34 +4736,6 @@ SUBROUTINE InflowWind_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Err END DO END DO END IF - CALL IfW_FlowField_Packflowfieldtype( Re_Buf, Db_Buf, Int_Buf, InData%FlowField, ErrStat2, ErrMsg2, OnlySize ) ! FlowField - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf - Re_Xferred = Re_Xferred + SIZE(Re_Buf) - DEALLOCATE(Re_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Db_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf - Db_Xferred = Db_Xferred + SIZE(Db_Buf) - DEALLOCATE(Db_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF - IF(ALLOCATED(Int_Buf)) THEN - IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 - IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf - Int_Xferred = Int_Xferred + SIZE(Int_Buf) - DEALLOCATE(Int_Buf) - ELSE - IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 - ENDIF CALL InflowWind_PackInput( Re_Buf, Db_Buf, Int_Buf, InData%u_Avg, ErrStat2, ErrMsg2, OnlySize ) ! u_Avg CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) IF (ErrStat >= AbortErrLev) RETURN @@ -4902,46 +4942,6 @@ SUBROUTINE InflowWind_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, END DO END DO END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) - Re_Xferred = Re_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) - Db_Xferred = Db_Xferred + Buf_size - END IF - Buf_size=IntKiBuf( Int_Xferred ) - Int_Xferred = Int_Xferred + 1 - IF(Buf_size > 0) THEN - ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) - IF (ErrStat2 /= 0) THEN - CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) - RETURN - END IF - Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) - Int_Xferred = Int_Xferred + Buf_size - END IF - CALL IfW_FlowField_Unpackflowfieldtype( Re_Buf, Db_Buf, Int_Buf, OutData%FlowField, ErrStat2, ErrMsg2 ) ! FlowField - CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF (ErrStat >= AbortErrLev) RETURN - - IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) - IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) - IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) Buf_size=IntKiBuf( Int_Xferred ) Int_Xferred = Int_Xferred + 1 IF(Buf_size > 0) THEN diff --git a/modules/inflowwind/tests/test_uniform_wind.F90 b/modules/inflowwind/tests/test_uniform_wind.F90 index b20e86b139..13421e5da4 100644 --- a/modules/inflowwind/tests/test_uniform_wind.F90 +++ b/modules/inflowwind/tests/test_uniform_wind.F90 @@ -90,13 +90,13 @@ subroutine test_uniform_wind_direct_data() ! Results @assertEqual(0, TmpErrStat, message='Error message: '//trim(TmpErrMsg)//NewLine//'ErrStat: ') - @assertEqual(0.0, m%FlowField%Uniform%Time(1)) - @assertEqual(0.1, m%FlowField%Uniform%Time(2)) - @assertEqual(999.9, m%FlowField%Uniform%Time(3)) + @assertEqual(0.0, p%FlowField%Uniform%Time(1)) + @assertEqual(0.1, p%FlowField%Uniform%Time(2)) + @assertEqual(999.9, p%FlowField%Uniform%Time(3)) - @assertEqual(12.0, m%FlowField%Uniform%VelH(1)) - @assertEqual(12.0, m%FlowField%Uniform%VelH(2)) - @assertEqual(12.0, m%FlowField%Uniform%VelH(3)) + @assertEqual(12.0, p%FlowField%Uniform%VelH(1)) + @assertEqual(12.0, p%FlowField%Uniform%VelH(2)) + @assertEqual(12.0, p%FlowField%Uniform%VelH(3)) end subroutine From 9531399510d07ba775942c72132b1cbd19bdfad0 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 19:24:10 +0000 Subject: [PATCH 47/51] IfW: added BoxExceed to driver input, moved accel Needed to have BoxExceed in the driver input file for regression testing Added acceleration to Points.Velocity.dat output file for regression testing. --- .../examples/inflowwind_driver_example.inp | 1 + modules/inflowwind/src/InflowWind_Driver.f90 | 44 ++++------------ .../inflowwind/src/InflowWind_Driver_Subs.f90 | 51 ++++++++++++------- .../src/InflowWind_Driver_Types.f90 | 1 - reg_tests/CTestList.cmake | 2 + reg_tests/executeInflowwindRegressionCase.py | 3 +- reg_tests/r-test | 2 +- 7 files changed, 48 insertions(+), 56 deletions(-) diff --git a/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp b/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp index 396035d1b9..ada6a15427 100644 --- a/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp +++ b/docs/source/user/inflowwind/examples/inflowwind_driver_example.inp @@ -14,6 +14,7 @@ InflowWind driver input file. DEFAULT DT -- timestep size for driver to take (s, or DEFAULT for what the file contains) t Summary -- Summarize the data extents in the windfile (flag) t SummaryFile -- Write summary to file (.dvr.sum) (flag) + f BoxExceedAllow -- Allow point sampling outside grid ---- Points file input (output given as POINTSFILENAME.Velocity.dat) -------- f PointsFile -- read in a list of output points from a file (flag) "Test005.txt" PointsFileName -- name of points file (-) (comma separated x,y,z coordinates, # symbol for comments) diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90 index 2456f29d4d..77beb83a58 100644 --- a/modules/inflowwind/src/InflowWind_Driver.f90 +++ b/modules/inflowwind/src/InflowWind_Driver.f90 @@ -276,15 +276,6 @@ PROGRAM InflowWind_Driver INQUIRE( file=TRIM(Settings%PointsVelOutput%Name), exist=TempFileExist ) IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsVelOutput%Name)) - ! If wind accelerations were requested, create/open file, print overwrite warning of applicable - IF (SettingsFlags%OutputAccel) then - CALL GetRoot( Settings%PointsFileName, Settings%PointsAccOutput%Name ) - Settings%PointsAccOutput%Name = TRIM(Settings%PointsAccOutput%Name)//'.Acceleration.dat' - CALL WrScr(NewLine//"Results output to '"//TRIM(Settings%PointsAccOutput%Name)//"'.") - INQUIRE( file=TRIM(Settings%PointsAccOutput%Name), exist=TempFileExist ) - IF ( TempFileExist .eqv. .TRUE. ) CALL ProgWarn( "Overwriting file "//TRIM(Settings%PointsAccOutput%Name)) - END IF - ENDIF @@ -649,23 +640,16 @@ PROGRAM InflowWind_Driver ENDIF ! Now create the velocity output file. Write header information - CALL PointData_OutputWrite( Settings%PointsVelOutput, Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%VelocityUVW, TimeNow, .true., ErrStat, ErrMsg ) + CALL PointData_OutputWrite( Settings%PointsVelOutput, Settings, & + InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, & + InflowWind_y2%AccelUVW, & + TimeNow, .true., ErrStat, ErrMsg ) IF ( ErrStat /= ErrID_None ) THEN CALL DriverCleanup() CALL ProgAbort( 'Error creating point data velocity output file: '//trim(Settings%PointsVelOutput%Name) ) ENDIF - ! If point acceleration calculate was requested, create file and write header - IF ( SettingsFlags%OutputAccel ) THEN - CALL PointData_OutputWrite( Settings%PointsAccOutput, Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%AccelUVW, TimeNow, .false., ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) THEN - CALL DriverCleanup() - CALL ProgAbort( 'Error creating point data acceleration output file: '//trim(Settings%PointsAccOutput%Name) ) - ENDIF - END IF - ENDIF ! FFT setup @@ -794,22 +778,15 @@ PROGRAM InflowWind_Driver ENDIF ! Output the Points results for this timestep - CALL PointData_OutputWrite( Settings%PointsVelOutput, Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%VelocityUVW, TimeNow, .true., ErrStat, ErrMsg ) + CALL PointData_OutputWrite( Settings%PointsVelOutput, Settings, & + InflowWind_u2%PositionXYZ, & + InflowWind_y2%VelocityUVW, & + InflowWind_y2%AccelUVW, & + TimeNow, .true., ErrStat, ErrMsg ) IF ( ErrStat >= AbortErrLev ) THEN CALL DriverCleanup() CALL ProgAbort( ErrMsg ) END IF - - ! If acceleration at points was requested, output values - IF ( SettingsFlags%OutputAccel ) then - CALL PointData_OutputWrite( Settings%PointsAccOutput, Settings, InflowWind_u2%PositionXYZ, & - InflowWind_y2%AccelUVW, TimeNow, .false., ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL DriverCleanup() - CALL ProgAbort( ErrMsg ) - END IF - END IF END IF @@ -959,7 +936,6 @@ SUBROUTINE DriverCleanup() ! Close output files that may have been opened if (Settings%WindGridOutput%Unit > -1_IntKi ) CLOSE( Settings%WindGridOutput%Unit ) if (Settings%PointsVelOutput%Unit > -1_IntKi ) CLOSE( Settings%PointsVelOutput%Unit ) - if (Settings%PointsAccOutput%Unit > -1_IntKi ) CLOSE( Settings%PointsAccOutput%Unit ) if (Settings%FFTOutput%Unit > -1_IntKi ) CLOSE( Settings%FFTOutput%Unit ) ! Find out how long this actually took diff --git a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 index 09b1e099ba..d7033445b2 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Subs.f90 @@ -994,7 +994,15 @@ SUBROUTINE ReadDvrIptFile( DvrFileName, DvrFlags, DvrSettings, ProgInfo, ErrStat ! DvrFlags%SummaryFile = .TRUE. ENDIF - + ! Flag to allow sampling outside grid + CALL ReadVar( UnIn, FileName,DvrFlags%BoxExceedAllowF,'BoxExceedAllow',' Allow point sampling outside grid', & + ErrStatTmp,ErrMsgTmp, UnEchoLocal ) + IF ( ErrStatTmp /= ErrID_None ) THEN + CALL SetErrStat(ErrID_Fatal,ErrMsgTmp,ErrStat,ErrMsg,RoutineName) + CALL CleanupEchoFile( EchoFileContents, UnEchoLocal ) + CLOSE( UnIn ) + RETURN + ENDIF #ifdef UNUSED_INPUTFILE_LINES !------------------------------------------------------------------------------------------------- @@ -2350,27 +2358,27 @@ SUBROUTINE WindGridVel_OutputWrite (OutFile, Settings, GridXYZ, GridVel, TIME, E END SUBROUTINE WindGridVel_OutputWrite -SUBROUTINE PointData_OutputWrite (OutFile, Settings, GridXYZ, GridDat, TIME, IsVel, ErrStat, ErrMsg) +SUBROUTINE PointData_OutputWrite (OutFile, Settings, GridXYZ, GridVel, GridAcc, TIME, IsVel, ErrStat, ErrMsg) TYPE(OutputFile), INTENT(INOUT) :: OutFile TYPE(IfWDriver_Settings), INTENT(IN ) :: Settings !< Settings for IfW driver REAL(ReKi), INTENT(IN ) :: GridXYZ(:,:) !< The position grid passed in - REAL(ReKi), INTENT(IN ) :: GridDat(:,:) !< The velocity grid passed in + REAL(ReKi), INTENT(IN ) :: GridVel(:,:) !< The velocity grid passed in + REAL(ReKi), allocatable, INTENT(IN ) :: GridAcc(:,:) !< The acceleration grid passed in REAL(DbKi), INTENT(IN ) :: TIME !< The current time LOGICAL, INTENT(IN ) :: IsVel !< Is this velocity output INTEGER(IntKi), INTENT( OUT) :: ErrStat !< returns a non-zero value when an error occurs CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None - ! Temporary local variables INTEGER(IntKi) :: ErrStatTmp !< Temporary variable for the status of error message CHARACTER(2048) :: ErrMsgTmp !< Temporary variable for the error message - INTEGER(IntKi) :: I !< Generic counter + INTEGER(IntKi) :: I, J !< Generic counter CHARACTER(61) :: NameUnitFmt !< Format specifier for the output file for channel names and units CHARACTER(61) :: PointsVelFmt !< Format specifier for the output file for wind point location and velocity - NameUnitFmt = "( 7(A16, 3X) )" - PointsVelFmt = "( 7(F16.8, 3X) )" + NameUnitFmt = "( *(A16,3X) )" + PointsVelFmt = "( *(F16.8,3X) )" ErrMsg = '' ErrStat = ErrID_None @@ -2391,12 +2399,12 @@ SUBROUTINE PointData_OutputWrite (OutFile, Settings, GridXYZ, GridDat, TIME, IsV ! Write header section WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file was generated by '//TRIM(GetNVD(Settings%ProgInfo))// & ' on '//CurDate()//' at '//CurTime()//'.' - if (IsVel) then - WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wind velocity at the '// & + if (allocated(GridAcc)) then + WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wind velocity and acceleration at the '// & TRIM(Num2LStr(SIZE(GridXYZ,DIM=2)))//' points specified in the '// & 'file '//TRIM(Settings%PointsFileName)//'.' else - WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wind acceleration at the '// & + WRITE( OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '## This file contains the wind velocity at the '// & TRIM(Num2LStr(SIZE(GridXYZ,DIM=2)))//' points specified in the '// & 'file '//TRIM(Settings%PointsFileName)//'.' end if @@ -2404,19 +2412,24 @@ SUBROUTINE PointData_OutputWrite (OutFile, Settings, GridXYZ, GridDat, TIME, IsV WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' WRITE (OutFile%Unit,'(A)', IOSTAT=ErrStatTmp ) '# ' - WRITE (OutFile%Unit, NameUnitFmt, IOSTAT=ErrStatTmp ) 'T', 'X', 'Y', 'Z', 'U', 'V', 'W' - if (IsVel) then + if (allocated(GridAcc)) then + WRITE (OutFile%Unit, NameUnitFmt, IOSTAT=ErrStatTmp ) 'T', 'X', 'Y', 'Z', 'U', 'V', 'W', 'UA', 'VA', 'WA' + WRITE (OutFile%Unit, NameUnitFmt, IOSTAT=ErrStatTmp ) '(s)', '(m)', '(m)', '(m)', '(m/s)', '(m/s)', '(m/s)', '(m/s/s)', '(m/s/s)', '(m/s/s)' + else + WRITE (OutFile%Unit, NameUnitFmt, IOSTAT=ErrStatTmp ) 'T', 'X', 'Y', 'Z', 'U', 'V', 'W' WRITE (OutFile%Unit, NameUnitFmt, IOSTAT=ErrStatTmp ) '(s)', '(m)', '(m)', '(m)', '(m/s)', '(m/s)', '(m/s)' - else - WRITE (OutFile%Unit, NameUnitFmt, IOSTAT=ErrStatTmp ) '(s)', '(m)', '(m)', '(m)', '(m/s/s)', '(m/s/s)', '(m/s/s)' end if ELSE - DO I = 1,SIZE(GridXYZ,DIM=2) - - WRITE (OutFile%Unit, PointsVelFmt, IOSTAT=ErrStatTmp ) TIME, GridXYZ(1,I), GridXYZ(2,I), GridXYZ(3,I), GridDat(1,I), GridDat(2,I), GridDat(3,I) - - ENDDO + if (allocated(GridAcc)) then + DO I = 1,SIZE(GridXYZ,DIM=2) + WRITE (OutFile%Unit, PointsVelFmt, IOSTAT=ErrStatTmp) TIME, (GridXYZ(J,I),j=1,3), (GridVel(J,I),j=1,3), (GridAcc(J,I),j=1,3) + ENDDO + else + DO I = 1,SIZE(GridXYZ,DIM=2) + WRITE (OutFile%Unit, PointsVelFmt, IOSTAT=ErrStatTmp) TIME, (GridXYZ(J,I),j=1,3), (GridVel(J,I),j=1,3) + ENDDO + end if ENDIF diff --git a/modules/inflowwind/src/InflowWind_Driver_Types.f90 b/modules/inflowwind/src/InflowWind_Driver_Types.f90 index d2584a9b2a..669303cf60 100644 --- a/modules/inflowwind/src/InflowWind_Driver_Types.f90 +++ b/modules/inflowwind/src/InflowWind_Driver_Types.f90 @@ -104,7 +104,6 @@ MODULE InflowWind_Driver_Types TYPE(OutputFile) :: WindGridOutput TYPE(OutputFile) :: FFTOutput TYPE(OutputFile) :: PointsVelOutput - TYPE(OutputFile) :: PointsAccOutput END TYPE IfWDriver_Settings diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake index 0bea1964e7..54fe6af445 100644 --- a/reg_tests/CTestList.cmake +++ b/reg_tests/CTestList.cmake @@ -381,6 +381,8 @@ sd_regression("SD_AnsysComp3_PinBeamCable" "subdyn;offshore") # InflowWind regression tests ifw_regression("ifw_turbsimff" "inflowwind") +ifw_regression("ifw_BoxExceed" "inflowwind") +ifw_regression("ifw_BoxExceedTwr" "inflowwind") # Py-InflowWind regression tests py_ifw_regression("py_ifw_turbsimff" "inflowwind;python") diff --git a/reg_tests/executeInflowwindRegressionCase.py b/reg_tests/executeInflowwindRegressionCase.py index d06b802e12..096ebe291c 100644 --- a/reg_tests/executeInflowwindRegressionCase.py +++ b/reg_tests/executeInflowwindRegressionCase.py @@ -92,7 +92,8 @@ # and initialize it with input files for all test cases if not os.path.isdir(testBuildDirectory): os.makedirs(testBuildDirectory) - for file in glob.glob(os.path.join(inputsDirectory,"*inp")): + for file in (glob.glob(os.path.join(inputsDirectory,"*inp")) + + glob.glob(os.path.join(inputsDirectory,"*bts"))): filename = file.split(os.path.sep)[-1] shutil.copy(os.path.join(inputsDirectory,filename), os.path.join(testBuildDirectory,filename)) diff --git a/reg_tests/r-test b/reg_tests/r-test index d5425d6f55..3a61da3eec 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit d5425d6f55e1ec1108c3a5b0cdd2e5db34d57029 +Subproject commit 3a61da3eec9233b308604c7dc055f06f118d5126 From 44214496669bb1ef142c96e06a56505ffd57a400 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 19:40:23 +0000 Subject: [PATCH 48/51] Updated Visual Studio Files --- vs-build/AeroDyn/AeroDyn_Driver.vfproj | 235 ++-------------- .../AeroDyn_Inflow_c_binding.vfproj | 235 ++-------------- vs-build/FASTlib/FASTlib.vfproj | 258 +++--------------- vs-build/InflowWind/InflowWind_driver.vfproj | 187 ++----------- .../InflowWind_c_binding.vfproj | 179 ++---------- vs-build/RunRegistry.bat | 9 +- 6 files changed, 140 insertions(+), 963 deletions(-) diff --git a/vs-build/AeroDyn/AeroDyn_Driver.vfproj b/vs-build/AeroDyn/AeroDyn_Driver.vfproj index 51fe9aa8d6..6ec860c422 100644 --- a/vs-build/AeroDyn/AeroDyn_Driver.vfproj +++ b/vs-build/AeroDyn/AeroDyn_Driver.vfproj @@ -376,32 +376,32 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -410,202 +410,32 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -682,13 +512,8 @@ - - - - - - - + + diff --git a/vs-build/AeroDyn_Inflow_c_binding/AeroDyn_Inflow_c_binding.vfproj b/vs-build/AeroDyn_Inflow_c_binding/AeroDyn_Inflow_c_binding.vfproj index 06eca6093b..f2bb6a0f86 100644 --- a/vs-build/AeroDyn_Inflow_c_binding/AeroDyn_Inflow_c_binding.vfproj +++ b/vs-build/AeroDyn_Inflow_c_binding/AeroDyn_Inflow_c_binding.vfproj @@ -442,32 +442,32 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -476,202 +476,32 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -748,13 +578,8 @@ - - - - - - - + + diff --git a/vs-build/FASTlib/FASTlib.vfproj b/vs-build/FASTlib/FASTlib.vfproj index 925cf1d7ac..bf482bb08e 100644 --- a/vs-build/FASTlib/FASTlib.vfproj +++ b/vs-build/FASTlib/FASTlib.vfproj @@ -1217,36 +1217,36 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -1255,226 +1255,36 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -1559,8 +1369,8 @@ - - + + diff --git a/vs-build/InflowWind/InflowWind_driver.vfproj b/vs-build/InflowWind/InflowWind_driver.vfproj index 7ef4ac242d..9b69cee844 100644 --- a/vs-build/InflowWind/InflowWind_driver.vfproj +++ b/vs-build/InflowWind/InflowWind_driver.vfproj @@ -90,131 +90,41 @@ - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -251,62 +161,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/vs-build/InflowWind_c_binding/InflowWind_c_binding.vfproj b/vs-build/InflowWind_c_binding/InflowWind_c_binding.vfproj index 09ec865b54..97c406319a 100644 --- a/vs-build/InflowWind_c_binding/InflowWind_c_binding.vfproj +++ b/vs-build/InflowWind_c_binding/InflowWind_c_binding.vfproj @@ -90,131 +90,41 @@ - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -251,54 +161,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/vs-build/RunRegistry.bat b/vs-build/RunRegistry.bat index 5a5034fc90..d3dfcbe2f7 100644 --- a/vs-build/RunRegistry.bat +++ b/vs-build/RunRegistry.bat @@ -118,13 +118,8 @@ SET Output_Loc=%CURR_LOC% %REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" GOTO checkError -:IfW_TSFFWind -:IfW_HAWCWind -:IfW_BladedFFWind -:IfW_UserWind -:IfW_4Dext -:IfW_FFWind_Base -:IfW_UniformWind +:IfW_FlowField +:InflowWind_IO SET CURR_LOC=%IfW_Loc% SET Output_Loc=%CURR_LOC% %REGISTRY% "%CURR_LOC%\%ModuleName%.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -noextrap -O "%Output_Loc%" From 47255466e28914ab397f44e53563c08bfa9ac06a Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 16:33:45 -0400 Subject: [PATCH 49/51] Fix Visual Studio project files --- vs-build/FASTlib/FASTlib.vfproj | 5 ----- vs-build/InflowWind/InflowWind_driver.vfproj | 8 ++++++++ vs-build/MAPlib/MAP_dll.vcxproj | 12 ++++++------ vs-build/Registry/FAST_Registry.vcxproj | 11 ++++++----- vs-build/SubDyn/SubDyn.sln | 15 +++++++++++++-- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/vs-build/FASTlib/FASTlib.vfproj b/vs-build/FASTlib/FASTlib.vfproj index bf482bb08e..438848eb42 100644 --- a/vs-build/FASTlib/FASTlib.vfproj +++ b/vs-build/FASTlib/FASTlib.vfproj @@ -1371,11 +1371,6 @@ - - - - - diff --git a/vs-build/InflowWind/InflowWind_driver.vfproj b/vs-build/InflowWind/InflowWind_driver.vfproj index 9b69cee844..267e49a877 100644 --- a/vs-build/InflowWind/InflowWind_driver.vfproj +++ b/vs-build/InflowWind/InflowWind_driver.vfproj @@ -164,6 +164,14 @@ + + + + + + + + diff --git a/vs-build/MAPlib/MAP_dll.vcxproj b/vs-build/MAPlib/MAP_dll.vcxproj index 22373bf523..c3aef0510f 100644 --- a/vs-build/MAPlib/MAP_dll.vcxproj +++ b/vs-build/MAPlib/MAP_dll.vcxproj @@ -22,32 +22,32 @@ {BF86702A-CB17-4050-8AE9-078CDC5910D3} Win32Proj MAP_DLL - 8.1 + 10.0 StaticLibrary true - v140 + v143 Unicode StaticLibrary true - v140 + v143 Unicode StaticLibrary false - v140 + v143 true Unicode StaticLibrary false - v140 + v143 true Unicode @@ -214,4 +214,4 @@ - + \ No newline at end of file diff --git a/vs-build/Registry/FAST_Registry.vcxproj b/vs-build/Registry/FAST_Registry.vcxproj index 90fb08b2c6..9c5785a464 100644 --- a/vs-build/Registry/FAST_Registry.vcxproj +++ b/vs-build/Registry/FAST_Registry.vcxproj @@ -22,33 +22,34 @@ {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} Win32Proj FAST_Registry_c + 10.0 Application true Unicode - v140 + v143 Application true Unicode - v140 + v143 Application false true Unicode - v140 + v143 Application false true Unicode - v140 + v143 @@ -176,4 +177,4 @@ - + \ No newline at end of file diff --git a/vs-build/SubDyn/SubDyn.sln b/vs-build/SubDyn/SubDyn.sln index d497e8bd4a..817a37d8cd 100644 --- a/vs-build/SubDyn/SubDyn.sln +++ b/vs-build/SubDyn/SubDyn.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33205.214 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "SubDyn", "SubDyn.vfproj", "{815C302F-A93D-4C22-9329-717B085113C0}" ProjectSection(ProjectDependencies) = postProject @@ -38,10 +38,18 @@ Global {815C302F-A93D-4C22-9329-717B085113C0}.Release|Win32.Build.0 = Release|Win32 {815C302F-A93D-4C22-9329-717B085113C0}.Release|x64.ActiveCfg = Release|x64 {815C302F-A93D-4C22-9329-717B085113C0}.Release|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Debug|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Debug|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Debug|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Debug|x64 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 @@ -50,4 +58,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BC2FB3AB-97DC-4701-90B3-DDAF966FAB07} + EndGlobalSection EndGlobal From 931305511fe258665194a0f1bc62b14603b526cf Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Fri, 7 Apr 2023 19:55:13 +0000 Subject: [PATCH 50/51] IfW: initialized ErrStat/ErrMsg in IfW_Points_Init --- modules/inflowwind/src/InflowWind_IO.f90 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/inflowwind/src/InflowWind_IO.f90 b/modules/inflowwind/src/InflowWind_IO.f90 index c7f0b5471d..117cdb0d6d 100644 --- a/modules/inflowwind/src/InflowWind_IO.f90 +++ b/modules/inflowwind/src/InflowWind_IO.f90 @@ -59,6 +59,9 @@ subroutine IfW_Points_Init(InitInp, PF, ErrStat, ErrMsg) integer(IntKi) :: TmpErrStat character(ErrMsgLen) :: TmpErrMsg + ErrStat = ErrID_None + ErrMsg = "" + ! UVW components at points call AllocAry(PF%Vel, 3, InitInp%NumWindPoints, & 'Point Velocity Array', TmpErrStat, TmpErrMsg) From 168e2941ad6a707ed215ad7310a92afa2044a810 Mon Sep 17 00:00:00 2001 From: Derek Slaughter Date: Mon, 17 Apr 2023 21:18:51 +0000 Subject: [PATCH 51/51] Resolved inflowwind/CMakeLists.txt issue --- modules/inflowwind/CMakeLists.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/inflowwind/CMakeLists.txt b/modules/inflowwind/CMakeLists.txt index f3cda1aa9d..ec987c89c9 100644 --- a/modules/inflowwind/CMakeLists.txt +++ b/modules/inflowwind/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2016 National Renewable Energy Laboratory +# Copyright 2023 National Renewable Energy Laboratory # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ if (GENERATE_TYPES) generate_f90_types(src/InflowWind.txt ${CMAKE_CURRENT_LIST_DIR}/src/InflowWind_Types.f90) endif() -add_library(ifwlib +add_library(ifwlib_obj OBJECT src/IfW_FlowField_Types.f90 src/IfW_FlowField.f90 src/InflowWind_IO_Types.f90 @@ -30,10 +30,7 @@ add_library(ifwlib src/InflowWind_Types.f90 src/InflowWind.f90 src/Lidar_Types.f90 - src/Lidar.f90 -) - -add_library(ifwlib_obj OBJECT ${IFW_SOURCES}) + src/Lidar.f90) target_link_libraries(ifwlib_obj nwtclibs_obj) add_library(ifwlib $)